1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-19 06:05:56 +02:00

[218659] Make *EventManager, *ChangeManager thread-safe

This commit is contained in:
Martin Oberhuber 2008-02-12 17:53:07 +00:00
parent 8db8a6662e
commit 6392f63296
4 changed files with 179 additions and 87 deletions

View file

@ -1,5 +1,5 @@
/******************************************************************************** /********************************************************************************
* Copyright (c) 2002, 2007 IBM Corporation and others. All rights reserved. * Copyright (c) 2002, 2008 IBM Corporation and others. All rights reserved.
* This program and the accompanying materials are made available under the terms * This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is * of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html * available at http://www.eclipse.org/legal/epl-v10.html
@ -12,10 +12,12 @@
* *
* Contributors: * Contributors:
* Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core * Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core
* Martin Oberhuber (Wind River) - [218659] Make *EventManager, *ChangeManager thread-safe
********************************************************************************/ ********************************************************************************/
package org.eclipse.rse.internal.core.model; package org.eclipse.rse.internal.core.model;
import java.util.Vector; import java.util.ArrayList;
import java.util.List;
import org.eclipse.rse.core.events.ISystemModelChangeEvent; import org.eclipse.rse.core.events.ISystemModelChangeEvent;
import org.eclipse.rse.core.events.ISystemModelChangeListener; import org.eclipse.rse.core.events.ISystemModelChangeListener;
@ -26,7 +28,8 @@ import org.eclipse.rse.core.events.ISystemModelChangeListener;
*/ */
public class SystemModelChangeEventManager public class SystemModelChangeEventManager
{ {
private Vector listeners = new Vector(); private List listeners = new ArrayList();
private Object lockObject = new Object();
/** /**
* Constructor * Constructor
@ -36,34 +39,48 @@ public class SystemModelChangeEventManager
} }
/** /**
* Add a listener to list of listeners. If this object is already in * Add a listener to list of listeners.
* the list, this does nothing. * If this object is already in the list, this does nothing.
* @param l the listener to add
*/ */
public void addSystemModelChangeListener(ISystemModelChangeListener l) public void addSystemModelChangeListener(ISystemModelChangeListener l)
{ {
if (!listeners.contains(l)) synchronized(lockObject) {
listeners.addElement(l); if (!listeners.contains(l))
listeners.add(l);
}
} }
/** /**
* Remove a listener to list of listeners. If this object is not in * Remove a listener from the list of listeners.
* the list, this does nothing. * If this object is not in the list, this does nothing.
* @param l the listener to remove
*/ */
public void removeSystemModelChangeListener(ISystemModelChangeListener l) public void removeSystemModelChangeListener(ISystemModelChangeListener l)
{ {
if (listeners.contains(l)) synchronized(lockObject) {
listeners.removeElement(l); //Thread-safety: create a new List when removing, to avoid problems in notify()
listeners = new ArrayList(listeners);
listeners.remove(l);
}
} }
/** /**
* Notify all registered listeners of the given event * Notify all registered listeners of the given event.
* @param event the event to send
*/ */
public void notify(ISystemModelChangeEvent event) public void notify(ISystemModelChangeEvent event)
{ {
for (int idx=0; idx<listeners.size(); idx++) //Thread-safe event firing: fire events on a current snapshot of the list.
{ //If not done that way, and a thread removes a listener while event firing
ISystemModelChangeListener l = (ISystemModelChangeListener)listeners.elementAt(idx); //is in progress, an ArrayIndexOutOfBoundException might occur.
l.systemModelResourceChanged(event); List currentListeners;
synchronized(lockObject) {
currentListeners = listeners;
}
for (int idx=0; idx<currentListeners.size(); idx++) {
ISystemModelChangeListener l = (ISystemModelChangeListener)currentListeners.get(idx);
l.systemModelResourceChanged(event);
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************** /********************************************************************************
* Copyright (c) 2002, 2007 IBM Corporation and others. All rights reserved. * Copyright (c) 2002, 2008 IBM Corporation and others. All rights reserved.
* This program and the accompanying materials are made available under the terms * This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is * of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html * available at http://www.eclipse.org/legal/epl-v10.html
@ -12,10 +12,12 @@
* *
* Contributors: * Contributors:
* Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core * Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core
* Martin Oberhuber (Wind River) - [218659] Make *EventManager, *ChangeManager thread-safe
********************************************************************************/ ********************************************************************************/
package org.eclipse.rse.internal.core.model; package org.eclipse.rse.internal.core.model;
import java.util.Vector; import java.util.ArrayList;
import java.util.List;
import org.eclipse.rse.core.events.ISystemPreferenceChangeEvent; import org.eclipse.rse.core.events.ISystemPreferenceChangeEvent;
import org.eclipse.rse.core.events.ISystemPreferenceChangeListener; import org.eclipse.rse.core.events.ISystemPreferenceChangeListener;
@ -26,7 +28,8 @@ import org.eclipse.rse.core.events.ISystemPreferenceChangeListener;
*/ */
public class SystemPreferenceChangeManager public class SystemPreferenceChangeManager
{ {
private Vector listeners = new Vector(); private List listeners = new ArrayList();
private Object lockObject = new Object();
/** /**
* Constructor * Constructor
@ -36,33 +39,47 @@ public class SystemPreferenceChangeManager
} }
/** /**
* Add a listener to list of listeners. If this object is already in * Add a listener to list of listeners.
* the list, this does nothing. * If this object is already in the list, this does nothing.
* @param l the listener to add
*/ */
public void addSystemPreferenceChangeListener(ISystemPreferenceChangeListener l) public void addSystemPreferenceChangeListener(ISystemPreferenceChangeListener l)
{ {
if (!listeners.contains(l)) synchronized(lockObject) {
listeners.addElement(l); if (!listeners.contains(l))
listeners.add(l);
}
} }
/** /**
* Remove a listener to list of listeners. If this object is not in * Remove a listener from the list of listeners.
* the list, this does nothing. * If this object is not in the list, this does nothing.
* @param l the listener to remove
*/ */
public void removeSystemPreferenceChangeListener(ISystemPreferenceChangeListener l) public void removeSystemPreferenceChangeListener(ISystemPreferenceChangeListener l)
{ {
if (listeners.contains(l)) synchronized(lockObject) {
listeners.removeElement(l); //Thread-safety: create a new List when removing, to avoid problems in notify()
listeners = new ArrayList(listeners);
listeners.remove(l);
}
} }
/** /**
* Notify all registered listeners of the given event * Notify all registered listeners of the given event.
* @param event the event to send
*/ */
public void notify(ISystemPreferenceChangeEvent event) public void notify(ISystemPreferenceChangeEvent event)
{ {
for (int idx=0; idx<listeners.size(); idx++) //Thread-safe event firing: fire events on a current snapshot of the list.
{ //If not done that way, and a thread removes a listener while event firing
ISystemPreferenceChangeListener l = (ISystemPreferenceChangeListener)listeners.elementAt(idx); //is in progress, an ArrayIndexOutOfBoundException might occur.
List currentListeners;
synchronized(lockObject) {
currentListeners = listeners;
}
for (int idx=0; idx<currentListeners.size(); idx++) {
ISystemPreferenceChangeListener l = (ISystemPreferenceChangeListener)currentListeners.get(idx);
l.systemPreferenceChanged(event); l.systemPreferenceChanged(event);
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************** /********************************************************************************
* Copyright (c) 2002, 2007 IBM Corporation and others. All rights reserved. * Copyright (c) 2002, 2008 IBM Corporation and others. All rights reserved.
* This program and the accompanying materials are made available under the terms * This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is * of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html * available at http://www.eclipse.org/legal/epl-v10.html
@ -13,11 +13,10 @@
* Contributors: * Contributors:
* Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core * Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core
* David McKnight (IBM) - [207100] adding SystemRemoteChangeEventManager.isRegisteredSystemRemoteChangeListener * David McKnight (IBM) - [207100] adding SystemRemoteChangeEventManager.isRegisteredSystemRemoteChangeListener
* Martin Oberhuber (Wind River) - [218659] Make *EventManager, *ChangeManager thread-safe
********************************************************************************/ ********************************************************************************/
package org.eclipse.rse.internal.core.model; package org.eclipse.rse.internal.core.model;
import java.util.Vector;
import org.eclipse.rse.core.events.ISystemRemoteChangeEvent; import org.eclipse.rse.core.events.ISystemRemoteChangeEvent;
import org.eclipse.rse.core.events.ISystemRemoteChangeListener; import org.eclipse.rse.core.events.ISystemRemoteChangeListener;
@ -26,7 +25,8 @@ import org.eclipse.rse.core.events.ISystemRemoteChangeListener;
*/ */
public class SystemRemoteChangeEventManager public class SystemRemoteChangeEventManager
{ {
private Vector listeners = new Vector(); private ISystemRemoteChangeListener[] listeners = new ISystemRemoteChangeListener[0];
private Object lockObject = new Object();
/** /**
* Constructor * Constructor
@ -36,11 +36,20 @@ public class SystemRemoteChangeEventManager
} }
/** /**
* Query if the ISystemRemoteChangeListener is already listening for SystemRemoteChange events * Query if the given listener is already listening for SystemRemoteChange events.
* @param l the listener to check
* @return <code>true</code> if the listener is already registered
*/ */
public boolean isRegisteredSystemRemoteChangeListener(ISystemRemoteChangeListener l) public boolean isRegisteredSystemRemoteChangeListener(ISystemRemoteChangeListener l)
{ {
return listeners.contains(l); synchronized(lockObject) {
for(int i=0; i<listeners.length; i++) {
if(listeners[i].equals(l)) {
return true;
}
}
return false;
}
} }
/** /**
@ -50,19 +59,38 @@ public class SystemRemoteChangeEventManager
*/ */
public void addSystemRemoteChangeListener(ISystemRemoteChangeListener l) public void addSystemRemoteChangeListener(ISystemRemoteChangeListener l)
{ {
if (!listeners.contains(l)) if (l==null) throw new IllegalArgumentException();
listeners.addElement(l); synchronized(lockObject) {
if (!isRegisteredSystemRemoteChangeListener(l)) {
int len = listeners.length;
ISystemRemoteChangeListener[] oldListeners = listeners;
listeners = new ISystemRemoteChangeListener[len+1];
System.arraycopy(oldListeners, 0, listeners, 0, len);
listeners[len] = l;
}
}
} }
/** /**
* Remove a listener to list of listeners. * Remove a listener from the list of listeners.
* If this object is not in the list, this does nothing. * If this object is not in the list, this does nothing.
* @param l the listener to remove. * @param l the listener to remove
*/ */
public void removeSystemRemoteChangeListener(ISystemRemoteChangeListener l) public void removeSystemRemoteChangeListener(ISystemRemoteChangeListener l)
{ {
if (listeners.contains(l)) synchronized(lockObject) {
listeners.removeElement(l); if (isRegisteredSystemRemoteChangeListener(l)) {
//Thread-safety: create a new List when removing, to avoid problems in notify()
int len = listeners.length;
ISystemRemoteChangeListener[] oldListeners = listeners;
listeners = new ISystemRemoteChangeListener[len-1];
for (int i=0, j=0; i<len; i++) {
if (!oldListeners[i].equals(l)) {
listeners[j++] = oldListeners[i];
}
}
}
}
} }
/** /**
@ -72,10 +100,15 @@ public class SystemRemoteChangeEventManager
*/ */
public void notify(ISystemRemoteChangeEvent event) public void notify(ISystemRemoteChangeEvent event)
{ {
for (int idx=0; idx<listeners.size(); idx++) //Thread-safe event firing: fire events on a current snapshot of the list.
{ //If not done that way, and a thread removes a listener while event firing
ISystemRemoteChangeListener l = (ISystemRemoteChangeListener)listeners.elementAt(idx); //is in progress, an ArrayIndexOutOfBoundException might occur.
l.systemRemoteResourceChanged(event); ISystemRemoteChangeListener[] currentListeners;
synchronized(lockObject) {
currentListeners = listeners;
}
for (int idx=0; idx<currentListeners.length; idx++) {
currentListeners[idx].systemRemoteResourceChanged(event);
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************** /********************************************************************************
* Copyright (c) 2002, 2007 IBM Corporation and others. All rights reserved. * Copyright (c) 2002, 2008 IBM Corporation and others. All rights reserved.
* This program and the accompanying materials are made available under the terms * This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is * of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html * available at http://www.eclipse.org/legal/epl-v10.html
@ -12,10 +12,12 @@
* *
* Contributors: * Contributors:
* Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core * Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core
* Martin Oberhuber (Wind River) - [218659] Make *EventManager, *ChangeManager thread-safe
********************************************************************************/ ********************************************************************************/
package org.eclipse.rse.ui.internal.model; package org.eclipse.rse.ui.internal.model;
import java.util.Vector; import java.util.ArrayList;
import java.util.List;
import org.eclipse.rse.core.events.ISystemResourceChangeEvent; import org.eclipse.rse.core.events.ISystemResourceChangeEvent;
import org.eclipse.rse.core.events.ISystemResourceChangeListener; import org.eclipse.rse.core.events.ISystemResourceChangeListener;
@ -26,7 +28,8 @@ import org.eclipse.rse.core.events.ISystemResourceChangeListener;
*/ */
public class SystemResourceChangeManager public class SystemResourceChangeManager
{ {
private Vector listeners = new Vector(); private List listeners = new ArrayList();
private Object lockObject = new Object();
/** /**
* Constructor * Constructor
@ -36,53 +39,75 @@ public class SystemResourceChangeManager
} }
/** /**
* Add a listener to list of listeners. If this object is already in * Query if the given listener is already listening for SystemResourceChange events.
* the list, this does nothing. * @param l the listener to check
*/ * @return <code>true</code> if the listener is already registered
public void addSystemResourceChangeListener(ISystemResourceChangeListener l)
{
if (!listeners.contains(l))
listeners.addElement(l);
}
/**
* Remove a listener to list of listeners. If this object is not in
* the list, this does nothing.
*/
public void removeSystemResourceChangeListener(ISystemResourceChangeListener l)
{
if (listeners.contains(l))
listeners.removeElement(l);
}
/**
* Query if the ISystemResourceChangeListener is already listening for SystemResourceChange events
*/ */
public boolean isRegisteredSystemResourceChangeListener(ISystemResourceChangeListener l) public boolean isRegisteredSystemResourceChangeListener(ISystemResourceChangeListener l)
{ {
return listeners.contains(l); synchronized(lockObject) {
} return listeners.contains(l);
/**
* Notify all registered listeners of the given event
*/
public void notify(ISystemResourceChangeEvent event)
{
for (int idx=0; idx<listeners.size(); idx++)
{
ISystemResourceChangeListener l = (ISystemResourceChangeListener)listeners.elementAt(idx);
l.systemResourceChanged(event);
} }
} }
/** /**
* Post a notify to all registered listeners of the given event * Add a listener to list of listeners.
* If this object is already in the list, this does nothing.
* @param l the listener to add
*/
public void addSystemResourceChangeListener(ISystemResourceChangeListener l)
{
synchronized(lockObject) {
if (!listeners.contains(l))
listeners.add(l);
}
}
/**
* Remove a listener from the list of listeners.
* If this object is not in the list, this does nothing.
* @param l the listener to remove
*/
public void removeSystemResourceChangeListener(ISystemResourceChangeListener l)
{
synchronized(lockObject) {
//Thread-safety: create a new List when removing, to avoid problems in notify()
listeners = new ArrayList(listeners);
listeners.remove(l);
}
}
/**
* Notify all registered listeners of the given event.
* @param event the event to send
*/
public void notify(ISystemResourceChangeEvent event)
{
//Thread-safe event firing: fire events on a current snapshot of the list.
//If not done that way, and a thread removes a listener while event firing
//is in progress, an ArrayIndexOutOfBoundException might occur.
List currentListeners;
synchronized(lockObject) {
currentListeners = listeners;
}
for (int idx=0; idx<currentListeners.size(); idx++) {
ISystemResourceChangeListener l = (ISystemResourceChangeListener)currentListeners.get(idx);
l.systemResourceChanged(event);
}
}
/**
* Post a notify to all registered listeners of the given event.
* @param event the event to send
*/ */
public void postNotify(ISystemResourceChangeEvent event) public void postNotify(ISystemResourceChangeEvent event)
{ {
for (int idx=0; idx<listeners.size(); idx++) List currentListeners;
{ synchronized(lockObject) {
ISystemResourceChangeListener listener = (ISystemResourceChangeListener)listeners.elementAt(idx); currentListeners = listeners;
}
for (int idx=0; idx<currentListeners.size(); idx++) {
ISystemResourceChangeListener listener = (ISystemResourceChangeListener)currentListeners.get(idx);
new SystemPostableEventNotifier(listener, event); // create and run the notifier new SystemPostableEventNotifier(listener, event); // create and run the notifier
//l.systemResourceChanged(event); //l.systemResourceChanged(event);
} }