Skip to content

Commit 2dde352

Browse files
committed
Use atomic in TVectorBuffer (Exercise 6 of Chapter 7)
1 parent 009d221 commit 2dde352

File tree

1 file changed

+22
-42
lines changed
  • src/main/scala/org/learningconcurrency/exercises/ch7

1 file changed

+22
-42
lines changed

src/main/scala/org/learningconcurrency/exercises/ch7/ex6.scala

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,75 +8,55 @@ package ch7
88
object Ex6 extends App {
99
import scala.concurrent.stm._
1010

11+
/**
12+
* `Vector` based implementation.
13+
*/
1114
class TVectorBuffer[T] extends scala.collection.mutable.Buffer[T] {
12-
private[this] val buf: Ref[Vector[T]] = Ref(Vector.empty[T]) // should store the immutable object in order to use CAS operations.
13-
14-
@annotation.tailrec
15-
final def +=(elem: T): this.type = {
16-
val ts = buf.single()
17-
if (buf.single.compareAndSet(ts, ts :+ elem))
18-
this
19-
else
20-
+=(elem)
15+
private[this] val buf: Ref[Vector[T]] = Ref(Vector.empty[T])
16+
17+
def +=(elem: T): this.type = atomic { implicit txn =>
18+
buf() = buf() :+ elem
19+
this
2120
}
2221

23-
@annotation.tailrec
24-
final def +=:(elem: T): this.type = {
25-
val ts = buf.single()
26-
if (buf.single.compareAndSet(ts, elem +: ts))
27-
this
28-
else
29-
+=:(elem)
22+
def +=:(elem: T): this.type = atomic { implicit txn =>
23+
buf() = elem +: buf()
24+
this
3025
}
3126

3227
def apply(n: Int): T = buf.single()(n)
3328

34-
@annotation.tailrec
35-
final def clear(): Unit = {
36-
val ts = buf.single()
37-
if (!buf.single.compareAndSet(ts, Vector.empty[T]))
38-
clear()
39-
}
29+
def clear(): Unit = buf.single.set(Vector.empty[T])
4030

41-
@annotation.tailrec
42-
final def insertAll(n: Int, elems: collection.Traversable[T]): Unit = {
43-
val ts = buf.single()
31+
def insertAll(n: Int, elems: collection.Traversable[T]): Unit = atomic { implicit txn =>
32+
val ts = buf()
4433
val len = ts.length
4534
if (n < 0 || n > len) throw new IndexOutOfBoundsException(n.toString)
4635

4736
val left = ts.take(n)
4837
val right = ts.drop(n)
49-
val nts = left ++ elems ++ right
50-
if (!buf.single.compareAndSet(ts, nts))
51-
insertAll(n, elems)
38+
buf() = left ++ elems ++ right
5239
}
5340

5441
def length: Int = buf.single().length
5542

56-
@annotation.tailrec
57-
final def remove(n: Int): T = {
58-
val ts = buf.single()
43+
def remove(n: Int): T = atomic { implicit txn =>
44+
val ts = buf()
5945
val len = ts.length
6046
if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString)
6147

6248
val left = ts.take(n)
6349
val right = ts.drop(n + 1)
64-
val nts = left ++ right
65-
if (buf.single.compareAndSet(ts, nts))
66-
ts(n)
67-
else
68-
remove(n)
50+
buf() = left ++ right
51+
ts(n)
6952
}
7053

71-
@annotation.tailrec
72-
final def update(n: Int, newelem: T): Unit = {
73-
val ts = buf.single()
54+
def update(n: Int, newelem: T): Unit = atomic { implicit txn =>
55+
val ts = buf()
7456
val len = ts.length
7557
if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString)
7658

77-
val nts = ts.updated(n, newelem)
78-
if (!buf.single.compareAndSet(ts, nts))
79-
update(n, newelem)
59+
buf() = ts.updated(n, newelem)
8060
}
8161

8262
def iterator: Iterator[T] = buf.single().iterator

0 commit comments

Comments
 (0)