Hi Rich,

maybe this is a better way of looking at it.

When you create a transaction, you get a new UnitOfTime object that
has the sequential timestamp in it. The Transaction object keeps a
reference to the UnitOfTime object for the rest of the Transaction
objects life.

private static final AtomicReference<UnitOfTime> timeLineHead =

        new AtomicReference<UnitOfTime>(new UnitOfTime(0));

public static UnitOfTime getNewUnitOfTime() {

    UnitOfTime current = timeLineHead.get();

    final UnitOfTime future = new UnitOfTime(current.time + 1);

    while (!timeLineHead.compareAndSet(current, future)) {

        current = timeLineHead.get();

        future.time = current.time + 1;

    }

    current.future = future;

    return future;

}

UnitOfTime objects are kept in a singly linked list to make a time
line. The sole purpose of this list is to guarantee garbage collection
order. The first UnitOfTime object created will also be the first one
GC'd. Now we have a guaranteed order objects will be GC'd - great for
a Ref history list.

The UnitOfTime object also has a set of objects you want it to keep
alive. This set is only written to, never read. It exists only to tell
the GC what you don't want GC'd too early. (It probably doesn't have
to be concurrent.)

public class UnitOfTime {

    public UnitOfTime future;

    public long time;

    private final ConcurrentLinkedQueue<Object> keepAliveSet = new
ConcurrentLinkedQueue<Object>();

    public void keepAlive(Object obj) { keepAliveSet.add(obj); }

    public UnitOfTime(long time) { this.time = time; }

}

So we now have Transaction objects referencing the UnitOfTime they
were created. This holds that UnitOfTime object in memory (and
consequently all later UnitOfTime objects) until the Transaction
object has been forgotten and GC'd.

I think you are using the using the latest time in your commits, so
your commit would getNewUnitOfTime(). So when you update your Refs
with new Values, you put the old value on the Ref's history list, you
also use the commit's UnitOfTime object and do
commitUnitOfTime.keepAlive(prevValue). This then guarantees the value
your replaced on the Ref will live up to the commit's UnitOfTime. Any
transaction starting before the commit is now guaranteed to be able to
find that old Value as the commitUnitOfTime will not GC until alll
previous UnitOfTime objects have GC'd. Which means all previous
Transaction objects have been GC'd.

You will need to keep a history list in Ref, but that history list
used WeakReference instead of a strong reference.

I hope this is a clearer explaination.

-Peter

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to