1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Added annotations to indicate thead access policy for objects used with DSF (bug# 154273).

This commit is contained in:
Pawel Piech 2006-10-09 22:22:49 +00:00
parent 4cde8d219c
commit 103d6ac39c
19 changed files with 179 additions and 26 deletions

View file

@ -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;

View file

@ -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 {
/**

View file

@ -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 {

View file

@ -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();

View file

@ -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.
* <p>
* 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();
}

View file

@ -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());
}
}
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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
{
/**

View file

@ -27,6 +27,7 @@ import org.eclipse.dd.dsf.service.IDsfService;
*
* @see java.util.concurrent.Callable
*/
@ThreadSafe
abstract public class DsfQuery<V> {
private V fResult;

View file

@ -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.
* <p>
* Note: the runtime retention policy is there to allow automated testing
* and validation code.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface Immutable {
}

View file

@ -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.
* <p>
* 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 {
}

View file

@ -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 <V> Data model data that this context is for.
*/
@Immutable
public class AbstractDMC<V extends IDataModelData> extends PlatformObject
implements IDataModelContext<V>
{

View file

@ -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 extends IDataModelContext> V getAncestorOfType(IDataModelContext ctx, Class<V> 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()) {

View file

@ -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<V extends IDataModelContext> implements IDataModelEvent<V> {
private V fModelContext;
private final V fModelContext;
public DataModelEvent(V context) {
fModelContext = context;
}

View file

@ -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<V extends IDataModelData> extends IAdaptable
{
/**

View file

@ -18,7 +18,6 @@ package org.eclipse.dd.dsf.model;
* <p>
* This interface is intended primarily to allow for future development of
* a generic API to parametrize data model data.
*
*/
public interface IDataModelData {

View file

@ -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;

View file

@ -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 {
/**