-
-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is a squashed commit of the following changes for #2221. Thanks to @godfat for the work on this one. commit 4bc9e8e Author: Lin Jen-Shin <godfat@godfat.org> Date: Fri Dec 19 04:13:20 2014 +0800 WeakIdentityLinkedHashMap: Properly set head. commit fe56e69 Author: Lin Jen-Shin <godfat@godfat.org> Date: Fri Dec 19 02:10:43 2014 +0800 Use WeakIdentityLinkedHashSet for RubyThreadGroup: We extend WeakIdentityHashMap for WeakIdentityLinkedHashMap, and use it for WeakIdentityLinkedHashSet. Sorry that this was a naive implementation and I didn't write any tests for this. Originally I want to do something like java.util.LinkedHashMap, but it seems WeakIdentityHashMap didn't implement every thing we need to do the same. Therefore I decided to just write what we need for RubyThreadGroup. We could complete this in the future. Note that this should also fix a bug where WeakIdentityHashMap#valueRemoved is not called properly. commit e5bcad9 Author: Lin Jen-Shin <godfat@godfat.org> Date: Tue Nov 25 00:43:53 2014 +0800 Use a ReferenceQueue to sweep dead references commit 475746f Author: Lin Jen-Shin <godfat@godfat.org> Date: Fri Nov 21 08:06:39 2014 +0800 Preserve ThreadGroup#list order with ArrayList Because MRI uses a linked list which preserves the order of the threads. https://github.com/ruby/ruby/blob/2a754a733045da9965e88d1f31e650ea6b3f2b6c/vm_core.h#L973-L978 This is useful to assume the first thread in the list is the root of a group, and saving values in the thread could be shared amongst the thread group. If we ever have thread group local variable, this is not really needed.
Showing
3 changed files
with
121 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
core/src/main/java/org/jruby/util/WeakIdentityLinkedHashMap.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
|
||
package org.jruby.util; | ||
|
||
import java.lang.ref.ReferenceQueue; | ||
import java.util.Iterator; | ||
import java.util.NoSuchElementException; | ||
|
||
public class WeakIdentityLinkedHashMap extends WeakIdentityHashMap { | ||
public WeakIdentityLinkedHashMap() { | ||
super(); | ||
} | ||
|
||
public WeakIdentityLinkedHashMap(int size) { | ||
super(size); | ||
} | ||
|
||
class Entry extends WeakIdentityHashMap.Entry { | ||
Entry before, after; | ||
|
||
Entry(int hash, Object masked_key, Object value, WeakIdentityHashMap.Entry next, ReferenceQueue queue, Entry tail) { | ||
super(hash, masked_key, value, next, queue); | ||
before = tail; | ||
if (tail != null) { | ||
tail.after = this; | ||
} | ||
} | ||
} | ||
|
||
// The head (eldest) of the doubly linked list. | ||
transient Entry head; | ||
|
||
// The tail (youngest) of the doubly linked list. | ||
transient Entry tail; | ||
|
||
@Override | ||
public void clear() { | ||
head = tail = null; | ||
super.clear(); | ||
} | ||
|
||
@Override | ||
protected WeakIdentityHashMap.Entry newEntry(int hash, Object masked_key, Object value, WeakIdentityHashMap.Entry next, ReferenceQueue queue) { | ||
Entry newTail = new Entry(hash, masked_key, value, next, queue, tail); | ||
if (head == null) { | ||
head = newTail; | ||
} | ||
tail = newTail; | ||
return newTail; | ||
} | ||
|
||
@Override | ||
protected void entryRemoved(WeakIdentityHashMap.Entry entry) { | ||
Entry ent = (Entry) entry; | ||
if (ent.before == null) { | ||
head = ent.after; | ||
} | ||
else { | ||
ent.before.after = ent.after; | ||
} | ||
super.entryRemoved(entry); | ||
} | ||
|
||
@Override | ||
protected Iterator entryIterator() { | ||
return new EntryIterator(); | ||
} | ||
|
||
final class EntryIterator implements Iterator { | ||
private Entry entry; | ||
|
||
EntryIterator() { | ||
expunge(); | ||
entry = head; | ||
} | ||
|
||
public boolean hasNext() { | ||
return (entry != null); | ||
} | ||
|
||
public Object next() { | ||
Object result = entry; | ||
|
||
if (result == null) { | ||
throw new NoSuchElementException(); | ||
} else { | ||
entry = entry.after; | ||
return result; | ||
} | ||
} | ||
|
||
public void remove() { | ||
Entry removed = entry; | ||
expunge(); | ||
entry = entry.after; | ||
WeakIdentityLinkedHashMap.this.removeEntry(removed); | ||
} | ||
} | ||
} |