diff options
| author | Jeroen Frijters <jeroen@sumatra.nl> | 2006-08-24 06:40:04 +0000 |
|---|---|---|
| committer | Jeroen Frijters <jeroen@sumatra.nl> | 2006-08-24 06:40:04 +0000 |
| commit | d705694ea9ae573bc4bc90dc7addf992e1dc8926 (patch) | |
| tree | e67cdf3dd8edd046af2e905f4633f6de1e8611c8 /java | |
| parent | d7b5e957dc8864898a3763356109a17fe4c90f11 (diff) | |
| download | classpath-d705694ea9ae573bc4bc90dc7addf992e1dc8926.tar.gz | |
2006-08-24 Jeroen Frijters <jeroen@frijters.net>
* java/lang/ref/Reference.java
(queue, nextOnQueue): Made volatile.
(enqueue): Made thread safe.
* java/lang/ref/ReferenceQueue.java
(lock): New field.
(poll): Removed synchronized.
(enqueue): Changed to synchronize on lock object, to update Reference
state and return success status.
(dequeue, remove): Synchronize on lock object.
Diffstat (limited to 'java')
| -rw-r--r-- | java/lang/ref/Reference.java | 13 | ||||
| -rw-r--r-- | java/lang/ref/ReferenceQueue.java | 53 |
2 files changed, 42 insertions, 24 deletions
diff --git a/java/lang/ref/Reference.java b/java/lang/ref/Reference.java index 4b6a3adbc..7ea9bdd5a 100644 --- a/java/lang/ref/Reference.java +++ b/java/lang/ref/Reference.java @@ -1,5 +1,5 @@ /* java.lang.ref.Reference - Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -82,7 +82,7 @@ public abstract class Reference * The queue this reference is registered on. This is null, if this * wasn't registered to any queue or reference was already enqueued. */ - ReferenceQueue queue; + volatile ReferenceQueue queue; /** * Link to the next entry on the queue. If this is null, this @@ -91,7 +91,7 @@ public abstract class Reference * (not to null, that value is used to mark a not enqueued * reference). */ - Reference nextOnQueue; + volatile Reference nextOnQueue; /** * This lock should be taken by the garbage collector, before @@ -166,11 +166,10 @@ public abstract class Reference */ public boolean enqueue() { - if (queue != null && nextOnQueue == null) + ReferenceQueue q = queue; + if (q != null) { - queue.enqueue(this); - queue = null; - return true; + return q.enqueue(this); } return false; } diff --git a/java/lang/ref/ReferenceQueue.java b/java/lang/ref/ReferenceQueue.java index f4729f282..59e00c858 100644 --- a/java/lang/ref/ReferenceQueue.java +++ b/java/lang/ref/ReferenceQueue.java @@ -1,5 +1,5 @@ /* java.lang.ref.ReferenceQueue - Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 1999, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -63,6 +63,12 @@ public class ReferenceQueue private Reference first; /** + * This is the lock that protects our linked list and is used to signal + * a thread waiting in remove(). + */ + private final Object lock = new Object(); + + /** * Creates a new empty reference queue. */ public ReferenceQueue() @@ -76,7 +82,7 @@ public class ReferenceQueue * @return a reference on the queue, if there is one, * <code>null</code> otherwise. */ - public synchronized Reference poll() + public Reference poll() { return dequeue(); } @@ -84,14 +90,23 @@ public class ReferenceQueue /** * This is called by reference to enqueue itself on this queue. * @param ref the reference that should be enqueued. + * @return true if successful, false if not. */ - synchronized void enqueue(Reference ref) + final boolean enqueue(Reference ref) { - /* last reference will point to itself */ - ref.nextOnQueue = first == null ? ref : first; - first = ref; - /* this wakes only one remove thread. */ - notify(); + synchronized (lock) + { + if (ref.queue != this) + return false; + + /* last reference will point to itself */ + ref.nextOnQueue = first == null ? ref : first; + ref.queue = null; + first = ref; + /* this wakes only one remove thread. */ + lock.notify(); + return true; + } } /** @@ -100,13 +115,16 @@ public class ReferenceQueue */ private Reference dequeue() { - if (first == null) - return null; + synchronized (lock) + { + if (first == null) + return null; - Reference result = first; - first = (first == first.nextOnQueue) ? null : first.nextOnQueue; - result.nextOnQueue = null; - return result; + Reference result = first; + first = (first == first.nextOnQueue) ? null : first.nextOnQueue; + result.nextOnQueue = null; + return result; + } } /** @@ -118,12 +136,13 @@ public class ReferenceQueue * <code>null</code> if timeout period expired. * @exception InterruptedException if the wait was interrupted. */ - public synchronized Reference remove(long timeout) + public Reference remove(long timeout) throws InterruptedException { - if (first == null) + synchronized (lock) { - wait(timeout); + if (first == null) + lock.wait(timeout); } return dequeue(); |
