org.openide.util
Class Mutex

java.lang.Object
  extended by org.openide.util.Mutex

public final class Mutex
extends java.lang.Object

Read-many/write-one lock. Allows control over resources that can be read by several readers at once but only written by one writer.

It is guaranteed that if you are a writer you can also enter the mutex as a reader. Conversely, if you are the only reader you can enter the mutex as a writer, but you'll be warned because it is very deadlock prone (two readers trying to get write access concurently).

If the mutex is used only by one thread, the thread can repeatedly enter it as a writer or reader. So one thread can never deadlock itself, whichever order operations are performed in.

There is no strategy to prevent starvation. Even if there is a writer waiting to enter, another reader might enter the section instead.

Examples of use:

 Mutex m = new Mutex ();

 // Grant write access, compute an integer and return it:
 return (Integer)m.writeAccess (new Mutex.Action () {
   public Object run () {
     return new Integer (1);
   }
 });

 // Obtain read access, do some computation, possibly throw an IOException:
 try {
   m.readAccess (new Mutex.ExceptionAction () {
     public Object run () throws IOException {
       if (...) throw new IOException ();

       return null;
     }
   });
 } catch (MutexException ex) {
   throw (IOException)ex.getException ();
 }

 // check whether you are already in read access
 if (m.isReadAccess ()) {
   // do your work
 }
 

Author:
Ales Novak

Nested Class Summary
static interface Mutex.Action<T>
          Action to be executed in a mutex without throwing any checked exceptions.
static interface Mutex.ExceptionAction<T>
          Action to be executed in a mutex, possibly throwing checked exceptions.
static class Mutex.Privileged
          Provides access to Mutex's internal methods.
 
Field Summary
(package private) static boolean beStrict
          this is used from tests to prevent upgrade from readAccess to writeAccess by strictly throwing exception.
static Mutex EVENT
          Mutex that allows code to be synchronized with the AWT event dispatch thread.
 
Constructor Summary
Mutex()
          Default constructor.
Mutex(Mutex.Privileged privileged)
           
Mutex(Mutex.Privileged privileged, java.util.concurrent.Executor executor)
          Constructor for those who wish to do some custom additional tasks whenever an action or runnable is executed in the Mutex.
Mutex(java.lang.Object lock)
          Enhanced constructor that permits specifying an object to use as a lock.
 
Method Summary
(package private) static boolean isDispatchThread()
           
 boolean isReadAccess()
          Tests whether this thread has already entered the mutex in read access.
 boolean isWriteAccess()
          Tests whether this thread has already entered the mutex in write access.
 void postReadRequest(java.lang.Runnable run)
          Posts a read request.
 void postWriteRequest(java.lang.Runnable run)
          Posts a write request.
<T> T
readAccess(Mutex.Action<T> action)
          Run an action only with read access.
<T> T
readAccess(Mutex.ExceptionAction<T> action)
          Run an action with read access and possibly throw a checked exception.
 void readAccess(java.lang.Runnable action)
          Run an action with read access, returning no result.
 java.lang.String toString()
          toString
<T> T
writeAccess(Mutex.Action<T> action)
          Run an action with write access.
<T> T
writeAccess(Mutex.ExceptionAction<T> action)
          Run an action with write access and possibly throw an exception.
 void writeAccess(java.lang.Runnable action)
          Run an action with write access and return no result.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

EVENT

public static final Mutex EVENT
Mutex that allows code to be synchronized with the AWT event dispatch thread.

When the Mutex methods are invoked on this mutex, the methods' semantics change as follows:


beStrict

static boolean beStrict
this is used from tests to prevent upgrade from readAccess to writeAccess by strictly throwing exception. Otherwise we just notify that using ErrorManager.

Constructor Detail

Mutex

public Mutex(java.lang.Object lock)
Enhanced constructor that permits specifying an object to use as a lock. The lock is used on entry and exit to readAccess(org.openide.util.Mutex.Action) and during the whole execution of writeAccess(org.openide.util.Mutex.Action). The ability to specify locks allows several Mutexes to synchronize on one object or to synchronize a mutex with another critical section.

Parameters:
lock - lock to use

Mutex

public Mutex()
Default constructor.


Mutex

public Mutex(Mutex.Privileged privileged)
Parameters:
privileged - can enter privileged states of this Mutex This helps avoid creating of custom Runnables.

Mutex

public Mutex(Mutex.Privileged privileged,
             java.util.concurrent.Executor executor)
Constructor for those who wish to do some custom additional tasks whenever an action or runnable is executed in the Mutex. This may be useful for wrapping all the actions with custom ThreadLocal value, etc. Just implement the Executor's execute(Runnable) method and do pre and post initialization tasks before running the runnable.

The Executor.execute(java.lang.Runnable) method shall return only when the passed in Runnable is finished, otherwise methods like readAccess(Action) and co. might not return proper result.

Parameters:
privileged - can enter privileged states of this Mutex
executor - allows to wrap the work of the mutex with a custom code
Since:
7.12
Method Detail

readAccess

public <T> T readAccess(Mutex.Action<T> action)
Run an action only with read access. See class description re. entering for write access within the dynamic scope.

Parameters:
action - the action to perform
Returns:
the object returned from Mutex.Action.run()

readAccess

public <T> T readAccess(Mutex.ExceptionAction<T> action)
             throws MutexException
Run an action with read access and possibly throw a checked exception. The exception if thrown is then encapsulated in a MutexException and thrown from this method. One is encouraged to catch MutexException, obtain the inner exception, and rethrow it. Here is an example:

 try {
   mutex.readAccess (new ExceptionAction () {
     public void run () throws IOException {
       throw new IOException ();
     }
   });
  } catch (MutexException ex) {
    throw (IOException) ex.getException ();
  }
 
Note that runtime exceptions are always passed through, and neither require this invocation style, nor are encapsulated.

Parameters:
action - the action to execute
Returns:
the object returned from Mutex.ExceptionAction.run()
Throws:
MutexException - encapsulates a user exception
java.lang.RuntimeException - if any runtime exception is thrown from the run method
See Also:
readAccess(Mutex.Action)

readAccess

public void readAccess(java.lang.Runnable action)
Run an action with read access, returning no result. It may be run asynchronously.

Parameters:
action - the action to perform
See Also:
readAccess(Mutex.Action)

writeAccess

public <T> T writeAccess(Mutex.Action<T> action)
Run an action with write access. The same thread may meanwhile reenter the mutex; see the class description for details.

Parameters:
action - the action to perform
Returns:
the result of Mutex.Action.run()

writeAccess

public <T> T writeAccess(Mutex.ExceptionAction<T> action)
              throws MutexException
Run an action with write access and possibly throw an exception. Here is an example:

 try {
   mutex.writeAccess (new ExceptionAction () {
     public void run () throws IOException {
       throw new IOException ();
     }
   });
  } catch (MutexException ex) {
    throw (IOException) ex.getException ();
  }
 

Parameters:
action - the action to execute
Returns:
the result of Mutex.ExceptionAction.run()
Throws:
MutexException - an encapsulated checked exception, if any
java.lang.RuntimeException - if a runtime exception is thrown in the action
See Also:
writeAccess(Mutex.Action), readAccess(Mutex.ExceptionAction)

writeAccess

public void writeAccess(java.lang.Runnable action)
Run an action with write access and return no result. It may be run asynchronously.

Parameters:
action - the action to perform
See Also:
writeAccess(Mutex.Action), readAccess(Runnable)

isReadAccess

public boolean isReadAccess()
Tests whether this thread has already entered the mutex in read access. If it returns true, calling readAccess will be executed immediatelly without any blocking. Calling postWriteAccess will delay the execution of its Runnable until a readAccess section is over and calling writeAccess is strongly prohibited and will result in a warning as a deadlock prone behaviour.

Warning: since a thread with write access automatically has effective read access as well (whether or not explicitly requested), if you want to check whether a thread can read some data, you should check for either kind of access, e.g.:

assert myMutex.isReadAccess() || myMutex.isWriteAccess();

Returns:
true if the thread is in read access section
Since:
4.48

isWriteAccess

public boolean isWriteAccess()
Tests whether this thread has already entered the mutex in write access. If it returns true, calling writeAccess will be executed immediatelly without any other blocking. postReadAccess will be delayed until a write access runnable is over.

Returns:
true if the thread is in write access section
Since:
4.48

postReadRequest

public void postReadRequest(java.lang.Runnable run)
Posts a read request. This request runs immediately iff this Mutex is in the shared mode or this Mutex is not contended at all. This request is delayed if this Mutex is in the exclusive mode and is held by this thread, until the exclusive is left. Finally, this request blocks, if this Mutex is in the exclusive mode and is held by another thread.

Warning: this method blocks.

Parameters:
run - runnable to run

postWriteRequest

public void postWriteRequest(java.lang.Runnable run)
Posts a write request. This request runs immediately iff this Mutex is in the "pure" exclusive mode, i.e. this Mutex is not reentered in shared mode after the exclusive mode was acquired. Otherwise it is delayed until all read requests are executed. This request runs immediately if this Mutex is not contended at all. This request blocks if this Mutex is in the shared mode.

Warning: this method blocks.

Parameters:
run - runnable to run

toString

public java.lang.String toString()
toString

Overrides:
toString in class java.lang.Object

isDispatchThread

static boolean isDispatchThread()
Returns:
true iff current thread is EventDispatchThread