Skip to content

Commit 882d76b

Browse files
committed
Add util for creating InMemory impls
1 parent 38be3be commit 882d76b

File tree

7 files changed

+229
-2
lines changed

7 files changed

+229
-2
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package japgolly.microlibs
22

3-
package object utils {
3+
package object utils extends utils.PackageShared {
44
val Platform: Platform = PlatformJS
55
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package japgolly.microlibs
22

3-
package object utils {
3+
package object utils extends utils.PackageShared {
44
val Platform: Platform = PlatformJVM
55
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package japgolly.microlibs.utils
2+
3+
import java.util.concurrent.atomic.AtomicInteger
4+
5+
object IntIncrementer {
6+
7+
trait Dsl[F[_]] {
8+
9+
def apply(): F[Int] =
10+
apply(1)
11+
12+
def apply(startAt: Int): F[Int] =
13+
apply(identity, startAt)
14+
15+
def apply[A](f: Int => A): F[A] =
16+
apply(f, 1)
17+
18+
def apply[A](f: Int => A, startAt: Int): F[A]
19+
}
20+
21+
// ===================================================================================================================
22+
23+
object threadUnsafe extends Dsl[Function0] {
24+
override def apply[A](f: Int => A, startAt: Int): () => A = {
25+
var prev = startAt
26+
() => {
27+
prev += 1
28+
f(prev)
29+
}
30+
}
31+
}
32+
33+
object volatile extends Dsl[Function0] {
34+
override def apply[A](f: Int => A, startAt: Int): () => A = {
35+
@volatile var prev = startAt
36+
() => {
37+
prev += 1
38+
f(prev)
39+
}
40+
}
41+
}
42+
43+
object cas extends Dsl[Function0] {
44+
override def apply[A](f: Int => A, startAt: Int): () => A = {
45+
val prev = new AtomicInteger(startAt)
46+
() => f(prev.incrementAndGet())
47+
}
48+
}
49+
50+
def syncOn(lock: AnyRef): Dsl[Function0] =
51+
new Dsl[Function0] {
52+
override def apply[A](f: Int => A, startAt: Int): () => A = {
53+
var prev = startAt
54+
() => {
55+
val n = lock.synchronized { prev += 1; prev }
56+
f(n)
57+
}
58+
}
59+
}
60+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package japgolly.microlibs.utils
2+
3+
import java.util.concurrent.atomic.AtomicLong
4+
5+
object LongIncrementer {
6+
7+
trait Dsl[F[_]] {
8+
9+
def apply(): F[Long] =
10+
apply(1L)
11+
12+
def apply(startAt: Long): F[Long] =
13+
apply(identity, startAt)
14+
15+
def apply[A](f: Long => A): F[A] =
16+
apply(f, 1L)
17+
18+
def apply[A](f: Long => A, startAt: Long): F[A]
19+
}
20+
21+
// ===================================================================================================================
22+
23+
object threadUnsafe extends Dsl[Function0] {
24+
override def apply[A](f: Long => A, startAt: Long): () => A = {
25+
var prev = startAt
26+
() => {
27+
prev += 1
28+
f(prev)
29+
}
30+
}
31+
}
32+
33+
object volatile extends Dsl[Function0] {
34+
override def apply[A](f: Long => A, startAt: Long): () => A = {
35+
@volatile var prev = startAt
36+
() => {
37+
prev += 1
38+
f(prev)
39+
}
40+
}
41+
}
42+
43+
object cas extends Dsl[Function0] {
44+
override def apply[A](f: Long => A, startAt: Long): () => A = {
45+
val prev = new AtomicLong(startAt)
46+
() => f(prev.incrementAndGet())
47+
}
48+
}
49+
50+
def syncOn(lock: AnyRef): Dsl[Function0] =
51+
new Dsl[Function0] {
52+
override def apply[A](f: Long => A, startAt: Long): () => A = {
53+
var prev = startAt
54+
() => {
55+
val n = lock.synchronized { prev += 1; prev }
56+
f(n)
57+
}
58+
}
59+
}
60+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package japgolly.microlibs.utils
2+
3+
import scala.runtime.AbstractFunction0
4+
5+
trait MutableFn0[A] extends AbstractFunction0[A] {
6+
def getFn: () => A
7+
def setFn(f: () => A): this.type
8+
9+
final def set(f: => A): this.type =
10+
setFn(() => f)
11+
}
12+
13+
object MutableFn0 {
14+
15+
def fromVariable[A](v: Variable[() => A]): MutableFn0[A] =
16+
new MutableFn0[A] {
17+
18+
override def apply(): A =
19+
v.get()()
20+
21+
override def getFn: () => A =
22+
v.get()
23+
24+
override def setFn(f: () => A): this.type = {
25+
v.set(f)
26+
this
27+
}
28+
}
29+
30+
class Dsl[A](make: (() => A) => Variable[() => A]) {
31+
32+
def apply(a: => A): MutableFn0[A] =
33+
withFn(() => a)
34+
35+
def withFn(f: () => A): MutableFn0[A] =
36+
MutableFn0.fromVariable(make(f))
37+
}
38+
39+
class DslWithDefault[A](default: () => A, make: (() => A) => Variable[() => A]) extends Dsl(make) {
40+
def apply(): MutableFn0[A] =
41+
withFn(default)
42+
}
43+
44+
class DslWithDefaultSelector[A](default: () => A) {
45+
def threadUnsafe = new DslWithDefault[A](default, Variable(_))
46+
def volatile = new DslWithDefault[A](default, Variable.volatile(_))
47+
def syncOn(lock: AnyRef) = new DslWithDefault[A](default, Variable.syncOn(lock))
48+
}
49+
50+
// ===================================================================================================================
51+
52+
def withDefault[A](a: => A): DslWithDefaultSelector[A] =
53+
new DslWithDefaultSelector[A](() => a)
54+
55+
def threadUnsafe[A] = new Dsl[A](Variable(_))
56+
def volatile[A] = new Dsl[A](Variable.volatile(_))
57+
def syncOn[A](lock: AnyRef) = new Dsl[A](Variable.syncOn(lock))
58+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package japgolly.microlibs.utils
2+
3+
import java.time.Instant
4+
5+
trait PackageShared {
6+
7+
final type MutableClock = MutableFn0[Instant]
8+
object MutableClock extends MutableFn0.DslWithDefaultSelector[Instant](() => Instant.now())
9+
10+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package japgolly.microlibs.utils
2+
3+
trait Variable[@specialized A] { self =>
4+
def get(): A
5+
def mod(f: A => A): A
6+
7+
def set(a: A): A =
8+
mod(_ => a)
9+
10+
def xmap[B](f: A => B)(g: B => A): Variable[B] =
11+
new Variable[B] {
12+
override def get() = f(self.get())
13+
override def mod(h: B => B) = f(self.mod(a => g(h(f(a)))))
14+
}
15+
}
16+
17+
object Variable {
18+
19+
def apply[@specialized A](init: A): Variable[A] =
20+
new Variable[A] {
21+
private[this] var value = init
22+
override def get() = value
23+
override def mod(f: A => A) = { value = f(value); value }
24+
}
25+
26+
def volatile[@specialized A](init: A): Variable[A] =
27+
new Variable[A] {
28+
@volatile private[this] var value = init
29+
override def get() = value
30+
override def mod(f: A => A) = { value = f(value); value }
31+
}
32+
33+
def syncOn[@specialized A](lock: AnyRef)(init: A): Variable[A] =
34+
new Variable[A] {
35+
private[this] var value = init
36+
override def get() = lock.synchronized(value)
37+
override def mod(f: A => A) = lock.synchronized { value = f(value); value }
38+
}
39+
}

0 commit comments

Comments
 (0)