/* * ActionQueue.hpp * * Created on: Aug 16, 2013 * Author: heber */ #ifndef ACTIONQUEUE_HPP_ #define ACTIONQUEUE_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/Singleton.hpp" #include "CodePatterns/Observer/Channels.hpp" #include "CodePatterns/Observer/Observable.hpp" #ifdef HAVE_ACTION_THREAD #include #endif #include #include "Actions/Action.hpp" #include "Actions/ActionState.hpp" #include "Actions/ActionStatusList.hpp" #ifdef HAVE_ACTION_THREAD void stopQueue(); void waitQueue(); #endif class CommandLineParser; namespace MoleCuilder { class ActionHistory; class ActionRegistry; class ActionTrait; class DryRunAdvocate; namespace Queuedetail { template const T* lastChanged() { ASSERT(0, "Queuedetail::lastChanged() - only specializations may be used."); return NULL; } } /** This class combines the whole handling of Actions into a single class. * * It spawns new Actions by its internal ActionRegistry. Spawned Actions are * automatically queued and placed into a History after execution. */ class ActionQueue : public Singleton, public Observable { friend class Singleton; public: typedef std::vector ActionTokens_t; typedef std::vector< Action * > ActionQueue_t; //!> channels for this observable enum NotificationType { ActionQueued, // new action was queued NotificationType_MAX // denotes the maximum of available notification types }; //>! access to last changed element (atom or molecule) template const T* lastChanged() const { return Queuedetail::lastChanged(); } /** Queues the Action with \a name to be called. * * \param name token of Action to actionqueue * \param state whether Actions needs to be filled via a Dialog or not */ void queueAction(const std::string &name, enum Action::QueryOptions state = Action::Interactive); /** Returns the spawned action by token \a name. * * Action is checked into internal actionqueue. * * \return ref to newly spawned action */ const Action& getActionByName(const std::string &name); /** Checks whether the Action is known by the given \a name. * * \param name token of action to check * \return true - token is known, false - else */ bool isActionKnownByName(const std::string &name) const; /** Register an Action with the ActionRegistry. * * \param _action action to add */ void registerAction(Action *_action); /** Returns the vector with the tokens of all currently known Actions. * * \return list of all tokens */ const ActionTokens_t getListOfActions() const; /** Returns the trait to an Action. * * \param name name of Action * \return const ref to its default Trait. */ const ActionTrait& getActionsTrait(const std::string &name) const; /** Print the current contents of the actionqueue as CLI instantiated list of Actions. * * This is useful for storing the current session. * * \param output output stream to print to */ void outputAsCLI(std::ostream &output) const; /** Print the current contents of the actionqueue as Python instantiated list of Actions. * * This is useful for storing the current session. * * \param output output stream to print to */ void outputAsPython(std::ostream &output) const; /** Undoes last called Acfriend void ::cleanUp();tion. * */ void undoLast(); /** Redoes last undone Action. * */ void redoLast(); /** Checks whether there is one completed Action stored in ActionHistory in the past. * * @return true - at least one Action to undo present, false - else */ bool canUndo() const; /** Checks whether there is one completed Action stored in ActionHistory in the future. * * @return true - at least one Action to redo present, false - else */ bool canRedo() const; /** Return status of last executed action. * * \return true - action executed correctly, false - else */ bool getLastActionOk() const { return lastActionOk; } /** Getter to ref to list of status messages. * * This is meant for UIs to registers as Observables. * * \return ref to StatusList variable */ ActionStatusList& getStatusList() { return StatusList; } /** Getter for isDryRun state flag. * * \return true - ActionQueue does not execute Actions but skips, false - else */ bool getDryRun() const { return dryrun_flag; } /** States whether the ActionQueue is currently executing Actions or done executing. * * \return true - ActionQueue is done executing Actions. */ bool isIdle() const; private: //!> grant Action access to internal history functions. friend class Action; //!> grant CommandLineParser access to stop and clearQueue() friend class ::CommandLineParser; //!> grant Advocate access to setting dryrun friend class DryRunAdvocate; /** Queues the Action with \a name to be called. * * \param _action action to add * \param state whether Actions needs to be filled via a Dialog or not */ void queueAction(const Action * const _action, enum Action::QueryOptions state = Action::Interactive); /** Wrapper function to add state to ActionHistory. * * \param _Action Action whose state to add * \param _state state to add */ void addElement(Action* _Action, ActionState::ptr _state); /** Advocate function to add status message to the list. * */ void pushStatus(const std::string &_msg) { StatusList.pushMessage(_msg); } /** Wrapper function to clear ActionHistory. * */ void clear(); /** Clears all actions present in the actionqueues from \a _fromAction. * * @param _fromAction 0 if all Actions to clear or else */ void clearQueue(const size_t _fromAction = 0); #ifdef HAVE_ACTION_THREAD boost::thread &getRunThread() { return run_thread; } /** Clears the temporary queue. * */ void clearTempQueue(); /** Sets the run_thread_isIdle flag. * * @param _flag state to set to */ void setRunThreadIdle(const bool _flag); /** Runs the ActionQueue. * */ void run(); friend void ::stopQueue(); /** Stops the internal thread. * */ void stop(); friend void ::waitQueue(); /** Wait till all currently queued actions are processed. * */ void wait(); /** Moves all action from tempqueue into real queue. * */ void insertTempQueue(); #endif /** Insert an action after CurrentAction. * * This is implemented only to allow action's COMMAND to work. If we * were to use queueAction, actions would come after all other already * present actions. */ void insertAction(Action *_action, enum Action::QueryOptions state); /** Sets the current state of the \a isDryRun flag. * * \param _dryrun true - Actions will not get executed anymore, false - else */ void setDryRun(const bool _dryrun) { dryrun_flag = _dryrun; } /** Checks whether next Action should be skipped or not. * * \param _nextaction next action to execute to inspect whether it unsets dryrun_flag * \return true - dryrun_flag set and \a _nextaction is not unsetting dry run */ bool isDryRun(const Action *_nextaction) const; private: /** Private cstor for ActionQueue. * * Must be private as is singleton. * */ ActionQueue(); /** Dstor for ActionQueue. * */ ~ActionQueue(); private: friend const Action *Queuedetail::lastChanged(); static const Action *_lastchangedaction; //!> ActionRegistry to spawn new actions ActionRegistry *AR; //!> ActionHistory is for undoing and redoing actions, requires ActionRegistry fully initialized ActionHistory *history; //!> internal actionqueue of actions ActionQueue_t actionqueue; //!> indicates that the last action has failed bool lastActionOk; //!> point to current action in actionqueue size_t CurrentAction; #ifdef HAVE_ACTION_THREAD //!> internal temporary actionqueue of actions used by insertAction() ActionQueue_t tempqueue; //!> internal thread to call Actions boost::thread run_thread; //!> internal mutex to synchronize access to queue mutable boost::mutex mtx_queue; //!> conditional variable notifying when run_thread is idling boost::condition_variable cond_idle; //!> flag indicating whether run_thread is idle or not bool run_thread_isIdle; //!> internal mutex to synchronize access to run_thread_isIdle mutable boost::mutex mtx_idle; #endif //!> internal list of status messages from Actions for UIs to display ActionStatusList StatusList; //!> internal flag whether to call or skip actions (i.e. do a dry run) bool dryrun_flag; }; namespace Queuedetail { template <> inline const Action* lastChanged() { return ActionQueue::_lastchangedaction; } } }; #endif /* ACTIONQUEUE_HPP_ */