Add basic java api for scala stm to transactor module
Note: this commit will be reverted once a java api is published for scala stm. Adding to transactor module for M3 release.
This commit is contained in:
parent
2757869c62
commit
2058765485
5 changed files with 290 additions and 1 deletions
|
|
@ -0,0 +1,112 @@
|
|||
/* scala-stm - (c) 2009-2011, Stanford University, PPL */
|
||||
|
||||
package scala.concurrent.stm
|
||||
|
||||
import java.util.concurrent.Callable
|
||||
import scala.runtime.AbstractFunction1
|
||||
|
||||
/**
|
||||
* Java-friendly API.
|
||||
*/
|
||||
object JavaAPI {
|
||||
|
||||
/**
|
||||
* Create a Ref with an initial value. Return a `Ref.View`, which does not
|
||||
* require implicit transactions.
|
||||
* @param initialValue the initial value for the newly created `Ref.View`
|
||||
* @return a new `Ref.View`
|
||||
*/
|
||||
def newRef[A](initialValue: A): Ref.View[A] = Ref(initialValue).single
|
||||
|
||||
/**
|
||||
* Create an empty TMap. Return a `TMap.View`, which does not require
|
||||
* implicit transactions.
|
||||
* @return a new, empty `TMap.View`
|
||||
*/
|
||||
def newTMap[A, B](): TMap.View[A, B] = TMap.empty[A, B].single
|
||||
|
||||
/**
|
||||
* Create an empty TSet. Return a `TSet.View`, which does not require
|
||||
* implicit transactions.
|
||||
* @return a new, empty `TSet.View`
|
||||
*/
|
||||
def newTSet[A](): TSet.View[A] = TSet.empty[A].single
|
||||
|
||||
/**
|
||||
* Create a TArray containing `length` elements. Return a `TArray.View`,
|
||||
* which does not require implicit transactions.
|
||||
* @param length the length of the `TArray.View` to be created
|
||||
* @return a new `TArray.View` containing `length` elements (initially null)
|
||||
*/
|
||||
def newTArray[A <: AnyRef](length: Int): TArray.View[A] = TArray.ofDim[A](length)(ClassManifest.classType(AnyRef.getClass)).single
|
||||
|
||||
/**
|
||||
* Atomic block that takes a `Runnable`.
|
||||
* @param runnable the `Runnable` to run within a transaction
|
||||
*/
|
||||
def atomic(runnable: Runnable): Unit = scala.concurrent.stm.atomic { txn ⇒ runnable.run }
|
||||
|
||||
/**
|
||||
* Atomic block that takes a `Callable`.
|
||||
* @param callable the `Callable` to run within a transaction
|
||||
* @return the value returned by the `Callable`
|
||||
*/
|
||||
def atomic[A](callable: Callable[A]): A = scala.concurrent.stm.atomic { txn ⇒ callable.call }
|
||||
|
||||
/**
|
||||
* Transform the value stored by `ref` by applying the function `f`.
|
||||
* @param ref the `Ref.View` to be transformed
|
||||
* @param f the function to be applied
|
||||
*/
|
||||
def transform[A](ref: Ref.View[A], f: AbstractFunction1[A, A]): Unit = ref.transform(f)
|
||||
|
||||
/**
|
||||
* Transform the value stored by `ref` by applying the function `f` and
|
||||
* return the old value.
|
||||
* @param ref the `Ref.View` to be transformed
|
||||
* @param f the function to be applied
|
||||
* @return the old value of `ref`
|
||||
*/
|
||||
def getAndTransform[A](ref: Ref.View[A], f: AbstractFunction1[A, A]): A = ref.getAndTransform(f)
|
||||
|
||||
/**
|
||||
* Transform the value stored by `ref` by applying the function `f` and
|
||||
* return the new value.
|
||||
* @param ref the `Ref.View` to be transformed
|
||||
* @param f the function to be applied
|
||||
* @return the new value of `ref`
|
||||
*/
|
||||
def transformAndGet[A](ref: Ref.View[A], f: AbstractFunction1[A, A]): A = ref.transformAndGet(f)
|
||||
|
||||
/**
|
||||
* Increment the `java.lang.Integer` value of a `Ref.View`.
|
||||
* @param ref the `Ref.View<Integer>` to be incremented
|
||||
* @param delta the amount to increment
|
||||
*/
|
||||
def increment(ref: Ref.View[java.lang.Integer], delta: Int): Unit = ref.transform { v ⇒ v.intValue + delta }
|
||||
|
||||
/**
|
||||
* Increment the `java.lang.Long` value of a `Ref.View`.
|
||||
* @param ref the `Ref.View<Long>` to be incremented
|
||||
* @param delta the amount to increment
|
||||
*/
|
||||
def increment(ref: Ref.View[java.lang.Long], delta: Long): Unit = ref.transform { v ⇒ v.longValue + delta }
|
||||
|
||||
/**
|
||||
* Add a task to run after the current transaction has committed.
|
||||
* @param task the `Runnable` task to run after transaction commit
|
||||
*/
|
||||
def afterCommit(task: Runnable): Unit = {
|
||||
val txn = Txn.findCurrent
|
||||
if (txn.isDefined) Txn.afterCommit(status ⇒ task.run)(txn.get)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a task to run after the current transaction has rolled back.
|
||||
* @param task the `Runnable` task to run after transaction rollback
|
||||
*/
|
||||
def afterRollback(task: Runnable): Unit = {
|
||||
val txn = Txn.findCurrent
|
||||
if (txn.isDefined) Txn.afterRollback(status ⇒ task.run)(txn.get)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/* scala-stm - (c) 2009-2011, Stanford University, PPL */
|
||||
|
||||
package scala.concurrent.stm;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import scala.concurrent.stm.Ref;
|
||||
import static scala.concurrent.stm.JavaAPI.*;
|
||||
|
||||
import scala.runtime.AbstractFunction1;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static scala.collection.JavaConversions.*;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
public class JavaAPITests {
|
||||
@Test
|
||||
public void createIntegerRef() {
|
||||
Ref.View<Integer> ref = newRef(0);
|
||||
int unboxed = ref.get();
|
||||
assertEquals(0, unboxed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atomicWithRunnable() {
|
||||
final Ref.View<Integer> ref = newRef(0);
|
||||
atomic(new Runnable() {
|
||||
public void run() {
|
||||
ref.set(10);
|
||||
}
|
||||
});
|
||||
int value = ref.get();
|
||||
assertEquals(10, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atomicWithCallable() {
|
||||
final Ref.View<Integer> ref = newRef(0);
|
||||
int oldValue = atomic(new Callable<Integer>() {
|
||||
public Integer call() {
|
||||
return ref.swap(10);
|
||||
}
|
||||
});
|
||||
assertEquals(0, oldValue);
|
||||
int newValue = ref.get();
|
||||
assertEquals(10, newValue);
|
||||
}
|
||||
|
||||
@Test(expected = TestException.class)
|
||||
public void failingTransaction() {
|
||||
final Ref.View<Integer> ref = newRef(0);
|
||||
try {
|
||||
atomic(new Runnable() {
|
||||
public void run() {
|
||||
ref.set(10);
|
||||
throw new TestException();
|
||||
}
|
||||
});
|
||||
} catch (TestException e) {
|
||||
int value = ref.get();
|
||||
assertEquals(0, value);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transformInteger() {
|
||||
Ref.View<Integer> ref = newRef(0);
|
||||
transform(ref, new AbstractFunction1<Integer, Integer>() {
|
||||
public Integer apply(Integer i) {
|
||||
return i + 10;
|
||||
}
|
||||
});
|
||||
int value = ref.get();
|
||||
assertEquals(10, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void incrementInteger() {
|
||||
Ref.View<Integer> ref = newRef(0);
|
||||
increment(ref, 10);
|
||||
int value = ref.get();
|
||||
assertEquals(10, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void incrementLong() {
|
||||
Ref.View<Long> ref = newRef(0L);
|
||||
increment(ref, 10L);
|
||||
long value = ref.get();
|
||||
assertEquals(10L, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAndUseTMap() {
|
||||
TMap.View<Integer, String> tmap = newTMap();
|
||||
Map<Integer, String> map = mutableMapAsJavaMap(tmap);
|
||||
map.put(1, "one");
|
||||
map.put(2, "two");
|
||||
assertEquals("one", map.get(1));
|
||||
assertEquals("two", map.get(2));
|
||||
assertTrue(map.containsKey(2));
|
||||
map.remove(2);
|
||||
assertFalse(map.containsKey(2));
|
||||
}
|
||||
|
||||
@Test(expected = TestException.class)
|
||||
public void failingTMapTransaction() {
|
||||
TMap.View<Integer, String> tmap = newTMap();
|
||||
final Map<Integer, String> map = mutableMapAsJavaMap(tmap);
|
||||
try {
|
||||
atomic(new Runnable() {
|
||||
public void run() {
|
||||
map.put(1, "one");
|
||||
map.put(2, "two");
|
||||
assertTrue(map.containsKey(1));
|
||||
assertTrue(map.containsKey(2));
|
||||
throw new TestException();
|
||||
}
|
||||
});
|
||||
} catch (TestException e) {
|
||||
assertFalse(map.containsKey(1));
|
||||
assertFalse(map.containsKey(2));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAndUseTSet() {
|
||||
TSet.View<String> tset = newTSet();
|
||||
Set<String> set = mutableSetAsJavaSet(tset);
|
||||
set.add("one");
|
||||
set.add("two");
|
||||
assertTrue(set.contains("one"));
|
||||
assertTrue(set.contains("two"));
|
||||
assertEquals(2, set.size());
|
||||
set.add("one");
|
||||
assertEquals(2, set.size());
|
||||
set.remove("two");
|
||||
assertFalse(set.contains("two"));
|
||||
assertEquals(1, set.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAndUseTArray() {
|
||||
TArray.View<String> tarray = newTArray(3);
|
||||
List<String> seq = mutableSeqAsJavaList(tarray);
|
||||
assertEquals(null, seq.get(0));
|
||||
assertEquals(null, seq.get(1));
|
||||
assertEquals(null, seq.get(2));
|
||||
seq.set(0, "zero");
|
||||
seq.set(1, "one");
|
||||
seq.set(2, "two");
|
||||
assertEquals("zero", seq.get(0));
|
||||
assertEquals("one", seq.get(1));
|
||||
assertEquals("two", seq.get(2));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/* scala-stm - (c) 2009-2011, Stanford University, PPL */
|
||||
|
||||
package scala.concurrent.stm;
|
||||
|
||||
public class TestException extends RuntimeException {
|
||||
public TestException() {
|
||||
super("Expected failure");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/* scala-stm - (c) 2009-2011, Stanford University, PPL */
|
||||
|
||||
package scala.concurrent.stm
|
||||
|
||||
import org.scalatest.junit.JUnitWrapperSuite
|
||||
|
||||
class JavaAPISuite extends JUnitWrapperSuite("scala.concurrent.stm.JavaAPITests", Thread.currentThread.getContextClassLoader)
|
||||
|
|
@ -450,7 +450,7 @@ object Dependency {
|
|||
val Netty = "3.2.5.Final"
|
||||
val Protobuf = "2.4.1"
|
||||
val Rabbit = "2.3.1"
|
||||
val ScalaStm = "0.5.0-SNAPSHOT"
|
||||
val ScalaStm = "0.4"
|
||||
val Scalatest = "1.6.1"
|
||||
val Slf4j = "1.6.4"
|
||||
val Spring = "3.0.5.RELEASE"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue