MPSCR-5: Clear all logicals from current StateFrameStack observer on incremental session teardown.
This commit is contained in:
parent
daa1bdceb6
commit
510c3cd479
|
|
@ -17,6 +17,7 @@
|
|||
package jetbrains.mps.logic.reactor.core
|
||||
|
||||
import jetbrains.mps.logic.reactor.core.internal.LogicalImpl
|
||||
import jetbrains.mps.logic.reactor.core.internal.StateFrameStack
|
||||
import jetbrains.mps.logic.reactor.logical.Logical
|
||||
|
||||
/**
|
||||
|
|
@ -41,3 +42,11 @@ fun Logical<*>.removeObserver(observer: LogicalObserver) {
|
|||
(this as LogicalImpl<*>).valueObservers.removeAll { p -> p.second == observer }
|
||||
(this as LogicalImpl<*>).parentObservers.removeAll { p -> p.second == observer }
|
||||
}
|
||||
|
||||
// Helps ensuring absence of memory leak of StateFrameStack through variable's internal arrays of observers
|
||||
internal fun checkForwardingObserverUniqueInstance(logical: Logical<*>): Boolean = with(logical as LogicalImpl<*>) {
|
||||
valueObservers.map { it.second }.filterIsInstance<StateFrameStack>().toHashSet().size <= 1 &&
|
||||
parentObservers.map { it.second }.filterIsInstance<StateFrameStack>().toHashSet().size <= 1
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -146,9 +146,11 @@ internal class EvaluationSessionImpl private constructor (
|
|||
}
|
||||
|
||||
return object : EvaluationResult {
|
||||
override fun token(): SessionToken = session.controller.state.snapshot()
|
||||
private val token = session.controller.state.endSession()
|
||||
|
||||
override fun storeView(): StoreView? = session.controller.storeView()
|
||||
override fun token(): SessionToken = token
|
||||
|
||||
override fun storeView(): StoreView = token.journalView.storeView
|
||||
|
||||
override fun feedback(): EvaluationFeedback? = failure
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,8 +204,15 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
|
|||
fun launchQueue(controller: Controller): FeedbackStatus =
|
||||
execQueue.run(controller, this)
|
||||
|
||||
fun snapshot(): SessionToken =
|
||||
SessionTokenImpl(view(), ruleOrdering.ruleTags, dispatchingFront.state())
|
||||
/**
|
||||
* Clears state unneeded between incremental sessions
|
||||
* and returns [SessionToken] with session results.
|
||||
*/
|
||||
fun endSession(): SessionToken {
|
||||
val histView = view()
|
||||
resetStore() // clear observers
|
||||
return SessionTokenImpl(histView, ruleOrdering.ruleTags, dispatchingFront.state())
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the state with the currently active constraint occurrence.
|
||||
|
|
|
|||
|
|
@ -43,11 +43,6 @@ internal class StateFrame constructor() : LogicalObserver
|
|||
this.observers = prototype.observers
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
// TODO remove observers
|
||||
|
||||
}
|
||||
|
||||
fun addForwardingObserver(logical: Logical<*>, observer: LogicalObserver) {
|
||||
val logicalId = Id(logical)
|
||||
this.observers = observers.assoc(logicalId,
|
||||
|
|
@ -64,6 +59,9 @@ internal class StateFrame constructor() : LogicalObserver
|
|||
fun isObserving(logical: Logical<*>) =
|
||||
observers[Id(logical)] != null
|
||||
|
||||
fun observed(): Sequence<Logical<*>> =
|
||||
observers.keys().asSequence().map { it.wrapped }
|
||||
|
||||
override fun valueUpdated(logical: Logical<*>) {
|
||||
observers[Id(logical)]?.let { list ->
|
||||
for (observer in list) {
|
||||
|
|
|
|||
|
|
@ -16,10 +16,7 @@
|
|||
|
||||
package jetbrains.mps.logic.reactor.core.internal
|
||||
|
||||
import jetbrains.mps.logic.reactor.core.LogicalObserver
|
||||
import jetbrains.mps.logic.reactor.core.ProcessingState
|
||||
import jetbrains.mps.logic.reactor.core.addObserver
|
||||
import jetbrains.mps.logic.reactor.core.removeObserver
|
||||
import jetbrains.mps.logic.reactor.core.*
|
||||
import jetbrains.mps.logic.reactor.logical.Logical
|
||||
import java.util.*
|
||||
|
||||
|
|
@ -42,12 +39,19 @@ internal open class StateFrameStack() : ProcessingState, LogicalObserver
|
|||
return newFrame
|
||||
}
|
||||
|
||||
fun reset() = reset(stateFrames.last)
|
||||
fun reset() {
|
||||
// Clear logicals from this forwarding observer on full reset
|
||||
currentFrame().observed().forEach {
|
||||
it.removeObserver(this)
|
||||
}
|
||||
reset(stateFrames.last)
|
||||
}
|
||||
|
||||
fun reset(frame: StateFrame) {
|
||||
val it = stateFrames.iterator()
|
||||
while (it.hasNext()) {
|
||||
if (frame === it.next()) { // referential equality
|
||||
val next = it.next()
|
||||
if (frame === next) { // referential equality
|
||||
return
|
||||
}
|
||||
it.remove()
|
||||
|
|
@ -60,6 +64,7 @@ internal open class StateFrameStack() : ProcessingState, LogicalObserver
|
|||
logical.addObserver(this)
|
||||
}
|
||||
currentFrame().addForwardingObserver(logical, observer)
|
||||
// assert(checkForwardingObserverUniqueInstance(logical))
|
||||
}
|
||||
|
||||
override fun removeForwardingObserver(logical: Logical<*>, observer: LogicalObserver) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue