diff options
Diffstat (limited to 'src/nativewindow/classes/jogamp')
10 files changed, 275 insertions, 32 deletions
diff --git a/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java new file mode 100644 index 000000000..0c2a1e43f --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java @@ -0,0 +1,75 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.nativewindow; + +import javax.media.nativewindow.ToolkitLock; + +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + +/** + * Implementing a global recursive {@link javax.media.nativewindow.ToolkitLock}. + * <p> + * This is the last resort for unstable driver, e.g. proprietary ATI/X11 12.8 and 12.9, + * where multiple X11 display connections to the same connection name are not treated + * thread safe within the GL/X11 driver. + * </p> + */ +public class GlobalToolkitLock implements ToolkitLock { + private static final RecursiveLock globalLock = LockFactory.createRecursiveLock(); + + /** Singleton via {@link NativeWindowFactoryImpl#getGlobalToolkitLock()} */ + protected GlobalToolkitLock() { } + + @Override + public final void lock() { + globalLock.lock(); + if(TRACE_LOCK) { System.err.println("GlobalToolkitLock.lock()"); } + } + + @Override + public final void unlock() { + if(TRACE_LOCK) { System.err.println("GlobalToolkitLock.unlock()"); } + globalLock.unlock(); // implicit lock validation + } + + @Override + public final void validateLocked() throws RuntimeException { + globalLock.validateLocked(); + } + + @Override + public final void dispose() { + // nop + } + + public String toString() { + return "GlobalToolkitLock[obj 0x"+Integer.toHexString(hashCode())+", isOwner "+globalLock.isOwner(Thread.currentThread())+", "+globalLock.toString()+"]"; + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java index 29564da3b..c35cede77 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java +++ b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java @@ -44,9 +44,14 @@ import com.jogamp.common.util.ReflectionUtil.AWTNames; public class NativeWindowFactoryImpl extends NativeWindowFactory { private static final ToolkitLock nullToolkitLock = new NullToolkitLock(); + private static final ToolkitLock globalToolkitLock = new GlobalToolkitLock(); public static ToolkitLock getNullToolkitLock() { - return nullToolkitLock; + return nullToolkitLock; + } + + public static ToolkitLock getGlobalToolkitLock() { + return globalToolkitLock; } // This subclass of NativeWindowFactory handles the case of diff --git a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java index e59910138..211e15955 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java +++ b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java @@ -31,15 +31,16 @@ package jogamp.nativewindow; import javax.media.nativewindow.ToolkitLock; /** - * Implementing a singleton global recursive {@link javax.media.nativewindow.ToolkitLock} - * without any locking. Since there is no locking it all, - * it is intrinsically recursive. + * Implementing a singleton global NOP {@link javax.media.nativewindow.ToolkitLock} + * without any locking. Since there is no locking it all, it is intrinsically recursive. */ public class NullToolkitLock implements ToolkitLock { - + public static final boolean INVALID_LOCKED = Debug.isPropertyDefined("nativewindow.debug.NullToolkitLock.InvalidLocked", true); + /** Singleton via {@link NativeWindowFactoryImpl#getNullToolkitLock()} */ protected NullToolkitLock() { } + @Override public final void lock() { if(TRACE_LOCK) { System.err.println("NullToolkitLock.lock()"); @@ -47,10 +48,20 @@ public class NullToolkitLock implements ToolkitLock { } } + @Override public final void unlock() { if(TRACE_LOCK) { System.err.println("NullToolkitLock.unlock()"); } } + @Override + public final void validateLocked() throws RuntimeException { + /* nop */ + if(INVALID_LOCKED) { + throw new RuntimeException("NullToolkitLock does not lock"); + } + } + + @Override public final void dispose() { // nop } diff --git a/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java index a3b0804fa..5b79de0b8 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java +++ b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java @@ -41,8 +41,6 @@ import com.jogamp.common.util.locks.RecursiveLock; * </p> */ public class ResourceToolkitLock implements ToolkitLock { - public static final boolean DEBUG = Debug.debug("ToolkitLock"); - public static final ResourceToolkitLock create() { return new ResourceToolkitLock(); } @@ -53,17 +51,24 @@ public class ResourceToolkitLock implements ToolkitLock { this.lock = LockFactory.createRecursiveLock(); } - + @Override public final void lock() { - if(TRACE_LOCK) { System.err.println("ResourceToolkitLock.lock()"); } lock.lock(); + if(TRACE_LOCK) { System.err.println("ResourceToolkitLock.lock()"); } } + @Override public final void unlock() { if(TRACE_LOCK) { System.err.println("ResourceToolkitLock.unlock()"); } - lock.unlock(); + lock.unlock(); // implicit lock validation + } + + @Override + public final void validateLocked() throws RuntimeException { + lock.validateLocked(); } + @Override public final void dispose() { // nop } diff --git a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java index 5d7ae8abb..94d12e6fc 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java +++ b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java @@ -49,7 +49,6 @@ import com.jogamp.common.util.locks.RecursiveLock; * </p> */ public class SharedResourceToolkitLock implements ToolkitLock { - public static final boolean DEBUG = Debug.debug("ToolkitLock"); private static final LongObjectHashMap handle2Lock; static { handle2Lock = new LongObjectHashMap(); @@ -109,16 +108,24 @@ public class SharedResourceToolkitLock implements ToolkitLock { } + @Override public final void lock() { - if(TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.lock()"); } lock.lock(); + if(TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.lock()"); } } + @Override public final void unlock() { if(TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.unlock()"); } lock.unlock(); } + @Override + public final void validateLocked() throws RuntimeException { + lock.validateLocked(); + } + + @Override public final void dispose() { if(0 < refCount) { // volatile OK synchronized(handle2Lock) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java b/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java new file mode 100644 index 000000000..2062d1f58 --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java @@ -0,0 +1,51 @@ +package jogamp.nativewindow; + +import javax.media.nativewindow.NativeWindowFactory; + +/** + * Marker interface. + * <p> + * Implementation requires to provide static methods: + * <pre> + public static void initSingleton() {} + + public static void shutdown() {} + + public static boolean requiresToolkitLock() {} + + public static boolean requiresGlobalToolkitLock() {} + * </pre> + * Above static methods are invoked by {@link NativeWindowFactory#initSingleton()}, + * or {@link NativeWindowFactory#shutdown()} via reflection. + * </p> + * <p> + * If <code>requiresGlobalToolkitLock() == true</code>, then + * <code>requiresToolkitLock() == true</code> shall be valid as well. + * </p> + */ +public interface ToolkitProperties { + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + */ + // void initSingleton(); + + /** + * Cleanup resources. + * <p> + * Called by {@link NativeWindowFactory#shutdown()} + * </p> + */ + // void shutdown(); + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + */ + // boolean requiresToolkitLock(); + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + */ + // boolean requiresGlobalToolkitLock(); + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java index 7c934b154..2dadfb16b 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java @@ -79,6 +79,8 @@ public class JAWTUtil { private static final Method sunToolkitAWTLockMethod; private static final Method sunToolkitAWTUnlockMethod; private static final boolean hasSunToolkitAWTLock; + + private static volatile Thread exclusiveOwnerThread; private static final ToolkitLock jawtToolkitLock; @@ -229,13 +231,23 @@ public class JAWTUtil { } hasSunToolkitAWTLock = _hasSunToolkitAWTLock; // hasSunToolkitAWTLock = false; + exclusiveOwnerThread = null; jawtToolkitLock = new ToolkitLock() { public final void lock() { + NativeWindowFactory.getGlobalToolkitLock().lock(); JAWTUtil.lockToolkit(); + if(TRACE_LOCK) { System.err.println("JAWTToolkitLock.lock()"); } } public final void unlock() { + if(TRACE_LOCK) { System.err.println("JAWTToolkitLock.unlock()"); } JAWTUtil.unlockToolkit(); + NativeWindowFactory.getGlobalToolkitLock().unlock(); + } + @Override + public final void validateLocked() throws RuntimeException { + NativeWindowFactory.getGlobalToolkitLock().validateLocked(); + JAWTUtil.validateLocked(); } public final void dispose() { // nop @@ -312,7 +324,7 @@ public class JAWTUtil { * JAWT's native Lock() function calls SunToolkit.awtLock(), * which just uses AWT's global ReentrantLock.<br> */ - private static void awtLock() { + private static final void awtLock() { if(hasSunToolkitAWTLock) { try { sunToolkitAWTLockMethod.invoke(null, (Object[])null); @@ -322,6 +334,7 @@ public class JAWTUtil { } else { jawtLockObject.Lock(); } + exclusiveOwnerThread = Thread.currentThread(); } /** @@ -330,7 +343,9 @@ public class JAWTUtil { * JAWT's native Unlock() function calls SunToolkit.awtUnlock(), * which just uses AWT's global ReentrantLock.<br> */ - private static void awtUnlock() { + private static final void awtUnlock() { + awtValidateLocked(); + exclusiveOwnerThread = null; if(hasSunToolkitAWTLock) { try { sunToolkitAWTUnlockMethod.invoke(null, (Object[])null); @@ -342,6 +357,16 @@ public class JAWTUtil { } } + private static final void awtValidateLocked() throws RuntimeException { + final Thread ct = Thread.currentThread(); + if( ct != exclusiveOwnerThread ) { + if ( null == exclusiveOwnerThread ) { + throw new RuntimeException(ct.getName()+": JAWT-ToolkitLock not locked"); + } + throw new RuntimeException(ct.getName()+": Not JAWT-ToolkitLock owner. Owner is "+exclusiveOwnerThread.getName()); + } + } + public static void lockToolkit() throws NativeWindowException { if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.lock()"); } if(!headlessMode && !isJava2DQueueFlusherThread()) { @@ -355,6 +380,13 @@ public class JAWTUtil { awtUnlock(); } } + + public static final void validateLocked() throws RuntimeException { + if(!headlessMode && !isJava2DQueueFlusherThread()) { + awtValidateLocked(); + } + } + public static ToolkitLock getJAWTToolkitLock() { return jawtToolkitLock; diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index b7a83e133..481cbbe39 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -34,13 +34,15 @@ import javax.media.nativewindow.util.Point; import jogamp.nativewindow.Debug; import jogamp.nativewindow.NWJNILibLoader; +import jogamp.nativewindow.ToolkitProperties; -public class OSXUtil { +public class OSXUtil implements ToolkitProperties { private static boolean isInit = false; private static final boolean DEBUG = Debug.debug("OSXUtil"); /** * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties */ public static synchronized void initSingleton() { if(!isInit) { @@ -60,13 +62,21 @@ public class OSXUtil { /** * Called by {@link NativeWindowFactory#shutdown()} + * @see ToolkitProperties */ - public static void shutdown() { - } + public static void shutdown() { } - public static boolean requiresToolkitLock() { - return false; - } + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static boolean requiresToolkitLock() { return false; } + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static final boolean requiresGlobalToolkitLock() { return false; } public static boolean isNSView(long object) { return isNSView0(object); diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java index 613c76032..4408a0903 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java @@ -33,9 +33,10 @@ import javax.media.nativewindow.NativeWindowFactory; import jogamp.nativewindow.NWJNILibLoader; import jogamp.nativewindow.Debug; +import jogamp.nativewindow.ToolkitProperties; import jogamp.nativewindow.x11.X11Util; -public class GDIUtil { +public class GDIUtil implements ToolkitProperties { private static final boolean DEBUG = Debug.debug("GDIUtil"); private static final String dummyWindowClassNameBase = "_dummyWindow_clazz" ; @@ -44,6 +45,7 @@ public class GDIUtil { /** * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties */ public static synchronized void initSingleton() { if(!isInit) { @@ -67,12 +69,23 @@ public class GDIUtil { /** * Called by {@link NativeWindowFactory#shutdown()} + * @see ToolkitProperties */ public static void shutdown() { } + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ public static boolean requiresToolkitLock() { return false; } + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static final boolean requiresGlobalToolkitLock() { return false; } + private static RegisteredClass dummyWindowClass = null; private static Object dummyWindowSync = new Object(); diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java index 30792113d..221939cde 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java @@ -43,13 +43,15 @@ import javax.media.nativewindow.NativeWindowFactory; import jogamp.nativewindow.Debug; import jogamp.nativewindow.NWJNILibLoader; +import jogamp.nativewindow.ToolkitProperties; + import com.jogamp.common.util.LongObjectHashMap; import com.jogamp.nativewindow.x11.X11GraphicsDevice; /** * Contains a thread safe X11 utility to retrieve display connections. */ -public class X11Util { +public class X11Util implements ToolkitProperties { /** * See Bug 515 - https://jogamp.org/bugzilla/show_bug.cgi?id=515 * <p> @@ -81,6 +83,11 @@ public class X11Util { */ public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true); + /** + * See Bug 623 - https://jogamp.org/bugzilla/show_bug.cgi?id=623 + */ + public static final boolean ATI_HAS_MULTITHREADING_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_MULTITHREADING_BUG", true); + public static final boolean DEBUG = Debug.debug("X11Util"); public static final boolean XSYNC_ENABLED = Debug.isPropertyDefined("nativewindow.debug.X11Util.XSync", true); public static final boolean XERROR_STACKDUMP = DEBUG || Debug.isPropertyDefined("nativewindow.debug.X11Util.XErrorStackDump", true); @@ -88,11 +95,15 @@ public class X11Util { private static String nullDisplayName = null; private static volatile boolean isInit = false; private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues + private static boolean requiresGlobalToolkitLock = false; // ATI/AMD X11 driver issues private static Object setX11ErrorHandlerLock = new Object(); + private static final String X11_EXTENSION_ATIFGLRXDRI = "ATIFGLRXDRI"; + private static final String X11_EXTENSION_ATIFGLEXTENSION = "ATIFGLEXTENSION"; /** * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties */ public static void initSingleton() { if(!isInit) { @@ -100,7 +111,7 @@ public class X11Util { if(!isInit) { isInit = true; if(DEBUG) { - System.out.println("X11UtilUtil.initSingleton()"); + System.out.println("X11Util.initSingleton()"); } if(!NWJNILibLoader.loadNativeWindow("x11")) { throw new NativeWindowException("NativeWindow X11 native library load error."); @@ -108,6 +119,7 @@ public class X11Util { final boolean isInitOK = initialize0( XERROR_STACKDUMP ); + final boolean hasX11_EXTENSION_ATIFGLRXDRI, hasX11_EXTENSION_ATIFGLEXTENSION; final long dpy = X11Lib.XOpenDisplay(null); if(0 != dpy) { if(XSYNC_ENABLED) { @@ -115,17 +127,29 @@ public class X11Util { } try { nullDisplayName = X11Lib.XDisplayString(dpy); + hasX11_EXTENSION_ATIFGLRXDRI = X11Lib.QueryExtension(dpy, X11_EXTENSION_ATIFGLRXDRI); + hasX11_EXTENSION_ATIFGLEXTENSION = X11Lib.QueryExtension(dpy, X11_EXTENSION_ATIFGLEXTENSION); } finally { X11Lib.XCloseDisplay(dpy); } } else { nullDisplayName = "nil"; + hasX11_EXTENSION_ATIFGLRXDRI = false; + hasX11_EXTENSION_ATIFGLEXTENSION = false; } + requiresGlobalToolkitLock = ATI_HAS_MULTITHREADING_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION ); + markAllDisplaysUnclosable = ATI_HAS_XCLOSEDISPLAY_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION ); if(DEBUG) { - System.err.println("X11Util init OK "+isInitOK+"]"+ - ", X11 Display(NULL) <"+nullDisplayName+">"+ - ", XSynchronize Enabled: "+XSYNC_ENABLED); + System.err.println("X11Util.initSingleton(): OK "+isInitOK+"]"+ + ",\n\t X11 Display(NULL) <"+nullDisplayName+">"+ + ",\n\t XSynchronize Enabled: " + XSYNC_ENABLED+ + ",\n\t X11_EXTENSION_ATIFGLRXDRI " + hasX11_EXTENSION_ATIFGLRXDRI+ + ",\n\t X11_EXTENSION_ATIFGLEXTENSION " + hasX11_EXTENSION_ATIFGLEXTENSION+ + ",\n\t requiresToolkitLock "+requiresToolkitLock()+ + ",\n\t requiresGlobalToolkitLock "+requiresGlobalToolkitLock()+ + ",\n\t markAllDisplaysUnclosable "+getMarkAllDisplaysUnclosable() + ); // Thread.dumpStack(); } } @@ -147,6 +171,7 @@ public class X11Util { * <p> * Called by {@link NativeWindowFactory#shutdown()} * </p> + * @see ToolkitProperties */ public static void shutdown() { if(isInit) { @@ -189,8 +214,20 @@ public class X11Util { } } - public static boolean requiresToolkitLock() { - return true; // JAWT locking: yes, instead of native X11 locking w use a recursive lock. + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static final boolean requiresToolkitLock() { + return true; // JAWT locking: yes, instead of native X11 locking w use a recursive lock per display connection. + } + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static final boolean requiresGlobalToolkitLock() { + return requiresGlobalToolkitLock; // JAWT locking: yes, instead of native X11 locking w use a global lock. } public static void setX11ErrorHandler(boolean onoff, boolean quiet) { @@ -206,9 +243,6 @@ public class X11Util { public static boolean getMarkAllDisplaysUnclosable() { return markAllDisplaysUnclosable; } - public static void setMarkAllDisplaysUnclosable(boolean v) { - markAllDisplaysUnclosable = v; - } private X11Util() {} @@ -373,7 +407,7 @@ public class X11Util { name = validateDisplayName(name); boolean reused = false; - synchronized(globalLock) { + synchronized(globalLock) { for(int i=0; i<reusableDisplayList.size(); i++) { if(reusableDisplayList.get(i).getName().equals(name)) { namedDpy = reusableDisplayList.remove(i); |