org.multiverse.api.programmatic
Interface ProgrammaticRef<E>


public interface ProgrammaticRef<E>

The ProgrammaticRef is a managed reference specially made for projects that don't want to rely on instrumentation, but do want to have managed references.

It provides a lot of methods and I don't think that exposing this method is very wise. I would expect that some nice language sugar is added on top.

If you also want to coordinate transactions without relying on instrumentation, you need to have a look at the TransactionTemplate

This ProgrammaticRef exposes in a lot of cases 3 types of methods:

  1. the original one: this method behaves nicely. If a method is available on the tranlocal it will lift on that. If there isn't, the method will be executed in its own transaction.
  2. one with a transaction as parameter: this method you want to use of you dont want to rely on the ThreadLocalTransaction, but want to pass transactions manually. These methods need to be used with an already running transaction
  3. one with atomic as postfix: these methods are very very fast. They don't look at an existing transaction at the ThreadLocalTransaction and will always succeed. The performance is comparable to that of a normal CAS. So use it very wisely
With the ProgrammaticRef it also is possible to have more than one stm in the same classloader; as long as transactionalobjects from different stms move into eachers space. If they do, you could have serious isolation problems or other failures at hand. If in the future this sharing problem will cause complaints, it is quite easy to add an STM field to each transactional objects.

Author:
Peter Veentjer

Method Summary
 boolean atomicCompareAndSet(E expected, E update)
          Executes a compare and swap without looking at a running transaction.
 E atomicGet()
          Gets the value without looking at an existing transaction (it will run its 'own').
 boolean atomicIsNull()
          Checks if the value stored in this reference is null.
 E atomicSet(E newValue)
          Sets the new value on this ProgrammaticRef using its own transaction (so it doesn't look at an existing transaction).
 E get()
          Gets the value.
 E get(Transaction tx)
          Gets the value using the specified transaction.
 E getOrAwait()
           
 E getOrAwait(Transaction tx)
           
 E getOrAwait(TransactionFactory txFactory)
           
 boolean isNull()
          Checks if the value stored in this reference is null.
 boolean isNull(Transaction tx)
          Checks if the value stored in this reference is null using the provided transaction.
 E set(E newValue)
          Sets the new value on this reference.
 E set(Transaction tx, E newValue)
          Sets the new value on this reference using the provided transaction.
 java.lang.String toString(Transaction tx)
           
 

Method Detail

get

E get()
Gets the value. If a Transaction already is running, it will lift on that transaction, if not the atomicGet() is used. In that cases it will be very very cheap (roughly 2/3 of the performance of atomicGet(). The reason why this call is more expensive than the atomicGet() is that a getThreadlocalTransaction needs to be called and a check on the Transaction if that is running.

Returns:
the current value stored in this reference.
Throws:
java.lang.IllegalThreadStateException - if the current transaction isn't in the right state for this operation.
ControlFlowError

get

E get(Transaction tx)
Gets the value using the specified transaction.

Parameters:
tx - the Transaction used for reading the value.
Returns:
the value currently stored, could be null.
Throws:
java.lang.NullPointerException - if tx is null
IllegalTransactionStateException - if the transaction is not in the correct state for this operation.
ControlFlowError

atomicGet

E atomicGet()
Gets the value without looking at an existing transaction (it will run its 'own').

This is a very cheap call since only one volatile read is needed an no additional objects are created. On my machine I'm able to do 150.000.000 atomic gets per second on a single thread to give some indication.

The only expensive thing that needs to be done is a single volatile read. So it is in the same league as a AtomicReference.get(). To be more specific; it would have the same performance as AtomicReferenceFieldUpdater.get(Object) since that is used under water.

Returns:
the current value.
Throws:
ReadConflict - if something fails while loading the reference.

set

E set(E newValue)
Sets the new value on this reference. If an active transaction is available in the ThreadLocalTransaction that will be used. If not, the atomicSet(Object) is used (which is very fast).

Parameters:
newValue - the new value to be stored in this reference. The newValue is allowed to be null.
Returns:
the value that is replaced, can be null.
Throws:
WriteConflict - if something failed while committing. If the commit fails, nothing bad will happen.
ReadConflict - if something fails while loading the reference.
java.lang.IllegalThreadStateException - if the transaction was not in the correct state for this operations. If the transaction in the TransactionThreadLocal is dead (so aborted or committed), a new transaction will be used.

set

E set(Transaction tx,
      E newValue)
Sets the new value on this reference using the provided transaction.

Use this call if you explicitly want to pass a transaction, instead of set(Object).

Parameters:
tx - the transaction to use.
newValue - the new value, and is allowed to be null.
Returns:
the previous value stored in this reference.
Throws:
IllegalTransactionStateException - if the transaction isn't in the correct state for this operation.
ReadConflict - if something fails while loading the reference.
java.lang.NullPointerException - if tx is null

atomicSet

E atomicSet(E newValue)
Sets the new value on this ProgrammaticRef using its own transaction (so it doesn't look at an existing transaction). This call is very fast (11M transactions/second on my machine with a single thread. It could be that this called is delayed because it is retried. If you want to fail immediately, check the atomicCompareAndSet(Object, Object)

Parameters:
newValue - the new value.
Returns:
the old value.
Throws:
WriteConflict - if something failed while committing. If the commit fails, nothing bad will happen.
ReadConflict - if something fails while loading the reference.

atomicCompareAndSet

boolean atomicCompareAndSet(E expected,
                            E update)
Executes a compare and swap without looking at a running transaction. This call essentially is being executed under its own transaction.

Parameters:
expected - the expected value
update - the update
Returns:
true if was a success, false otherwise.

isNull

boolean isNull()
Checks if the value stored in this reference is null.

If a Transaction currently is active, it will lift on that transaction. If not, the atomicIsNull is used, so very very cheap. See the get() for more info since that method is used to retrieve the current value.

Returns:
true if the reference currently is null.
Throws:
ReadConflict - if something fails while loading the reference.

isNull

boolean isNull(Transaction tx)
Checks if the value stored in this reference is null using the provided transaction.

Parameters:
tx - the transaction used
Returns:
true if the value is null, false otherwise.
Throws:
java.lang.NullPointerException - if tx is null.
DeadTransactionException - is tx isn't active
ReadConflict - if something fails while loading the reference.

atomicIsNull

boolean atomicIsNull()
Checks if the value stored in this reference is null. This method doesn't lift on a transaction, so it is very very cheap. See the atomicGet() for more information.

Returns:
true if the reference is null, false otherwise.
Throws:
ReadConflict - if something fails while loading the reference.

getOrAwait

E getOrAwait()

getOrAwait

E getOrAwait(TransactionFactory txFactory)

getOrAwait

E getOrAwait(Transaction tx)
Parameters:
tx -
Returns:
Throws:
java.lang.NullPointerException - if tx is null

toString

java.lang.String toString(Transaction tx)


Copyright © 2008-2010 Multiverse. All Rights Reserved.