From c8afa2e38a7d7174ceed0be2069856ed548192b4 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Tue, 8 Feb 2011 23:30:18 +0100 Subject: CLContext and CLPlatform are now threadsafe. Updated javadocs. --- src/com/jogamp/opencl/CLContext.java | 112 +++++++++++++++++++++------------- src/com/jogamp/opencl/CLPlatform.java | 4 +- 2 files changed, 72 insertions(+), 44 deletions(-) (limited to 'src/com/jogamp') diff --git a/src/com/jogamp/opencl/CLContext.java b/src/com/jogamp/opencl/CLContext.java index 8f5c411b..b7ddb813 100644 --- a/src/com/jogamp/opencl/CLContext.java +++ b/src/com/jogamp/opencl/CLContext.java @@ -47,30 +47,45 @@ import java.nio.LongBuffer; import java.nio.ShortBuffer; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import static java.lang.System.*; import static com.jogamp.opencl.CLException.*; import static com.jogamp.common.nio.Buffers.*; import static com.jogamp.common.os.Platform.*; import static com.jogamp.opencl.CL.*; import static com.jogamp.opencl.CLBuffer.*; +import static java.util.Collections.*; /** * CLContext is responsible for managing objects such as command-queues, memory, * program and kernel objects and for executing kernels on one or more devices * specified in the context. + *

+ * Must be released if no longer used to free native resources. {@link #release()} will + * also free all associated {@link CLResource} like programs, samplers, command queues and memory + * objects. + *

+ *

+ * For a code example see {@link CLPlatform}. + *

+ * + * concurrency:
+ * CLContext is threadsafe. + * * @author Michael Bien */ public class CLContext extends CLObject implements CLResource { protected CLDevice[] devices; - protected final List programs; - protected final List samplers; - protected final List> memoryObjects; + protected final Set programs; + protected final Set samplers; + protected final Set> memoryObjects; protected final Map> queuesMap; @@ -81,10 +96,13 @@ public class CLContext extends CLObject implements CLResource { protected CLContext(CLPlatform platform, long contextID, ErrorDispatcher dispatcher) { super(CLPlatform.getLowLevelCLInterface(), contextID); this.platform = platform; - this.programs = new ArrayList(); - this.samplers = new ArrayList(); - this.memoryObjects = new ArrayList>(); + + this.programs = synchronizedSet(new HashSet()); + this.samplers = synchronizedSet(new HashSet()); + this.memoryObjects = synchronizedSet(new HashSet>()); + this.queuesMap = new HashMap>(); + this.errorHandler = dispatcher; /* @@ -97,7 +115,7 @@ public class CLContext extends CLObject implements CLResource { } - private void initDevices() { + private synchronized void initDevices() { if (devices == null) { @@ -415,12 +433,14 @@ public class CLContext extends CLObject implements CLResource { CLCommandQueue queue = CLCommandQueue.create(this, device, properties); - List list = queuesMap.get(device); - if(list == null) { - list = new ArrayList(); - queuesMap.put(device, list); + synchronized(queuesMap) { + List list = queuesMap.get(device); + if(list == null) { + list = new ArrayList(); + queuesMap.put(device, list); + } + list.add(queue); } - list.add(queue); return queue; } @@ -440,11 +460,13 @@ public class CLContext extends CLObject implements CLResource { } void onCommandQueueReleased(CLDevice device, CLCommandQueue queue) { - List list = queuesMap.get(device); - list.remove(queue); - // remove empty lists from map - if(list.isEmpty()) - queuesMap.remove(device); + synchronized(queuesMap) { + List list = queuesMap.get(device); + list.remove(queue); + // remove empty lists from map + if(list.isEmpty()) + queuesMap.remove(device); + } } void onSamplerReleased(CLSampler sampler) { @@ -458,30 +480,28 @@ public class CLContext extends CLObject implements CLResource { public void removeCLErrorHandler(CLErrorHandler handler) { errorHandler.removeHandler(handler); } + + private void release(Collection resources) { + // resources remove themselves when released, see above + CLResource[] array = resources.toArray(new CLResource[resources.size()]); + for (CLResource resource : array) { + resource.release(); + } + } /** - * Releases the context and all resources. + * Releases this context and all resources. */ - public void release() { + public synchronized void release() { try{ //release all resources - while(!programs.isEmpty()) - programs.get(0).release(); - - while(!memoryObjects.isEmpty()) - memoryObjects.get(0).release(); - - while(!samplers.isEmpty()) - samplers.get(0).release(); + release(programs); + release(memoryObjects); + release(samplers); for (CLDevice device : getDevices()) { - List list = queuesMap.get(device); - if(list != null) { - while(!list.isEmpty()) { - list.get(0).release(); - } - } + release(queuesMap.get(device)); } }finally{ @@ -553,24 +573,30 @@ public class CLContext extends CLObject implements CLResource { } /** - * Returns a read only view of all programs associated with this context. + * Returns a read only shapshot of all programs associated with this context. */ public List getPrograms() { - return Collections.unmodifiableList(programs); + synchronized(programs) { + return unmodifiableList(new ArrayList(programs)); + } } /** - * Returns a read only view of all allocated memory objects associated with this context. + * Returns a read only shapshot of all allocated memory objects associated with this context. */ public List> getMemoryObjects() { - return Collections.unmodifiableList(memoryObjects); + synchronized(memoryObjects) { + return unmodifiableList(new ArrayList>(memoryObjects)); + } } /** - * Returns a read only view of all samplers associated with this context. + * Returns a read only shapshot of all samplers associated with this context. */ public List getSamplers() { - return Collections.unmodifiableList(samplers); + synchronized(samplers) { + return unmodifiableList(new ArrayList(samplers)); + } } /** @@ -667,7 +693,7 @@ public class CLContext extends CLObject implements CLResource { protected static class ErrorDispatcher implements CLErrorHandler { - private volatile CLErrorHandler[] clientHandlers = new CLErrorHandler[0]; + private CLErrorHandler[] clientHandlers = new CLErrorHandler[0]; public void onError(String errinfo, ByteBuffer private_info, long cb) { CLErrorHandler[] handlers = this.clientHandlers; @@ -676,7 +702,7 @@ public class CLContext extends CLObject implements CLResource { } } - private void addHandler(CLErrorHandler handler) { + private synchronized void addHandler(CLErrorHandler handler) { if(handler == null) { throw new IllegalArgumentException("handler was null."); @@ -688,7 +714,7 @@ public class CLContext extends CLObject implements CLResource { clientHandlers = handlers; } - private void removeHandler(CLErrorHandler handler) { + private synchronized void removeHandler(CLErrorHandler handler) { if(handler == null) { throw new IllegalArgumentException("handler was null."); diff --git a/src/com/jogamp/opencl/CLPlatform.java b/src/com/jogamp/opencl/CLPlatform.java index 1db3dcf2..218efed3 100644 --- a/src/com/jogamp/opencl/CLPlatform.java +++ b/src/com/jogamp/opencl/CLPlatform.java @@ -82,6 +82,8 @@ import static com.jogamp.opencl.CL.*; * context.release(); * } *

+ * concurrency:
+ * CLPlatform is threadsafe. * * @author Michael Bien * @see #initialize() @@ -441,7 +443,7 @@ public final class CLPlatform { * Returns all platform extension names as unmodifiable Set. */ @CLProperty("CL_PLATFORM_EXTENSIONS") - public Set getExtensions() { + public synchronized Set getExtensions() { if(extensions == null) { extensions = new HashSet(); -- cgit v1.2.3