Class ThreadLocalDirectory<AGGREGATOR,SAMPLE>

java.lang.Object
com.yahoo.concurrent.ThreadLocalDirectory<AGGREGATOR,SAMPLE>
Type Parameters:
AGGREGATOR - the type input data is aggregated into
SAMPLE - the type of input data

public final class ThreadLocalDirectory<AGGREGATOR,SAMPLE> extends Object
A class for multiple producers and potentially multiple consumers (usually only one).

The consuming threads always unregisters the data producers when doing fetch(). This is the reason for having to do update through the directory. The reason for this is otherwise, we would either get reference leaks from registered objects belonging to dead threads if we did not unregister instances, otherwise the sampling thread would have to unregister the instance, and then we would create a memory relationship between all producing threads, which is exactly what this class aims to avoid.

A complete example from a test:

 private static class SumUpdater implements ThreadLocalDirectory.Updater<Integer, Integer> {

     @Override
     public Integer update(Integer current, Integer x) {
         return Integer.valueOf(current.intValue() + x.intValue());
     }

     @Override
     public Integer createGenerationInstance(Integer previous) {
         return Integer.valueOf(0);
     }
 }

 ... then the producers does (where r is in instance of
 ThreadLocalDirectory)...

 @Override
 public void run() {
     LocalInstance<Integer, Integer> s = r.getLocalInstance();
     for (int i = 0; i < 500; ++i) {
         r.update(Integer.valueOf(i), s);
     }
 }

 ... and the consumer...

 List<Integer> measurements = s.fetch()
 

Invoking r.fetch() will produce a list of integers from all the participating threads at any time.

Author:
Steinar Knutsen
  • Constructor Details

  • Method Details

    • fetch

      public List<AGGREGATOR> fetch()
      Fetch the current set of sampled data, and reset state of all thread local instances. The producer threads will not alter data in the list returned from this method.
      Returns:
      a list of data from all producer threads
    • view

      public List<AGGREGATOR> view()
      Get a view of the current data. This requires this ThreadLocalDirectory to have been instantiated with an updater implementing ObservableUpdater.
      Returns:
      a list of a copy of the current data in all producer threads
      Throws:
      IllegalStateException - if the updater does not implement ThreadLocalDirectory.ObservableUpdater
    • getLocalInstance

      public LocalInstance<AGGREGATOR,SAMPLE> getLocalInstance()
      Expose the thread local for the running thread, for use in conjunction with update(SAMPLE, LocalInstance<AGGREGATOR, SAMPLE>).
      Returns:
      the current thread's local instance
    • update

      public void update(SAMPLE x)
      Input data from a producer thread.
      Parameters:
      x - the data to insert
    • update

      public void update(SAMPLE x, LocalInstance<AGGREGATOR,SAMPLE> localInstance)
      Update a value with a given thread local instance.

      If a producer thread is to insert a series of data, it is desirable to limit the number of memory transactions to the theoretical minimum. Since reading a thread local is the memory equivalence of reading a volatile, it is then useful to avoid re-reading the running threads' input instance. For this scenario, fetch the running thread's instance with getLocalInstance(), and then insert the produced data with the multiple calls necessary to update(SAMPLE, LocalInstance<AGGREGATOR, SAMPLE>).

      Parameters:
      x - the data to insert
      localInstance - the local data insertion instance