diff src/EDU/oswego/cs/dl/util/concurrent/SyncMap.java @ 0:3dc0c5604566

Initial checkin of blitz 2.0 fcs - no installer yet.
author Dan Creswell <dan.creswell@gmail.com>
date Sat, 21 Mar 2009 11:00:06 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/EDU/oswego/cs/dl/util/concurrent/SyncMap.java	Sat Mar 21 11:00:06 2009 +0000
@@ -0,0 +1,307 @@
+/*
+  File: SyncMap.java
+
+  Originally written by Doug Lea and released into the public domain.
+  This may be used for any purposes whatsoever without acknowledgment.
+  Thanks for the assistance and support of Sun Microsystems Labs,
+  and everyone contributing, testing, and using this code.
+
+  History:
+  Date       Who                What
+   1Aug1998  dl               Create public version
+*/
+
+package EDU.oswego.cs.dl.util.concurrent;
+import java.util.*;
+
+/**
+ * SyncMaps wrap Sync-based control around java.util.Maps.
+ * They operate in the same way as SyncCollection.
+ * <p>
+ * Reader operations are
+ * <ul>
+ *  <li> size
+ *  <li> isEmpty
+ *  <li> get
+ *  <li> containsKey
+ *  <li> containsValue
+ *  <li> keySet
+ *  <li> entrySet
+ *  <li> values
+ * </ul>
+ * Writer operations are:
+ * <ul>
+ *  <li> put
+ *  <li> putAll
+ *  <li> remove
+ *  <li> clear
+ * </ul>
+ *  
+ * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
+ * @see SyncCollection
+**/
+
+
+public class SyncMap implements Map {
+  protected final Map c_;	   // Backing Map
+  protected final Sync rd_;  //  sync for read-only methods
+  protected final Sync wr_;  //  sync for mutative methods
+
+  protected final SynchronizedLong syncFailures_ = new SynchronizedLong(0);
+
+  /**
+   * Create a new SyncMap protecting the given map,
+   * and using the given sync to control both reader and writer methods.
+   * Common, reasonable choices for the sync argument include
+   * Mutex, ReentrantLock, and Semaphores initialized to 1.
+   **/
+  public SyncMap(Map map, Sync sync) {
+    this (map, sync, sync);
+  }
+
+
+  /**
+   * Create a new SyncMap protecting the given map,
+   * and using the given ReadWriteLock to control reader and writer methods.
+   **/
+  public SyncMap(Map map, ReadWriteLock rwl) {
+    this (map, rwl.readLock(), rwl.writeLock());
+  }
+
+  /**
+   * Create a new SyncMap protecting the given map,
+   * and using the given pair of locks to control reader and writer methods.
+   **/
+  public SyncMap(Map map, Sync readLock, Sync writeLock) {
+    c_ = map; 
+    rd_ = readLock;
+    wr_ = writeLock;
+  }
+
+  /** 
+   * Return the Sync object managing read-only operations
+   **/
+      
+  public Sync readerSync() {
+    return rd_;
+  }
+
+  /** 
+   * Return the Sync object managing mutative operations
+   **/
+
+  public Sync writerSync() {
+    return wr_;
+  }
+
+  /**
+   * Return the number of synchronization failures for read-only operations
+   **/
+  public long syncFailures() {
+    return syncFailures_.get();
+  }
+
+
+  /** Try to acquire sync before a reader operation; record failure **/
+  protected boolean beforeRead() {
+    try {
+      rd_.acquire();
+      return false;
+    }
+    catch (InterruptedException ex) { 
+      syncFailures_.increment();
+      return true; 
+    }
+  }
+
+  /** Clean up after a reader operation **/
+  protected void afterRead(boolean wasInterrupted) {
+    if (wasInterrupted) {
+      Thread.currentThread().interrupt();
+    }
+    else
+      rd_.release();
+  }
+
+
+
+  public int hashCode() {
+    boolean wasInterrupted = beforeRead();
+    try {
+      return c_.hashCode();
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+  public boolean equals(Object o) {
+    boolean wasInterrupted = beforeRead();
+    try {
+      return c_.equals(o);
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+  public int size() {
+    boolean wasInterrupted = beforeRead();
+    try {
+      return c_.size();
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+  public boolean isEmpty() {
+    boolean wasInterrupted = beforeRead();
+    try {
+      return c_.isEmpty();
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+  public boolean containsKey(Object o) {
+    boolean wasInterrupted = beforeRead();
+    try {
+      return c_.containsKey(o);
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+  public boolean containsValue(Object o) {
+    boolean wasInterrupted = beforeRead();
+    try {
+      return c_.containsValue(o);
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+  public Object get(Object key) {
+    boolean wasInterrupted = beforeRead();
+    try {
+      return c_.get(key);
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+
+  public Object put(Object key, Object value) {
+    try {
+      wr_.acquire();
+      try {
+        return c_.put(key, value);
+      }
+      finally {
+        wr_.release();
+      }
+    }
+    catch (InterruptedException ex) {
+      Thread.currentThread().interrupt();
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  public Object remove(Object key) {
+    try {
+      wr_.acquire();
+      try {
+        return c_.remove(key);
+      }
+      finally {
+        wr_.release();
+      }
+    }
+    catch (InterruptedException ex) {
+      Thread.currentThread().interrupt();
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  public void putAll(Map coll) {
+    try {
+      wr_.acquire();
+      try {
+        c_.putAll(coll);
+      }
+      finally {
+        wr_.release();
+      }
+    }
+    catch (InterruptedException ex) {
+      Thread.currentThread().interrupt();
+      throw new UnsupportedOperationException();
+    }
+  }
+
+	
+  public void clear() {
+    try {
+      wr_.acquire();
+      try {
+        c_.clear();
+      }
+      finally {
+        wr_.release();
+      }
+    }
+    catch (InterruptedException ex) {
+      Thread.currentThread().interrupt();
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  private transient Set keySet_ = null;
+  private transient Set entrySet_ = null;
+  private transient Collection values_ = null;
+  
+  public Set keySet() {
+    boolean wasInterrupted = beforeRead();
+    try {
+      if (keySet_ == null)
+        keySet_ = new SyncSet(c_.keySet(), rd_, wr_);
+      return keySet_;
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+  public Set entrySet() {
+    boolean wasInterrupted = beforeRead();
+    try {
+      if (entrySet_ == null)
+        entrySet_ = new SyncSet(c_.entrySet(), rd_, wr_);
+      return entrySet_;
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+
+  public Collection values() {
+    boolean wasInterrupted = beforeRead();
+    try {
+      if (values_ == null)
+        values_ = new SyncCollection(c_.values(), rd_, wr_);
+      return values_;
+    }
+    finally {
+      afterRead(wasInterrupted);
+    }
+  }
+
+}
+
+