new syntax - a provocation
Luke Gorrie
luke@REDACTED
Thu Sep 25 14:42:07 CEST 2003
Joe Armstrong <joe@REDACTED> writes:
> Yes - I spent about 10 years thinking about "how to garb the atom
> table" just to realise that I'd been thinking about the wrong problem.
Surely you considered the (undoubtedly unoriginal) idea that I posted
in that time. I'd like to know what's wrong with it - does it badly
conflict with the existing ERTS implementation somehow?
To restate my idea in terms unlikely to be overlooked, I wrote a
working and fully garbage-collectable Atom datatype in about a page of
Java (below).
Of course, maybe symbolic computing is just easier in Java.
My program is not deterministic because it relies on the runtime
system to actually collect the garbage. On my computer it works fine,
and runs with this output:
Equality is okay.
There are 3 atoms.
After GC there's 1.
And it still works after GC.
The program:
import java.util.*;
import java.lang.ref.*;
/**
* Atom datatype. Use e.g. Atom.get("foobar") to get/create an atom.
* Atoms can be tested for equality in unit time using the == operator.
*
* Atoms and their names are only weakly-referenced internally, and
* are therefore able to be garbage collected provided no other
* objects reference them.
*/
public class Atom
{
// Mapping from names to weakly-referenced Atom objects.
// Keys (names) are also weakly referenced.
static Map atom_table = new WeakHashMap();
String name;
public static Atom get(String name) {
synchronized (atom_table) {
Reference ref = (Reference)atom_table.get(name);
Atom atom = ref == null ? null : (Atom)ref.get();
if (atom == null) {
atom = new Atom(name);
atom_table.put(name, new WeakReference(atom));
}
return atom;
}
}
private Atom(String name)
{ this.name = name; }
// Make atoms remove their names from the table when garbage
// collected. This should not be needed in principle, because the
// names are only weakly-referenced by the table and should be
// garbage collected out of it. However, this isn't happening, and
// I think it's because I'm using strings that appear as literals
// in the source code and are allocated in the
// non-garbage-collected constant pool.
public void finalize()
{ atom_table.remove(this.name); }
// Run a simple test when invoked.
public static void main(String[] args) {
Atom baz = get("baz");
test();
System.out.println("There are " + atom_table.size() + " atoms.");
// Create piles and piles of garbage to force a sincere effort
// at garbage collection.
for (int i = 0; i < 100000000; i++) {
new Object();
}
System.gc();
System.out.println("After GC there's " + atom_table.size() + ".");
if (baz == get("baz"))
System.out.println("And it still works after GC.");
else
System.out.println("But it doesn't work after GC.");
}
static void test() {
Atom foo = get("foo"), foo2 = get("foo"), bar = get("bar");
if ((foo == foo2) && (bar != foo))
System.out.println("Equality is okay.");
else
System.out.println("Equality broken.");
}
}
More information about the erlang-questions
mailing list