ProcDispatcher: integrate queue and finish preliminary implementation draft
TODO: the wakeup / notification on changes still needs to be done consistently
This commit is contained in:
parent
3010c87008
commit
282829956b
5 changed files with 63 additions and 31 deletions
|
|
@ -23,10 +23,11 @@
|
|||
|
||||
/** @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.
|
||||
** This is the actual implementation of the command queue to allow for
|
||||
** strictly sequential dispatch of commands to work on the session.
|
||||
**
|
||||
** @todo WIP-WIP as of 12/2016
|
||||
** @todo as of 12/2016 this is fully functional, but we may want to add
|
||||
** some further management functions like purging of expired commands
|
||||
**
|
||||
** @see CommandQueue_test
|
||||
** @see proc-dispatcher.hpp
|
||||
|
|
@ -43,26 +44,23 @@
|
|||
|
||||
#include "proc/control/command.hpp"
|
||||
#include "lib/iter-stack.hpp"
|
||||
//#include "common/subsys.hpp"
|
||||
//#include "lib/depend.hpp"
|
||||
#include "lib/format-string.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <memory>
|
||||
//#include <functional>
|
||||
|
||||
|
||||
|
||||
namespace proc {
|
||||
namespace control {
|
||||
|
||||
// using lib::Symbol;
|
||||
// using std::bind;
|
||||
namespace error = lumiera::error;
|
||||
|
||||
using util::_Fmt;
|
||||
using lib::unConst;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @todo Type-comment
|
||||
* Implementation of the Session's command queue.
|
||||
* @see DispatcherLoop
|
||||
*/
|
||||
class CommandQueue
|
||||
: public lib::IterQueue<Command>
|
||||
|
|
@ -73,12 +71,25 @@ namespace control {
|
|||
{ }
|
||||
|
||||
|
||||
CommandQueue&
|
||||
feed (Command const& cmd)
|
||||
{
|
||||
if (not cmd.canExec())
|
||||
throw error::Logic(_Fmt("Reject '%s'. Not suitably prepared for invocation: %s")
|
||||
% cmd.getID() % cmd
|
||||
, LUMIERA_ERROR_UNBOUND_ARGUMENTS);
|
||||
|
||||
lib::IterQueue<Command>::feed(cmd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
clear()
|
||||
{
|
||||
this->stateCore().clear();
|
||||
}
|
||||
|
||||
|
||||
/* == diagnostics == */
|
||||
|
||||
size_t
|
||||
|
|
@ -94,8 +105,6 @@ namespace control {
|
|||
}
|
||||
|
||||
};
|
||||
////////////////TODO 12/16 currently just fleshing out the API....
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,10 +26,16 @@
|
|||
** 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
|
||||
** state predicates necessary to manage the state transitions regarding the
|
||||
** ProcDispatcher implementation:
|
||||
** - detect working state, based on a closure to detect an non empty CommandQueue
|
||||
** - handle the disabling and shutdown of the dispatching task
|
||||
** - detect an idle state to allow the DispatcherLoop to go to sleep
|
||||
** - detect the need to run the builder after handling a command
|
||||
** - manage timeout to run the builder with a slight latency
|
||||
** - manage an extended timeout to enforce builder run eventually.
|
||||
** - offer a "check point" where all state is balanced, which can be
|
||||
** used as a synchronisation point to halt the loop.
|
||||
**
|
||||
** @see DispatcherLooper_test
|
||||
** @see proc-dispatcher.hpp
|
||||
|
|
|
|||
|
|
@ -92,12 +92,10 @@
|
|||
#include "proc/control/session-command-service.hpp"
|
||||
#include "proc/mobject/session.hpp"
|
||||
#include "backend/thread-wrapper.hpp"
|
||||
#include "lib/format-string.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using backend::ThreadJoinable;
|
||||
using util::_Fmt;
|
||||
using lib::Sync;
|
||||
using lib::RecursiveLock_Waitable;
|
||||
using std::unique_ptr;
|
||||
|
|
@ -181,26 +179,23 @@ namespace control {
|
|||
clear() override
|
||||
{
|
||||
Lock sync(this);
|
||||
UNIMPLEMENTED ("clear the queue");
|
||||
queue_.clear();
|
||||
//////////////////////////////////////////TODO notify!!!!
|
||||
}
|
||||
|
||||
void
|
||||
enqueue (Command cmd) override
|
||||
{
|
||||
if (not cmd.canExec())
|
||||
throw error::Logic(_Fmt("Reject '%s'. Not suitably prepared for invocation: %s")
|
||||
% cmd.getID() % cmd
|
||||
, LUMIERA_ERROR_UNBOUND_ARGUMENTS);
|
||||
UNIMPLEMENTED ("enqueue command");
|
||||
Lock sync(this);
|
||||
queue_.feed (cmd);
|
||||
//////////////////////////////////////////TODO notify!!!!
|
||||
}
|
||||
|
||||
size_t
|
||||
size() const
|
||||
{
|
||||
TODO ("implement command processing queue");
|
||||
return 0;
|
||||
Lock sync(this);
|
||||
return queue_.size();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -217,7 +212,7 @@ namespace control {
|
|||
awaitStateProcessed()
|
||||
{
|
||||
Lock blockWaiting(this, &DispatcherLoop::stateIsSynched);
|
||||
//////////////////////////////////////////TODO find out who will notify us!!!!
|
||||
//////////////////////////////////////////TODO eternal sleep.... find out who will wake us!!!!
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -117,11 +117,11 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
PLANNED "Dispatcher loop control logic" DispatcherLooper_test <<END
|
||||
TEST "Dispatcher loop control logic" DispatcherLooper_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
PLANNED "Dispatcher command queue" CommandQueue_test <<END
|
||||
TEST "Dispatcher command queue" CommandQueue_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ namespace test {
|
|||
run (Arg)
|
||||
{
|
||||
verifyBasics();
|
||||
verifyExecutabilityCheck();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -128,6 +129,27 @@ namespace test {
|
|||
CHECK (0 == queue.size());
|
||||
CHECK (queue.empty());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verifyExecutabilityCheck()
|
||||
{
|
||||
Command com11 = Command(COMMAND_1).newInstance();
|
||||
Command com12 = Command(COMMAND_1).newInstance();
|
||||
|
||||
com11.bind(42);
|
||||
// NOT binding the second command...
|
||||
|
||||
CommandQueue queue;
|
||||
queue.feed (com11);
|
||||
CHECK (1 == queue.size());
|
||||
|
||||
VERIFY_ERROR (UNBOUND_ARGUMENTS, queue.feed (com12));
|
||||
CHECK (1 == queue.size());
|
||||
|
||||
queue.pop().execSync();
|
||||
VERIFY_ERROR (UNBOUND_ARGUMENTS, com12.execSync());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue