diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/DataViewModelSchemaNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/DataViewModelSchemaNode.java index 04a7fed2faf..781d0162301 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/DataViewModelSchemaNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/DataViewModelSchemaNode.java @@ -14,6 +14,7 @@ import org.eclipse.dd.dsf.concurrent.Done; import org.eclipse.dd.dsf.concurrent.DoneTracker; import org.eclipse.dd.dsf.concurrent.DsfExecutor; import org.eclipse.dd.dsf.concurrent.GetDataDone; +import org.eclipse.dd.dsf.concurrent.Immutable; import org.eclipse.dd.dsf.model.DMCs; import org.eclipse.dd.dsf.model.IDataModelContext; import org.eclipse.dd.dsf.model.IDataModelEvent; @@ -35,9 +36,10 @@ abstract public class DataViewModelSchemaNode implements IViewModelSchemaNode { /** * IViewModelContext implementation used for this schema node. */ + @Immutable public class DataVMC implements IViewModelContext { - IViewModelContext fParent; - IDataModelContext fDmc; + private final IViewModelContext fParent; + private final IDataModelContext fDmc; public DataVMC(IViewModelContext parent, IDataModelContext dataModelContext) { fParent = parent; diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/IViewModelContext.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/IViewModelContext.java index 02dbf460d6d..cc14081913f 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/IViewModelContext.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/IViewModelContext.java @@ -11,10 +11,12 @@ package org.eclipse.dd.dsf.ui.model; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.dd.dsf.concurrent.Immutable; /** * View model element which is stored as the data object of nodes in the viewer. */ +@Immutable public interface IViewModelContext extends IAdaptable { /** diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/IViewModelSchemaNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/IViewModelSchemaNode.java index 3e6679e1b12..788fc63a781 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/IViewModelSchemaNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/IViewModelSchemaNode.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.dd.dsf.ui.model; +import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.dd.dsf.concurrent.Done; import org.eclipse.dd.dsf.concurrent.GetDataDone; import org.eclipse.dd.dsf.model.IDataModelEvent; @@ -27,6 +28,7 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta; * of other data in the view tree. * @see ViewModelProvider */ +@ConfinedToDsfExecutor("") @SuppressWarnings("restriction") public interface IViewModelSchemaNode { diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/ViewModelProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/ViewModelProvider.java index a36fccca031..1246d15ae5e 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/ViewModelProvider.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/model/ViewModelProvider.java @@ -15,9 +15,11 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.dd.dsf.concurrent.Done; import org.eclipse.dd.dsf.concurrent.DoneTracker; import org.eclipse.dd.dsf.concurrent.GetDataDone; +import org.eclipse.dd.dsf.concurrent.ThreadSafe; import org.eclipse.dd.dsf.model.IDataModelEvent; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy; @@ -44,10 +46,11 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IModelProxy; * @see IModelProxy * @see IViewModelSchemaNode */ +@ConfinedToDsfExecutor("fSession#getExecutor") @SuppressWarnings("restriction") public class ViewModelProvider extends AbstractModelProxy { - private DsfSession fSession; + private final DsfSession fSession; /** * Counter for whether the model proxy is currently installed in the viewer. @@ -66,7 +69,7 @@ public class ViewModelProvider extends AbstractModelProxy * Root VMC node for the model. The devault value may be overriden with * an object from a tree, by the data model adapter. */ - IViewModelContext fRootVMC = new IViewModelContext() { + IViewModelContext fRootVMC = new IViewModelContext(){ public IViewModelContext getParent() { return null; } public IViewModelSchemaNode getSchemaNode() { return null; } public Object getAdapter(Class adapter) { @@ -209,10 +212,12 @@ public class ViewModelProvider extends AbstractModelProxy public boolean isConflicting(ISchedulingRule rule) { return rule == this; } }; + @ThreadSafe public void installed() { fProxyActive++; } + @ThreadSafe public void dispose() { fProxyActive--; super.dispose(); diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/ConfinedToDsfExecutor.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/ConfinedToDsfExecutor.java new file mode 100644 index 00000000000..3b880946af5 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/ConfinedToDsfExecutor.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. 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 available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.dd.dsf.concurrent; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation idicating that given package, class, method, or field can be + * access safely only from a DSF executor thread. If declared on package or type, + * a field or method could still be declared with an annotation indicating that it's + * thread-safe. + *

+ * Note: the runtime retention policy is there to allow automated testing + * and validation code. + * + * @param value The value indicates the method to use to obtain the executor. + * It should be null if it cannot be determined from the given object. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PACKAGE, ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) +@Inherited +@Documented +public @interface ConfinedToDsfExecutor { + String value(); +} diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DefaultDsfExecutor.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DefaultDsfExecutor.java index bae93caaf90..1453b258d82 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DefaultDsfExecutor.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DefaultDsfExecutor.java @@ -24,6 +24,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; @@ -70,18 +71,21 @@ public class DefaultDsfExecutor extends ScheduledThreadPoolExecutor } catch (CancellationException e) { // Ignore also } catch (ExecutionException e) { if (e.getCause() != null) { - DsfPlugin.getDefault().getLog().log(new Status( - IStatus.ERROR, DsfPlugin.PLUGIN_ID, -1, "Uncaught exception in DSF executor thread", e.getCause())); - - // Print out the stack trace to console if assertions are enabled. - if(ASSERTIONS_ENABLED) { - ByteArrayOutputStream outStream = new ByteArrayOutputStream(512); - PrintStream printStream = new PrintStream(outStream); - try { - printStream.write("Uncaught exception in session executor thread: ".getBytes()); - } catch (IOException e2) {} - e.getCause().printStackTrace(new PrintStream(outStream)); - System.err.println(outStream.toString()); + ILog log = DsfPlugin.getDefault().getLog(); + if (log != null) { + log.log(new Status( + IStatus.ERROR, DsfPlugin.PLUGIN_ID, -1, "Uncaught exception in DSF executor thread", e.getCause())); + + // Print out the stack trace to console if assertions are enabled. + if(ASSERTIONS_ENABLED) { + ByteArrayOutputStream outStream = new ByteArrayOutputStream(512); + PrintStream printStream = new PrintStream(outStream); + try { + printStream.write("Uncaught exception in session executor thread: ".getBytes()); + } catch (IOException e2) {} + e.getCause().printStackTrace(new PrintStream(outStream)); + System.err.println(outStream.toString()); + } } } } diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/Done.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/Done.java index 5bff4d2d26b..7136de89b8c 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/Done.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/Done.java @@ -23,6 +23,7 @@ import org.eclipse.dd.dsf.DsfPlugin; * clients have to make sure that access to this object is thread safe if * it's used outside of the caller's dispatch thread. */ +@ConfinedToDsfExecutor("") abstract public class Done extends DsfRunnable { private IStatus fStatus = Status.OK_STATUS; diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutable.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutable.java index 2a845472759..6ed2646a003 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutable.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutable.java @@ -21,6 +21,7 @@ import java.util.Set; * contains fields and methods that used for debugging and tracing when * tracing is enabled. */ +@Immutable public class DsfExecutable { final StackTraceElement[] fCreatedAt; final DefaultDsfExecutor.TracingWrapper fCreatedBy; diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutor.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutor.java index a3243f4cbb8..b8e895d41da 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutor.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutor.java @@ -20,6 +20,7 @@ import java.util.concurrent.ScheduledExecutorService; * to be exclusive to the executor, it could be shared with * another event dispatch service, such as the SWT display dispatch thread. */ +@ThreadSafe public interface DsfExecutor extends ScheduledExecutorService { /** diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfQuery.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfQuery.java index b944df7bb09..351f84bd674 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfQuery.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfQuery.java @@ -27,6 +27,7 @@ import org.eclipse.dd.dsf.service.IDsfService; * * @see java.util.concurrent.Callable */ +@ThreadSafe abstract public class DsfQuery { private V fResult; diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/Immutable.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/Immutable.java new file mode 100644 index 00000000000..2987d7f802e --- /dev/null +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/Immutable.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. 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 available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.dd.dsf.concurrent; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation idicating that given class is immutable and thus thread-safe. + * This annotation is not automatically inherited by sub-classes, since + * sub-classes need to make sure that they are immutable as well. + *

+ * Note: the runtime retention policy is there to allow automated testing + * and validation code. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +public @interface Immutable { + +} diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/ThreadSafe.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/ThreadSafe.java new file mode 100644 index 00000000000..af24e0d4120 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/ThreadSafe.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems and others. + * All rights reserved. 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 available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.dd.dsf.concurrent; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation idicating that given package, class, method, or field can be + * access safely from any thread. If declared on package or type, a field + * or method could still be declared with an annotation indicating that it's + * not thread-safe. + *

+ * Note: the runtime retention policy is there to allow automated testing + * and validation code. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PACKAGE, ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR}) +@Inherited +@Documented +public @interface ThreadSafe { + +} diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/AbstractDMC.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/AbstractDMC.java index ecc291300e0..7defea3c20e 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/AbstractDMC.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/AbstractDMC.java @@ -11,6 +11,7 @@ package org.eclipse.dd.dsf.model; import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.dd.dsf.concurrent.Immutable; import org.eclipse.dd.dsf.service.AbstractDsfService; import org.eclipse.dd.dsf.service.DsfSession; @@ -20,6 +21,7 @@ import org.eclipse.dd.dsf.service.DsfSession; * correctly. * @param Data model data that this context is for. */ +@Immutable public class AbstractDMC extends PlatformObject implements IDataModelContext { diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/DMCs.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/DMCs.java index 923621244b6..a63f490ab3f 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/DMCs.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/DMCs.java @@ -10,6 +10,8 @@ *******************************************************************************/ package org.eclipse.dd.dsf.model; +import org.eclipse.dd.dsf.concurrent.ThreadSafe; + /** * Holder for utility static methods for manipulating IDataModelContext @@ -24,6 +26,7 @@ public class DMCs { * @param ancestorType Class type of the desired DMC ancestor. * @return Returns the ancestor if found, null otherwise. */ + @ThreadSafe @SuppressWarnings("unchecked") public static V getAncestorOfType(IDataModelContext ctx, Class ancestorType) { if (ancestorType.isAssignableFrom(ctx.getClass())) { @@ -50,6 +53,7 @@ public class DMCs { * @param potentialAncestor Ancestor DMC to look for. * @return true if a match is found. */ + @ThreadSafe public static boolean isAncestorOf(IDataModelContext dmc, IDataModelContext potentialAncestor) { // Check the direct parents for a match. for (IDataModelContext parentDmc : dmc.getParents()) { diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/DataModelEvent.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/DataModelEvent.java index 681b62defae..b6acb420b30 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/DataModelEvent.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/DataModelEvent.java @@ -10,12 +10,15 @@ *******************************************************************************/ package org.eclipse.dd.dsf.model; +import org.eclipse.dd.dsf.concurrent.Immutable; + /** * Base implementation of the IDataModelContext interface. */ +@Immutable public class DataModelEvent implements IDataModelEvent { - private V fModelContext; + private final V fModelContext; public DataModelEvent(V context) { fModelContext = context; } diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/IDataModelContext.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/IDataModelContext.java index 362182961ab..2c2ff5af6d3 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/IDataModelContext.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/IDataModelContext.java @@ -11,6 +11,7 @@ package org.eclipse.dd.dsf.model; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.dd.dsf.concurrent.Immutable; /** * The base class for data model objects. @@ -42,6 +43,7 @@ import org.eclipse.core.runtime.IAdaptable; * * @see IDataModelData */ +@Immutable public interface IDataModelContext extends IAdaptable { /** diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/IDataModelData.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/IDataModelData.java index 5d3df186db0..b40bc85f523 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/IDataModelData.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/model/IDataModelData.java @@ -18,7 +18,6 @@ package org.eclipse.dd.dsf.model; *

* This interface is intended primarily to allow for future development of * a generic API to parametrize data model data. - * */ public interface IDataModelData { diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/DsfSession.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/DsfSession.java index fc20317d3fb..7c541cf5a94 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/DsfSession.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/DsfSession.java @@ -27,8 +27,10 @@ import java.util.TreeMap; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.dd.dsf.DsfPlugin; +import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.dd.dsf.concurrent.DsfExecutor; import org.eclipse.dd.dsf.concurrent.DsfRunnable; +import org.eclipse.dd.dsf.concurrent.ThreadSafe; import org.osgi.framework.Filter; /** @@ -47,13 +49,12 @@ import org.osgi.framework.Filter; * * @see org.eclipse.dd.dsf.concurrent.DsfExecutor */ +@ConfinedToDsfExecutor("getExecutor") public class DsfSession -{ - +{ /** * Listener for session started events. This listener is always going to be * called in the dispatch thread of the session's executor. - * */ public static interface SessionStartedListener { /** @@ -86,12 +87,15 @@ public class DsfSession } /** Returns a session instance for given session identifier */ + @ThreadSafe public static DsfSession getSession(String sessionId) { - for (DsfSession session : fgActiveSessions) { - if (session.getId().equals(sessionId)) { - return session; - } - } + synchronized(fgActiveSessions) { + for (DsfSession session : fgActiveSessions) { + if (session.getId().equals(sessionId)) { + return session; + } + } + } return null; } @@ -99,6 +103,7 @@ public class DsfSession * Registers a listener for session started events. * Can be called on any thread. */ + @ThreadSafe public static void addSessionStartedListener(SessionStartedListener listener) { assert !fSessionStartedListeners.contains(listener); fSessionStartedListeners.add(listener); @@ -108,6 +113,7 @@ public class DsfSession * Un-registers a listener for session started events. * Can be called on any thread. */ + @ThreadSafe public static void removeSessionStartedListener(SessionStartedListener listener) { assert fSessionStartedListeners.contains(listener); fSessionStartedListeners.remove(listener); @@ -117,6 +123,7 @@ public class DsfSession * Registers a listener for session ended events. * Can be called on any thread. */ + @ThreadSafe public static void addSessionEndedListener(SessionEndedListener listener) { assert !fSessionEndedListeners.contains(listener); fSessionEndedListeners.add(listener); @@ -126,6 +133,7 @@ public class DsfSession * Un-registers a listener for session ended events. * Can be called on any thread. */ + @ThreadSafe public static void removeSessionEndedListener(SessionEndedListener listener) { assert fSessionEndedListeners.contains(listener); fSessionEndedListeners.remove(listener); @@ -139,6 +147,7 @@ public class DsfSession * @param ownerId ID (plugin ID preferably) of the owner of this session * @return instance object of the new session */ + @ThreadSafe public static DsfSession startSession(DsfExecutor executor, String ownerId) { synchronized(fgActiveSessions) { final DsfSession newSession = new DsfSession(executor, ownerId, Integer.toString(fgSessionIdCounter++)); @@ -160,6 +169,7 @@ public class DsfSession * executor. * @param session session to terminate */ + @ThreadSafe public static void endSession(final DsfSession session) { synchronized(fgActiveSessions) { if (!fgActiveSessions.contains(session)) { @@ -260,6 +270,7 @@ public class DsfSession * @param event to be sent out * @param serviceProperties properties of the service requesting the event to be dispatched */ + @ThreadSafe public void dispatchEvent(final Object event, final Dictionary serviceProperties) { getExecutor().submit(new DsfRunnable() { public void run() { doDispatchEvent(event, serviceProperties);} @@ -273,6 +284,7 @@ public class DsfSession * @param adapter adapter instance to register * @see org.eclipse.dsdp.model.AbstractDMC#getAdapter */ + @ThreadSafe public void registerModelAdapter(Class adapterType, Object adapter) { fAdapters.put(adapterType, adapter); } @@ -282,6 +294,7 @@ public class DsfSession * @param adapterType adapter type to unregister * @see org.eclipse.dsdp.model.AbstractDMC#getAdapter */ + @ThreadSafe public void unregisterModelAdapter(Class adapterType) { fAdapters.remove(adapterType); } @@ -292,14 +305,17 @@ public class DsfSession * @return adapter object for given type, null if none is registered with the session * @see org.eclipse.dsdp.model.AbstractDMC#getAdapter */ + @ThreadSafe public Object getModelAdapter(Class adapterType) { return fAdapters.get(adapterType); } + @ThreadSafe public boolean equals(Object other) { return other instanceof DsfSession && fId.equals(((DsfSession)other).fId); } + @ThreadSafe public int hashCode() { return fId.hashCode(); } private void doDispatchEvent(Object event, Dictionary serviceProperties) { @@ -391,6 +407,7 @@ public class DsfSession /** * Class to be instanciated only using startSession() */ + @ThreadSafe private DsfSession(DsfExecutor executor, String ownerId, String id) { fId = id; fOwnerId = ownerId; diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/IDsfService.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/IDsfService.java index 3b62dea946a..5db2136b8b0 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/IDsfService.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/IDsfService.java @@ -12,6 +12,7 @@ package org.eclipse.dd.dsf.service; import java.util.Dictionary; +import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.dd.dsf.concurrent.Done; import org.eclipse.dd.dsf.concurrent.DsfExecutor; @@ -34,6 +35,7 @@ import org.eclipse.dd.dsf.concurrent.DsfExecutor; * * @see org.osgi.framework.BundleContext#registerService(String[], Object, Dictionary) */ +@ConfinedToDsfExecutor("getExecutor") public interface IDsfService { /**