[mod] modified broadcastobject to mirror a real live broadcast better
- allow to watch until a specific or later frame has been cast - allow to return from watching if the broadcast is ended - allow to reset the broadcast to be reset - in retrospect this wasnt really needed for the project...
This commit is contained in:
@@ -35,6 +35,7 @@ object ScalaLocks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The conditional readlock waits for a condition to be met, before executing the provided read function
|
||||||
class ScalaConditionalReadLock(readLock: ReentrantReadWriteLock.ReadLock, writeLock: ReentrantReadWriteLock.WriteLock, signal: Condition) {
|
class ScalaConditionalReadLock(readLock: ReentrantReadWriteLock.ReadLock, writeLock: ReentrantReadWriteLock.WriteLock, signal: Condition) {
|
||||||
private val scalaWriteLock = new ScalaWriteLock(writeLock)
|
private val scalaWriteLock = new ScalaWriteLock(writeLock)
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ object ScalaLocks {
|
|||||||
|
|
||||||
object ConcurrentBroadcast {
|
object ConcurrentBroadcast {
|
||||||
|
|
||||||
class BroadcastObject[A]() {
|
class BroadcastObject[A](default: Option[A] = None) {
|
||||||
|
|
||||||
import ScalaLocks._
|
import ScalaLocks._
|
||||||
|
|
||||||
@@ -76,12 +77,15 @@ object ConcurrentBroadcast {
|
|||||||
private val writeLock = new ScalaWriteLock(javaWriteLock)
|
private val writeLock = new ScalaWriteLock(javaWriteLock)
|
||||||
private val readLock = new ScalaReadLock(javaReadLock)
|
private val readLock = new ScalaReadLock(javaReadLock)
|
||||||
|
|
||||||
private var value: Option[A] = None
|
private var frame: Int = 0 // should be a large enough buffer
|
||||||
|
private var broadcastEnded = false
|
||||||
|
private var value: Option[A] = default
|
||||||
|
|
||||||
// NON-BLOCKING: check if value has been set, write new value and return if it was overwritten
|
// NON-BLOCKING: check if value has been set, write new value and return if it was overwritten
|
||||||
def broadcast(newValue: A): Unit = {
|
def broadcast(newValue: A): Unit = {
|
||||||
writeLock(() => {
|
writeLock(() => {
|
||||||
value = Some(newValue)
|
value = Some(newValue)
|
||||||
|
frame += 1
|
||||||
signal.signalAll()
|
signal.signalAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -91,23 +95,62 @@ object ConcurrentBroadcast {
|
|||||||
readWriteLock(() => {
|
readWriteLock(() => {
|
||||||
val result = value.isEmpty
|
val result = value.isEmpty
|
||||||
value = Some(newValue)
|
value = Some(newValue)
|
||||||
|
frame += 1
|
||||||
signal.signalAll()
|
signal.signalAll()
|
||||||
result
|
result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def broadcastStop(): Unit = {
|
||||||
|
writeLock(() => {
|
||||||
|
value = None // this indicates the watcher that the broadcast ended
|
||||||
|
broadcastEnded = true
|
||||||
|
signal.signal()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
def broadcastRestart(): Unit = {
|
||||||
|
writeLock(() => {
|
||||||
|
broadcastEnded = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
def broadcastReset(): Unit = {
|
||||||
|
broadcastEnded = false
|
||||||
|
frame = 0
|
||||||
|
value = default
|
||||||
|
}
|
||||||
|
|
||||||
// BLOCKING: watch value, block until it is set, then return it
|
// BLOCKING: watch value, block until it is set, then return it
|
||||||
def watch(): A = {
|
def watch(): A = {
|
||||||
conditionalReadLock(!value.isEmpty, value.get)
|
conditionalReadLock(!value.isEmpty, value.get)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BLOCKING: watch value, block until it is set or the broadcast ends
|
||||||
|
// returns None for broadcast end and Some[A] otherwise
|
||||||
|
def watchUntilEnd(): Option[A] = {
|
||||||
|
conditionalReadLock(!value.isEmpty || broadcastEnded, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BLOCKING: watch value from frame, block until it is set, then return it
|
||||||
|
// IMPORTANT: no guarantee for the frame, a later one may be returned
|
||||||
|
def watchFrame(requestedFrame: Int): (A, Int) = {
|
||||||
|
conditionalReadLock(!value.isEmpty && frame >= requestedFrame, (value.get, frame))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BLOCKING: watch value from frame, block until it is set or the broadcast ends
|
||||||
|
// returns None for broadcast end and Some[A] otherwise
|
||||||
|
// IMPORTANT: no guarantee for the frame, a later one may be returned
|
||||||
|
def watchFrameUntilEnd(requestedFrame: Int): (Option[A], Int) = {
|
||||||
|
conditionalReadLock((!value.isEmpty && frame >= requestedFrame) || broadcastEnded, (value, frame))
|
||||||
|
}
|
||||||
|
|
||||||
// NON-BLOCKING: returns value as Option
|
// NON-BLOCKING: returns value as Option
|
||||||
def peak(): Option[A] = {
|
def peak(): Option[A] = {
|
||||||
readLock {
|
readLock {
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Broadcast[A](stream: mutable.ArraySeq[BroadcastObject[A]]) extends Runnable {
|
abstract class Broadcast[A](stream: mutable.ArraySeq[BroadcastObject[A]]) extends Runnable {
|
||||||
|
|||||||
Reference in New Issue
Block a user