source: src/Actions/ActionQueue.hpp@ 99c705

Candidate_v1.6.1 ChemicalSpaceEvaluator
Last change on this file since 99c705 was 559293, checked in by Frederik Heber <frederik.heber@…>, 7 years ago

ActionQueue has predicates to check if current Action is Process or MakroAction.

  • Property mode set to 100644
File size: 9.6 KB
Line 
1/*
2 * ActionQueue.hpp
3 *
4 * Created on: Aug 16, 2013
5 * Author: heber
6 */
7
8#ifndef ACTIONQUEUE_HPP_
9#define ACTIONQUEUE_HPP_
10
11// include config.h
12#ifdef HAVE_CONFIG_H
13#include <config.h>
14#endif
15
16#include "CodePatterns/Singleton.hpp"
17
18#include "CodePatterns/Observer/Channels.hpp"
19#include "CodePatterns/Observer/Observable.hpp"
20
21#ifdef HAVE_ACTION_THREAD
22#include <boost/thread.hpp>
23#endif
24#include <vector>
25
26#include "Actions/Action.hpp"
27#include "Actions/ActionState.hpp"
28#include "Actions/ActionStatusList.hpp"
29
30#ifdef HAVE_ACTION_THREAD
31void stopQueue();
32void waitQueue();
33#endif
34
35class CommandLineParser;
36
37namespace MoleCuilder {
38
39class ActionHistory;
40class ActionRegistry;
41class ActionTrait;
42class DryRunAdvocate;
43
44namespace Queuedetail {
45 template <class T> const T* lastChanged()
46 {
47 ASSERT(0, "Queuedetail::lastChanged() - only specializations may be used.");
48 return NULL;
49 }
50}
51
52/** This class combines the whole handling of Actions into a single class.
53 *
54 * It spawns new Actions by its internal ActionRegistry. Spawned Actions are
55 * automatically queued and placed into a History after execution.
56 */
57class ActionQueue : public Singleton<ActionQueue>, public Observable
58{
59 friend class Singleton<ActionQueue>;
60public:
61 typedef std::vector<std::string> ActionTokens_t;
62 typedef std::vector< Action * > ActionQueue_t;
63
64 //!> channels for this observable
65 enum NotificationType {
66 ActionQueued, // new action was queued
67 NotificationType_MAX // denotes the maximum of available notification types
68 };
69
70 //>! access to last changed element (atom or molecule)
71 template <class T> const T* lastChanged() const
72 { return Queuedetail::lastChanged<T>(); }
73
74 /** Queues the Action with \a name to be called.
75 *
76 * \param name token of Action to actionqueue
77 * \param state whether Actions needs to be filled via a Dialog or not
78 */
79 void queueAction(const std::string &name, enum Action::QueryOptions state = Action::Interactive);
80
81 /** Returns the spawned action by token \a name.
82 *
83 * Action is checked into internal actionqueue.
84 *
85 * \return ref to newly spawned action
86 */
87 const Action& getActionByName(const std::string &name);
88
89 /** Checks whether the Action is known by the given \a name.
90 *
91 * \param name token of action to check
92 * \return true - token is known, false - else
93 */
94 bool isActionKnownByName(const std::string &name) const;
95
96 /** Register an Action with the ActionRegistry.
97 *
98 * \param _action action to add
99 */
100 void registerAction(Action *_action);
101
102 /** Returns the vector with the tokens of all currently known Actions.
103 *
104 * \return list of all tokens
105 */
106 const ActionTokens_t getListOfActions() const;
107
108 /** Returns the trait to an Action.
109 *
110 * \param name name of Action
111 * \return const ref to its default Trait.
112 */
113 const ActionTrait& getActionsTrait(const std::string &name) const;
114
115 /** Print the current contents of the actionqueue as CLI instantiated list of Actions.
116 *
117 * This is useful for storing the current session.
118 *
119 * \param output output stream to print to
120 */
121 void outputAsCLI(std::ostream &output) const;
122
123 /** Print the current contents of the actionqueue as Python instantiated list of Actions.
124 *
125 * This is useful for storing the current session.
126 *
127 * \param output output stream to print to
128 */
129 void outputAsPython(std::ostream &output) const;
130
131 /** Undoes last called Acfriend void ::cleanUp();tion.
132 *
133 */
134 void undoLast();
135
136 /** Redoes last undone Action.
137 *
138 */
139 void redoLast();
140
141 /** Checks whether there is one completed Action stored in ActionHistory in the past.
142 *
143 * @return true - at least one Action to undo present, false - else
144 */
145 bool canUndo() const;
146
147 /** Checks whether there is one completed Action stored in ActionHistory in the future.
148 *
149 * @return true - at least one Action to redo present, false - else
150 */
151 bool canRedo() const;
152
153 /** Return status of last executed action.
154 *
155 * \return true - action executed correctly, false - else
156 */
157 bool getLastActionOk() const
158 { return lastActionOk; }
159
160 /** Getter to ref to list of status messages.
161 *
162 * This is meant for UIs to registers as Observables.
163 *
164 * \return ref to StatusList variable
165 */
166 ActionStatusList& getStatusList()
167 { return StatusList; }
168
169 /** Getter for isDryRun state flag.
170 *
171 * \return true - ActionQueue does not execute Actions but skips, false - else
172 */
173 bool getDryRun() const
174 { return dryrun_flag; }
175
176 /** States whether the ActionQueue is currently executing Actions or done executing.
177 *
178 * \return true - ActionQueue is done executing Actions.
179 */
180 bool isIdle() const;
181
182 /** States whether the current Action in the ActionQueue is a Process.
183 *
184 * \return true - ActionQueue is currently executing a process.
185 */
186 bool isProcess() const;
187
188 /** States whether the current Action in the ActionQueue is a MakroAction.
189 *
190 * \return true - ActionQueue is currently executing a MakroAction.
191 */
192 bool isMakroAction() const;
193
194 /** Getter to the current Action.
195 *
196 * \note Using this ref is only useful during the execution of the Action, e.g.
197 * when an Action inside the ActionSequence of a MakroAction needs access to the
198 * MakroAction itself (to signal stop). \sa MoleCuilder::ForceAnnealingAction::performCall()
199 *
200 * \warning Due to the multi-threaded nature of the ActionQueue this is very
201 * dangerous to use in other circumstances.
202 *
203 * \return const ref to the currently executed action
204 */
205 const Action& getCurrentAction() const;
206
207private:
208 //!> grant Action access to internal history functions.
209 friend class Action;
210 //!> grant CommandLineParser access to stop and clearQueue()
211 friend class ::CommandLineParser;
212 //!> grant Advocate access to setting dryrun
213 friend class DryRunAdvocate;
214
215 /** Queues the Action with \a name to be called.
216 *
217 * \param _action action to add
218 * \param state whether Actions needs to be filled via a Dialog or not
219 */
220 void queueAction(const Action * const _action, enum Action::QueryOptions state = Action::Interactive);
221
222 /** Wrapper function to add state to ActionHistory.
223 *
224 * \param _Action Action whose state to add
225 * \param _state state to add
226 */
227 void addElement(Action* _Action, ActionState::ptr _state);
228
229 /** Advocate function to add status message to the list.
230 *
231 */
232 void pushStatus(const std::string &_msg)
233 { StatusList.pushMessage(_msg); }
234
235 /** Wrapper function to clear ActionHistory.
236 *
237 */
238 void clear();
239
240 /** Clears all actions present in the actionqueues from \a _fromAction.
241 *
242 * @param _fromAction 0 if all Actions to clear or else
243 */
244 void clearQueue(const size_t _fromAction = 0);
245
246#ifdef HAVE_ACTION_THREAD
247 boost::thread &getRunThread()
248 { return run_thread; }
249
250 /** Clears the temporary queue.
251 *
252 */
253 void clearTempQueue();
254
255 /** Sets the run_thread_isIdle flag.
256 *
257 * @param _flag state to set to
258 */
259 void setRunThreadIdle(const bool _flag);
260
261 /** Runs the ActionQueue.
262 *
263 */
264 void run();
265
266 friend void ::stopQueue();
267
268 /** Stops the internal thread.
269 *
270 */
271 void stop();
272
273 friend void ::waitQueue();
274
275 /** Wait till all currently queued actions are processed.
276 *
277 */
278 void wait();
279
280 /** Moves all action from tempqueue into real queue.
281 *
282 */
283 void insertTempQueue();
284
285#endif
286
287 /** Insert an action after CurrentAction.
288 *
289 * This is implemented only to allow action's COMMAND to work. If we
290 * were to use queueAction, actions would come after all other already
291 * present actions.
292 */
293 void insertAction(Action *_action, enum Action::QueryOptions state);
294
295 /** Sets the current state of the \a isDryRun flag.
296 *
297 * \param _dryrun true - Actions will not get executed anymore, false - else
298 */
299 void setDryRun(const bool _dryrun)
300 { dryrun_flag = _dryrun; }
301
302 /** Checks whether next Action should be skipped or not.
303 *
304 * \param _nextaction next action to execute to inspect whether it unsets dryrun_flag
305 * \return true - dryrun_flag set and \a _nextaction is not unsetting dry run
306 */
307 bool isDryRun(const Action *_nextaction) const;
308
309private:
310 /** Private cstor for ActionQueue.
311 *
312 * Must be private as is singleton.
313 *
314 */
315 ActionQueue();
316
317 /** Dstor for ActionQueue.
318 *
319 */
320 ~ActionQueue();
321
322private:
323 friend const Action *Queuedetail::lastChanged<Action>();
324 static const Action *_lastchangedaction;
325
326 //!> ActionRegistry to spawn new actions
327 ActionRegistry *AR;
328
329 //!> ActionHistory is for undoing and redoing actions, requires ActionRegistry fully initialized
330 ActionHistory *history;
331
332 //!> internal actionqueue of actions
333 ActionQueue_t actionqueue;
334
335 //!> indicates that the last action has failed
336 bool lastActionOk;
337
338 //!> point to current action in actionqueue
339 size_t CurrentAction;
340
341#ifdef HAVE_ACTION_THREAD
342 //!> internal temporary actionqueue of actions used by insertAction()
343 ActionQueue_t tempqueue;
344
345 //!> internal thread to call Actions
346 boost::thread run_thread;
347
348 //!> internal mutex to synchronize access to queue
349 mutable boost::mutex mtx_queue;
350
351 //!> conditional variable notifying when run_thread is idling
352 boost::condition_variable cond_idle;
353
354 //!> flag indicating whether run_thread is idle or not
355 bool run_thread_isIdle;
356
357 //!> internal mutex to synchronize access to run_thread_isIdle
358 mutable boost::mutex mtx_idle;
359#endif
360
361 //!> internal list of status messages from Actions for UIs to display
362 ActionStatusList StatusList;
363
364 //!> internal flag whether to call or skip actions (i.e. do a dry run)
365 bool dryrun_flag;
366};
367namespace Queuedetail {
368 template <> inline const Action* lastChanged<Action>() { return ActionQueue::_lastchangedaction; }
369}
370
371};
372
373#endif /* ACTIONQUEUE_HPP_ */
Note: See TracBrowser for help on using the repository browser.