[concurrency-interest] Stricter read ordering

Howard Lovatt howard.lovatt at gmail.com
Fri Apr 25 17:08:25 EDT 2014


Hi Tobias,

I find that if you can restructure your code to use immutable data and therefore avoid any locks, e.g. using streams, then this is the fastest. However you may not be able to or have the resources to do so, in which case I use a compromise of copy on write:

class DataCarrier {
  final int x, y, offset; // These are final to ensure copy on write
  DataCarrier(int x, int y, int offset) { this.x = x; this.y = y; this.offset = offset; }
}

class VersionedData {
  private static class DataCarrierCOW {
    private volatile DataCarrier data;
    DataCarrierCOW(DataCarrier data) { this.data = data; }
    synchronized void update(DataCarrier data) { this.data = data; }
    DataCarrier read() { return data; }
  }
  private final DataCarrierCOW[] datas; // I know data is also plural, but datas is clearer!
  VersionedData( ... ) { ... } // Copy the data into the array "datas"
  void update(Iterable<DataCarrier> cursors) { 
    for (DataCarrier cursor : cursors) {
      datas[cursor.offset].update(cursor);
    }
  }
  DataCarrier read(int offset) { return datas[offset].read(); }
}


Something like the above could be worth trying. It has worked well for me in the past. 

 -- Howard. 

Sent from my iPad

> On 24 Apr 2014, at 1:28 am, Tobias Lindaaker <thobes at gmail.com> wrote:
> 
> class VersionedData {
>   // this is the overhead I use to manage consistency
>   private final volatile long written;
>   private final volatile long next;
> 
>   // the protected data, this typically a memory mapped file
>   private final ByteBuffer buffer;
>   VersionedData( ByteBuffer buffer ) { this.buffer = buffer; }
>   
>   public synchronized void update( Iterable<DataCarrier> data ) {
>     long next = this.next + 1;
>     this.next = next;
>     for (DataCarrier cursor : data) {
>       int offset = data.offset * 8;
>       buffer.putInt( offset    , data.x );
>       buffer.putInt( offset + 4, data.y );
>     }
>     this.written = next;
>   }
> 
>   public void read(DataCarrier cursor) {
>     // I allow multiple readers, so this method is not synchronized
>     int x, y, offset = cursor.offset * 8;
>     long version;
>     do {
>       version = this.written;
>       x = buffer.getInt(offset);
>       y = buffer.getInt(offset + 4);
>     } while ( version != this.next );
>     cursor.x = x;
>     cursor.y = y;
>   }
> }
> 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20140426/03a3534e/attachment.html>


More information about the Concurrency-interest mailing list