Skip to content

Instantly share code, notes, and snippets.

@pathikrit
Last active September 7, 2016 19:30
Show Gist options
  • Select an option

  • Save pathikrit/6cbadf01ba35517561dd to your computer and use it in GitHub Desktop.

Select an option

Save pathikrit/6cbadf01ba35517561dd to your computer and use it in GitHub Desktop.
DataTables in Scala
trait DataTable[PK, C, V] {
type Row = C => V
type Filter = Row => Boolean
val table: PK => Row
def apply(id: PK): Row = table(id)
def keys: Iterable[PK]
def rows: Iterable[Row] = keys.map(apply)
def select(columns: Set[C]): DataTable[PK, C, V]
def filter(f: Filter): DataTable[PK, C, V]
}
object DataTable {
trait Mutable[PK, C, V] extends DataTable[PK, C, V] {
def update(id: PK, c: C, v: V): this.type
def +=(row: (PK, Map[C, V])): this.type = {
val (r, cols) = row
cols foreach {case (c, v) => this(r, c) = v}
this
}
}
implicit class Immutable[PK, C, V](override val table: collection.Map[PK, collection.Map[C, V]]) extends DataTable[PK, C, V] {
override def keys = table.keys
override def select(columns: Set[C]) = table.mapValues(_ filterKeys columns)
override def filter(f: Filter) = table filter {case (_, row) => f(row)}
}
import scala.collection.mutable.{Map => Dict}
class Concurrent[PK, C, V](table: Dict[PK, Dict[C, V]]) extends Immutable(table) with Mutable[PK, C, V] {
private[this] val lock = new ReadWriteLock
override def update(r: PK, c: C, v: V) = lock.doWrite {
table(r)(c) = v
this
}
override def select(columns: Set[C]) = lock.doRead {
super.select(columns)
}
override def filter(f: Filter) = lock.doRead {
super.filter(f)
}
}
object Concurrent {
def empty[PK, C, V] = new Concurrent(Dict.empty[PK, Dict[C, V]] withDefaultValue Dict.empty[C, V])
}
}
// A Scala friendly R/W lock wrapper class around Java's StampedLock
class ReadWriteLock {
val lock = new java.util.concurrent.locks.StampedLock()
def doRead[A](f: => A) = using[A](lock.readLock(), lock.unlockRead)(f)
def doWrite[A](f: => A) = using[A](lock.writeLock(), lock.unlockWrite)(f)
private[this] def using[A](stamp: Long, unlock: Long => Unit)(f: => A): A = try f finally unlock(stamp)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment