diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 319544cb9..3d4584fc6 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -361,9 +361,9 @@ namespace lib { template bool - wait (X& instance, bool (X::*method)(void), ulong timedwait=0) + wait (X& instance, bool (X::*method)(void), ulong timedwait=0) ///////////////////////TICKET #1051 : add support for lambdas { - BoolMethodPredicate invokeMethod(instance, method); + BoolMethodPredicate invokeMethod(instance, method); ///////////////////////TICKET #1057 : const correctness, allow use of const member functions return IMPL::wait(invokeMethod, timeout_.setOffset(timedwait)); } @@ -463,7 +463,7 @@ namespace lib { template bool - wait (X& instance, bool (X::*predicate)(void), ulong timeout=0) + wait (X& instance, bool (X::*predicate)(void), ulong timeout=0) //////////////////////TICKET #1051 : enable use of lambdas { return mon_.wait(instance,predicate,timeout); } diff --git a/src/proc/control/proc-dispatcher.cpp b/src/proc/control/proc-dispatcher.cpp index 426df4a75..f74d7f100 100644 --- a/src/proc/control/proc-dispatcher.cpp +++ b/src/proc/control/proc-dispatcher.cpp @@ -73,8 +73,6 @@ ** is a private detail of the performing thread. The lock is acquired solely for checking or leaving ** the wait state and when fetching the next command from queue. ** - ** @todo as of 12/2016, implementation has been drafted and is very much WIP - ** ** @see ProcDispatcher ** @see DispatcherLooper_test ** @see CommandQueue_test @@ -94,9 +92,9 @@ #include -using backend::Thread; using lib::Sync; using lib::RecursiveLock_Waitable; +using backend::Thread; using std::unique_ptr; namespace proc { @@ -104,10 +102,10 @@ namespace control { namespace error = lumiera::error; - /** - * PImpl within ProcDispatcher - * to implement the _Session Loop Thread._ - * During the lifetime of this object + + /********************************************************************//** + * PImpl within ProcDispatcher to implement the _Session Loop Thread._ + * During the lifetime of this object... * - the SessionCommandService is offered to enqueue commands * - the Session Loop thread dispatches commands and triggers the Builder * @see DispatcherLooper_test @@ -117,8 +115,7 @@ namespace control { , public CommandDispatch , public Sync { - bool canDispatch_{false}; - + /** manage the primary public Session interface */ unique_ptr commandService_; @@ -165,18 +162,18 @@ namespace control { activateCommandProecssing() { Lock sync(this); - canDispatch_ = true; + looper_.enableProcessing(true); INFO (command, "Session command processing activated."); - TODO ("implement command processing queue"); + sync.notifyAll(); } void deactivateCommandProecssing() { Lock sync(this); - canDispatch_ = false; + looper_.enableProcessing(false); INFO (command, "Session command interface closed."); - TODO ("implement command processing queue"); + sync.notifyAll(); } void @@ -191,8 +188,8 @@ namespace control { void awaitStateProcessed() const { - Lock blockWaiting(this, &DispatcherLoop::stateIsSynched); - //////////////////////////////////////////TODO eternal sleep.... find out who will wake us!!!! + Lock blockWaiting(unConst(this), &DispatcherLoop::stateIsSynched); ///////////////////////TICKET #1057 : const correctness on wait predicate + // wake-up typically by updateState() } size_t @@ -272,14 +269,14 @@ namespace control { updateState() ///< at end of loop body... { looper_.markStateProcessed(); - if (looper_.isDisabled()) + if (looper_.isDisabled()) // otherwise wake-up would not be safe Lock(this).notifyAll(); } bool stateIsSynched() { - if (looper_.hasPendingChanges() and calledFromWithinSessionThread()) + if (calledFromWithinSessionThread()) throw error::Fatal("Possible Deadlock. " "Attempt to synchronise to a command processing check point " "from within the (single) session thread." @@ -324,11 +321,12 @@ namespace control { + /** storage for Singleton access */ lib::Depend ProcDispatcher::instance; - + /* ======== ProcDispatcher implementation ======== */ /** starting the ProcDispatcher means to start the session subsystem. * @return `false` when _starting_ failed since it is already running... @@ -426,6 +424,12 @@ namespace control { } + /** halt further processing of session commands + * @note the processing itself runs in a separate thread, thus any currently + * ongoing command or builder execution will be completed prior to this setting + * to take effect. If the intention is to halt processing because the session is + * about to dismantled, it is mandatory to awaitDeactivation() + */ void ProcDispatcher::deactivate() { @@ -472,8 +476,6 @@ namespace control { return not runningLoop_ or 0 == runningLoop_->size(); } - - diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 45f56eabe..1b534ccaa 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -5222,7 +5222,7 @@ Besides, they provide an __inward interface__ for the [[ProcNode]]s, enabling th [img[Asset Classess|uml/fig131077.png]] {{red{Note 3/2010}}} it is very unlikely we'll organise the processing nodes as a class hierarchy. Rather it looks like we'll get several submodules/special capabilities configured in within the Builder -
+
//The guard and coordinator of any operation within the session subsystem.//
 The session and related components work effectively single threaded. Any tangible operation on the session data structure has to be enqueued as [[command|CommandHandling]] into the dispatcher. Moreover, the [[Builder]] is triggered from the ProcDispatcher; and while the Builder is running, any command processing is halted. The Builder in turn creates or reshapes the processing nodes network, and the changed network is brought into operation with a //transactional switch// -- while render processes on this processing network operate unaffected and essentially multi-threaded.
 
@@ -5233,19 +5233,18 @@ To function properly as action coordinator of the session subsystem, the dispatc
 ;enqueue
 :accept and enqueue command messages concurrently, any time, without blocking the caller
 :*FIFO for //regular commands//
-:*LIFO for //priority requests//
+:*LIFO for //priority requests//  {{red{unimplemented 1/17}}}
 ;process
 :dequeue and process entries sequentially
 ;sleep
 :work continuously until queue is empty, then enter wait state
 ;check point
-:invoke a well defined check point reliably non blocking ("ensure to make progress")
+:arrive at a well defined check point reliably non blocking ("ensure to make progress")
+:* necessary to know when internal state is consistent
 :* when?
 :** after each command
-:** regularily whle idle
-:* why?
-:** ensure the Builder runs regularly
-:** respond reliably to shutdown request
+:** after builder run
+:** after wake-up
 ;manage
 :care for rectifying entries in the queue
 :* ensure they //match// current session, discard obsoleted requests
@@ -5263,9 +5262,9 @@ Initially the command queue is empty and the ProcDispatcher can be considered id
 
 So the logic to trigger builder runs has to take some leeway into account. Due to the typical interactive working style of an editing application, session commands might be trickling in in strikes of similar commands, intermingled with tiny pauses. For this reason, the ProcDispatcher implements some //hysteresis,// as far as triggering the builder runs is concerned. The builder is fired in idle state, but only after passing some //latency period.// On the other hand, massive UI activities (especially during a builder run) may have flooded the queue, thus sending the session into an extended period of command processing. From the user's view angle, the application looks non responsive in such a case, albeit not frozen, since the UI can still enqueue further commands and thus retains the ability to react locally on user interaction. To mitigate this problem, the builder should be started anyway after some extended period of command processing, even if the queue is not yet emptied. Each builder run produces a structural diff message sent towards the UI and thus causes user visible changes within the session's UI representation. This somewhat stuttering response conveys to the user a tangible sensation of ongoing activity, while communicating at the same time, at least subconsciously some degree of operational overload. {{red{note 12/2016 builder is not implemented, so consider this planning}}}
 
-Any change to the circumstances determining the ProcDispatcher's behaviour need to be imparted actively through the public interface -- the dispatcher is not designed to be a state listener or observer. Any such state change notifications are synchronised and cause a wakeup notification to the session thread. For this purpose, enqueuing of further commands counts as state change and is lock protected. Beyond that, any other activities, like //processing// of commands or builder runs, are performed within the session thread without blocking other threads; the locking on the ProcDispatcher is only ever short term to ensure consistent internal state. Clients need to be prepared for the effect of actions to appear asynchronously and with some delay. Especially this means that session switch or shutdown has to await completion of any session command or builder run currently in progress.
+Any change to the circumstances determining the ProcDispatcher's behaviour needs to be imparted actively through the public interface -- the dispatcher is not designed to be a state listener or observer. Any such state change notifications are synchronised and cause a wakeup notification to the session thread. For this purpose, enqueuing of further commands counts as state change and is lock protected. Beyond that, any other activities, like //processing// of commands or builder runs, are performed within the session thread without blocking other threads; the locking on the ProcDispatcher is only ever short term to ensure consistent internal state. Clients need to be prepared for the effect of actions to appear asynchronously and with some delay. Especially this means that session switch or shutdown has to await completion of any session command or builder run currently in progress.
 
-When the session is closed or dismantled, further processing in the ProcDispatcher will be disabled, after completing the current command or builder run. This disabled state can be reversed when a new session instance becomes operative. And while the dispatcher will then continue to empty the command queue, most commands in queue will probably be obsoleted and dropped, because of referring to a deceased session instance. Moreover, the lifecycle of the session instances has to be distinguished from the lifecycle of the "session subsystem" as such. When the latter is terminated, be it by a fatal error in some builder run, or be it due to general shutdown of the application, the ProcDispatcher will be asked to terminate the session thread after completing the current activity in progress. Such an event will also discard any further commands waiting in the dispatcher's queue.
+When the session is closed or dismantled, further processing in the ProcDispatcher will be disabled, after completing the current command or builder run. This disabled state can be reversed when a new session instance becomes operative. And while the dispatcher will then continue to empty the command queue, most commands in queue will probably be obsoleted and dropped, because of referring to a deceased session instance. Moreover, the lifecycle of the session instances has to be distinguished from the lifecycle of the SessionSubsystem as such. When the latter is terminated, be it by a fatal error in some builder run, or be it due to general shutdown of the application, the ProcDispatcher will be asked to terminate the session thread after completing the current activity in progress. Such an event will also discard any further commands waiting in the dispatcher's queue.
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index c48b034e0..d6858e943 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -419,7 +419,7 @@ - + @@ -437,15 +437,15 @@ - + - - + + @@ -455,8 +455,12 @@ - - + + + + + + @@ -630,9 +634,9 @@ - + - + @@ -662,7 +666,7 @@ - + @@ -11221,8 +11225,8 @@ - - + + @@ -11234,9 +11238,13 @@ - + - + + + + + @@ -11347,13 +11355,17 @@ - - - - - + + + + + + + + + - +