summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorJeroen Frijters <jeroen@sumatra.nl>2006-08-24 06:40:04 +0000
committerJeroen Frijters <jeroen@sumatra.nl>2006-08-24 06:40:04 +0000
commitd705694ea9ae573bc4bc90dc7addf992e1dc8926 (patch)
treee67cdf3dd8edd046af2e905f4633f6de1e8611c8 /java
parentd7b5e957dc8864898a3763356109a17fe4c90f11 (diff)
downloadclasspath-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.java13
-rw-r--r--java/lang/ref/ReferenceQueue.java53
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();