summaryrefslogtreecommitdiff
path: root/test/files/pos/Transactions.scala
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2006-04-06 09:49:46 +0000
committerIulian Dragos <jaguarul@gmail.com>2006-04-06 09:49:46 +0000
commit9ce18b19b66f73cd872158b6b28efd480fc5c5d1 (patch)
tree61885ddf670127e4b85f23f6d39d9c7ca1de79c2 /test/files/pos/Transactions.scala
parent99a204f18789c0e628cd73b8cb485fc46e57e3de (diff)
downloadscala-9ce18b19b66f73cd872158b6b28efd480fc5c5d1.tar.gz
scala-9ce18b19b66f73cd872158b6b28efd480fc5c5d1.tar.bz2
scala-9ce18b19b66f73cd872158b6b28efd480fc5c5d1.zip
Fixed several bugs in Inliners and the monitor ...
Fixed several bugs in Inliners and the monitor crash in jvm.
Diffstat (limited to 'test/files/pos/Transactions.scala')
-rw-r--r--test/files/pos/Transactions.scala114
1 files changed, 114 insertions, 0 deletions
diff --git a/test/files/pos/Transactions.scala b/test/files/pos/Transactions.scala
new file mode 100644
index 0000000000..8fb23268dc
--- /dev/null
+++ b/test/files/pos/Transactions.scala
@@ -0,0 +1,114 @@
+package scala.concurrent;
+
+class AbortException extends RuntimeException;
+
+object Transaction {
+ private var cnt = 0L
+ def nextId: long = synchronized {
+ cnt = cnt + 1; cnt
+ }
+
+ // Transaction status constants
+ val Running = 0
+ val Committed = 1
+ val Abortable = 2
+ val Aborted = 3
+ val Compound = 4
+
+ def atomic[T](b: Transaction => T): Option[T] =
+ (new Transaction).run(b)
+}
+
+class Transaction {
+ var status: int = _
+
+ var id: long = _ // only for real transactions
+
+ var head: Transaction = this
+ var next: Transaction = null
+
+ def this(hd: Transaction, tl: Transaction) = { this(); this.head = head; this.next = next }
+
+ def makeAbort() = synchronized {
+ while (status != Transaction.Aborted && status != Transaction.Committed) {
+ status = Transaction.Abortable
+ wait()
+ }
+ }
+ private def abort() = synchronized { status = Transaction.Aborted; notifyAll() }
+ private def commit() = synchronized { status = Transaction.Committed; notifyAll() }
+ def run[T](b: Transaction => T): Option[T] =
+ try {
+ status = Transaction.Running
+ id = Transaction.nextId
+ val result = Some(b(this))
+ commit()
+ result
+ } catch {
+ case ex: AbortException => abort(); None
+ case ex: Throwable => abort(); throw ex
+ }
+
+}
+
+trait Transactional {
+
+ /** create a new snapshot */
+ def checkPoint(): unit
+
+ /** copy back snapshot */
+ def rollBack(): unit
+
+ var readers: Transaction
+ var writer: Transaction
+
+ def currentWriter(): Transaction = null
+ if (writer == null) null
+ else if (writer.status == Transaction.Running) writer
+ else {
+ if (writer.status != Transaction.Committed) rollBack();
+ writer = null;
+ null
+ }
+
+ def getter(thisTrans: Transaction): unit = {
+ if (writer == thisTrans) return
+ var r = readers
+ while (r != null && r.head.status != Transaction.Running) { r = r.next; readers = r }
+ while (r != null) {
+ if (r.head == thisTrans) return
+ val last = r
+ r = r.next
+ while (r != null && r.head.status != Transaction.Running) { r = r.next; last.next = r }
+ }
+ synchronized {
+ if (thisTrans.status == Transaction.Abortable) throw new AbortException
+ val w = currentWriter()
+ if (w != null)
+ if (thisTrans.id < w.id) { w.makeAbort(); rollBack(); writer = null }
+ else throw new AbortException
+ readers = if (readers == null) thisTrans else new Transaction(thisTrans, readers)
+ }
+ }
+
+ def setter(thisTrans: Transaction): unit = {
+ if (writer == thisTrans) return
+ synchronized {
+ val w = currentWriter()
+ if (w != null)
+ if (thisTrans.id < w.id) { w.makeAbort(); rollBack() }
+ else throw new AbortException
+ var r = readers
+ while (r != null && r.head.status != Transaction.Running) { r = r.next; readers = r }
+ while (r != null) {
+ if (r.id < thisTrans.id) throw new AbortException
+ else w.makeAbort()
+ val last = r
+ r = r.next
+ while (r != null && r.head.status != Transaction.Running) { r = r.next; last.next = r }
+ }
+ checkPoint()
+ }
+ }
+}
+