From 00077d0431489168075f9a5d2e2e408fec951c4c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 15 Dec 2016 20:48:35 +0100 Subject: [PATCH] ProcDispatcher: decide on requirements and implementation structure (#1049) --- src/common/guifacade.cpp | 3 +- src/lib/sync.hpp | 23 +++-- src/proc/control/command-queue.hpp | 85 ++++++++++++++++++ src/proc/control/looper.hpp | 87 ++++++++++++++++++ src/proc/control/proc-dispatcher.cpp | 7 ++ tests/45controller.tests | 10 +++ tests/backend/sync-timedwait-test.cpp | 12 ++- .../core/proc/control/command-queue-test.cpp | 89 +++++++++++++++++++ .../proc/control/dispatcher-looper-test.cpp | 89 +++++++++++++++++++ wiki/renderengine.html | 26 +++++- wiki/thinkPad.ichthyo.mm | 47 ++++++++-- 11 files changed, 462 insertions(+), 16 deletions(-) create mode 100644 src/proc/control/command-queue.hpp create mode 100644 src/proc/control/looper.hpp create mode 100644 tests/core/proc/control/command-queue-test.cpp create mode 100644 tests/core/proc/control/dispatcher-looper-test.cpp diff --git a/src/common/guifacade.cpp b/src/common/guifacade.cpp index b3fd1db30..2854d978b 100644 --- a/src/common/guifacade.cpp +++ b/src/common/guifacade.cpp @@ -121,7 +121,8 @@ namespace gui { * However, the Lumiera thread handling wrapper/framework ensures that a new thread actually * starts to execute (and picks up the arguments), prior to returning from the thread starting * function. For this reason, it is rather unlikely this race actually happens in practice, - * since opening the GuiNotification interface is done early, while starting the UI-Bus. + * since opening the GuiNotification interface is done early, while starting the UI-Bus. + * @todo ////////////////////////////////////////////////////////TICKET #1048 : use Thread.sync (barrier) to work around this! */ void triggerShutdown () noexcept override diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index f80f236bb..14b1a92f6 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -29,7 +29,7 @@ ** describes a way of dealing with synchronisation known to play well with ** scoping, encapsulation and responsibility for a single purpose. ** - ** A class becomes \em lockable by inheriting from lib::Sync with the appropriate + ** A class becomes _lockable_ by inheriting from lib::Sync with the appropriate ** parametrisation. This causes any instance to inherit a monitor member (object), ** managing a mutex and (optionally) a condition variable for waiting. The actual ** synchronisation is achieved by placing a guard object as local (stack) variable @@ -38,7 +38,7 @@ ** manages the locking and unlocking; optionally it may also be used for waiting ** on a condition. ** - ** Please note: + ** @note ** - It is important to select a suitable parametrisation of the monitor. ** This is done by specifying one of the defined policy classes. ** - Be sure to pick the recursive mutex implementation when recursive calls @@ -176,7 +176,7 @@ namespace lib { } while(err == EINTR); if (err) lumiera_lockerror_set (err, &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC); - return !err; + return not err; } bool @@ -187,7 +187,7 @@ namespace lib { } while(err == EINTR); if (err) lumiera_lockerror_set (err, &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC); - return !err; + return not err; } @@ -405,7 +405,20 @@ namespace lib { * The interface for clients to access the functionality is the embedded * Lock template, which should be instantiated as an automatic variable * within the scope to be protected. - * + * + * ## Usage + * - for *locking*, just place an instant of the embedded Lock into the local + * scope to be protected. All lock instances within the same object share + * the monitor; thus any time, only one of them gets the mutex all other + * instances block on construction. + * - for *waiting* likewise place an instance of the Lock class (which gets + * you a mutex). Then invoke the wait method on that instance; this suspends + * the current thread and releases the mutex. To awake and check the condition, + * some other thread must invoke the Lock::notify() within the same object. + * The Lock::wait() call returns `true` when the condition was met, and + * `false` if awakened due to timeout. The call might throw in case of + * technical errors. In any case, when returning from the `wait()` call, + * the mutex has been re-acquired. */ template class Sync diff --git a/src/proc/control/command-queue.hpp b/src/proc/control/command-queue.hpp new file mode 100644 index 000000000..3a0e48f9e --- /dev/null +++ b/src/proc/control/command-queue.hpp @@ -0,0 +1,85 @@ +/* + COMMAND-QUEUE.hpp - organise ordering of commands within ProcDispatcher + + Copyright (C) Lumiera.org + 2016, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file command-queue.hpp + ** Implementation building block of ProcDispatcher to organise commands. + ** This is the actual implementation of the command queue and additionally + ** supports some management tasks pertaining to the queue as a whole. + ** + ** @todo WIP-WIP as of 12/2016 + ** + ** @see CommandQueue_test + ** @see proc-dispatcher.hpp + ** @see session-command-service.hpp + ** @see DispatcherLoop + ** @see Looper + ** + */ + + + +#ifndef PROC_CONTROL_COMMAND_QUEUE_H +#define PROC_CONTROL_COMMAND_QUEUE_H + +#include "lib/error.hpp" ////////TODO needed? +//#include "common/subsys.hpp" +//#include "lib/depend.hpp" + +//#include +//#include + + + +namespace proc { +namespace control { + +// using lib::Symbol; +// using std::bind; + + + + /** + * @todo Type-comment + */ + class CommandQueue + { + + public: + CommandQueue() + { } + + + + /* == diagnostics == */ + +// size_t size() const ; +// bool empty() const ; + + }; + ////////////////TODO 12/16 currently just fleshing out the API.... + + + + +}} // namespace proc::control +#endif /*PROC_CONTROL_COMMAND_QUEUE_H*/ diff --git a/src/proc/control/looper.hpp b/src/proc/control/looper.hpp new file mode 100644 index 000000000..6edd3fb7b --- /dev/null +++ b/src/proc/control/looper.hpp @@ -0,0 +1,87 @@ +/* + LOOPER.hpp - proc dispatcher loop and timing control logic + + Copyright (C) Lumiera.org + 2016, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file looper.hpp + ** Implementation building block of ProcDispatcher to control waiting and timing. + ** This helper encapsulates the loop control logic to separate it from actual + ** implementation of timing and waiting (per pthread condition variables). + ** It exposes a combined condition (to be used for waiting) plus any further + ** controls to manage the operation of the actual queue. The actual tasks to + ** be controlled are installed as functors. + ** + ** @todo WIP-WIP as of 12/2016 + ** + ** @see DispatcherLooper_test + ** @see proc-dispatcher.hpp + ** @see DispatcherLoop + ** @see CommandQueue + ** + */ + + + +#ifndef PROC_CONTROL_LOOPER_H +#define PROC_CONTROL_LOOPER_H + +#include "lib/error.hpp" ////////TODO needed? +//#include "common/subsys.hpp" +//#include "lib/depend.hpp" + +//#include +//#include + + + +namespace proc { +namespace control { + +// using lib::Symbol; +// using std::bind; + + + + /** + * @todo Type-comment + */ + class Looper + { + + public: + Looper() + { } + + + + /* == diagnostics == */ + +// size_t size() const ; +// bool empty() const ; + + }; + ////////////////TODO 12/16 currently just fleshing out the API.... + + + + +}} // namespace proc::control +#endif /*PROC_CONTROL_LOOPER_H*/ diff --git a/src/proc/control/proc-dispatcher.cpp b/src/proc/control/proc-dispatcher.cpp index e86b59ee4..090518334 100644 --- a/src/proc/control/proc-dispatcher.cpp +++ b/src/proc/control/proc-dispatcher.cpp @@ -26,6 +26,8 @@ #include "include/logging.h" #include "proc/control/proc-dispatcher.hpp" #include "proc/control/command-dispatch.hpp" +#include "proc/control/command-queue.hpp" +#include "proc/control/looper.hpp" #include "proc/control/session-command-service.hpp" #include "proc/mobject/session.hpp" #include "backend/thread-wrapper.hpp" @@ -55,12 +57,17 @@ namespace control { unique_ptr commandService_; + CommandQueue queue_; + Looper looper_; + public: DispatcherLoop (Subsys::SigTerm notification) : ThreadJoinable("Lumiera Session" , bind (&DispatcherLoop::run, this, notification)) , commandService_(new SessionCommandService(*this)) + , queue_() + , looper_() { INFO (session, "Proc-Dispatcher running..."); } diff --git a/tests/45controller.tests b/tests/45controller.tests index 8761a6d86..f176bbe79 100644 --- a/tests/45controller.tests +++ b/tests/45controller.tests @@ -115,3 +115,13 @@ END PLANNED "Command usage aspects III" CommandUse3_test < + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "lib/test/run.hpp" +#include "proc/control/command-queue.hpp" +//#include "proc/control/command.hpp" +//#include "proc/control/command-registry.hpp" +//#include "lib/test/event-log.hpp" + +//#include "proc/control/test-dummy-commands.hpp" + +//#include + + +namespace proc { +namespace control { +namespace test { + + +// using std::function; +// using std::rand; + + + namespace { // test fixture... + + + }//(End) test fixture + +// typedef shared_ptr PCommandImpl; +// typedef HandlingPattern const& HaPatt; + + + + + + + /******************************************************************************//** + * @test verify proper working of queue management used within ProcDispatcher. + * - can enqueue and dequeue command messages + * - handling of priority messages + * + * @see CommandQueue + * @see DispatcherLoop + * @see ProcDispatcher + * @see DispatcherLooper_test + */ + class CommandQueue_test : public Test + { + + + virtual void + run (Arg) + { + verifyBasics(); + } + + + void + verifyBasics() + { + } + }; + + + /** Register this test class... */ + LAUNCHER (CommandQueue_test, "unit controller"); + + +}}} // namespace proc::control::test diff --git a/tests/core/proc/control/dispatcher-looper-test.cpp b/tests/core/proc/control/dispatcher-looper-test.cpp new file mode 100644 index 000000000..9d622aab4 --- /dev/null +++ b/tests/core/proc/control/dispatcher-looper-test.cpp @@ -0,0 +1,89 @@ +/* + DispatcherLooper(Test) - verify loop control and timing functionality of ProcDispatcher + + Copyright (C) Lumiera.org + 2016, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "lib/test/run.hpp" +#include "proc/control/command-queue.hpp" +//#include "proc/control/command.hpp" +//#include "proc/control/command-registry.hpp" +//#include "lib/test/event-log.hpp" + +//#include "proc/control/test-dummy-commands.hpp" + +//#include + + +namespace proc { +namespace control { +namespace test { + + +// using std::function; +// using std::rand; + + + namespace { // test fixture... + + + }//(End) test fixture + +// typedef shared_ptr PCommandImpl; +// typedef HandlingPattern const& HaPatt; + + + + + + + /******************************************************************************//** + * @test verify encapsulated control logic of ProcDispatcher. + * - fusing of conditions for the pthread waiting condition + * - detection and handling of work states + * - management of builder run triggers + * + * @see proc::control::Looper + * @see DispatcherLoop + * @see CommandQueue_test + */ + class DispatcherLooper_test : public Test + { + + + virtual void + run (Arg) + { + verifyBasics(); + } + + + void + verifyBasics() + { + } + }; + + + /** Register this test class... */ + LAUNCHER (DispatcherLooper_test, "unit controller"); + + +}}} // namespace proc::control::test diff --git a/wiki/renderengine.html b/wiki/renderengine.html index f78fbbb04..7b76182c7 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -5222,11 +5222,35 @@ 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.
 
 Enqueueing commands through the {{{SessionCommandFacade}}} into the ProcDispatcher is the official way to cause changes to the session. And the running state of the ProcDispatcher is equivalent with the running state of the //session subsystem as a whole.//
+
+!Requirements
+To function properly as action coordinator of the session subsystem, the dispatcher has to fulfil multiple demands
+;enqueue
+:accept and enqueue command messages concurrently, any time, without blocking the caller
+:*FIFO for //regular commands//
+:*LIFO for //priority requests//
+;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")
+:* when?
+:** after each command
+:** regularily whle idle
+:* why?
+:** ensure the Builder runs regularly
+:** respond reliably to shutdown request
+;manage
+:care for rectifying entries in the queue
+:* ensure they //match// current session, discard obsoleted requests
+:* //aggregate// similar requests
+:* //supersede// by newer commands of a certain kind
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 83306912f..cacab2536 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -11005,8 +11005,8 @@ - - + + @@ -11016,7 +11016,32 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -11024,13 +11049,23 @@ - - + + - + + + + + + + + + + +