source: src/Actions/ActionQueue.hpp@ 9a4949

Last change on this file since 9a4949 was 9a4949, checked in by Frederik Heber <heber@…>, 10 years ago

Added extra flag run_thread_running to ActionQueue.

  • helgrind admonished race conditions when thread is joined. This did not fix them but should be safer as we cannot know whether the other thread has already been started when suddenly shutting down molecuilder due to an exception.
  • Property mode set to 100644
File size: 7.3 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;
42
43namespace Queuedetail {
44 template <class T> const T* lastChanged()
45 {
46 ASSERT(0, "Queuedetail::lastChanged() - only specializations may be used.");
47 return NULL;
48 }
49}
50
51/** This class combines the whole handling of Actions into a single class.
52 *
53 * It spawns new Actions by its internal ActionRegistry. Spawned Actions are
54 * automatically queued and placed into a History after execution.
55 */
56class ActionQueue : public Singleton<ActionQueue>, public Observable
57{
58 friend class Singleton<ActionQueue>;
59public:
60 typedef std::vector<std::string> ActionTokens_t;
61 typedef std::vector< Action * > ActionQueue_t;
62
63 //!> channels for this observable
64 enum NotificationType {
65 ActionQueued, // new action was queued
66 NotificationType_MAX // denotes the maximum of available notification types
67 };
68
69 //>! access to last changed element (atom or molecule)
70 template <class T> const T* lastChanged() const
71 { return Queuedetail::lastChanged<T>(); }
72
73 /** Queues the Action with \a name to be called.
74 *
75 * \param name token of Action to actionqueue
76 * \param state whether Actions needs to be filled via a Dialog or not
77 */
78 void queueAction(const std::string &name, enum Action::QueryOptions state = Action::Interactive);
79
80 /** Queues the Action with \a name to be called.
81 *
82 * \param _action action to add
83 * \param state whether Actions needs to be filled via a Dialog or not
84 */
85 void queueAction(const Action * const _action, enum Action::QueryOptions state = Action::Interactive);
86
87 /** Returns the spawned action by token \a name.
88 *
89 * Action is checked into internal actionqueue.
90 *
91 * \return pointer to newly spawned action
92 */
93 Action* getActionByName(const std::string &name);
94
95 /** Checks whether the Action is known by the given \a name.
96 *
97 * \param name token of action to check
98 * \return true - token is known, false - else
99 */
100 bool isActionKnownByName(const std::string &name) const;
101
102 /** Register an Action with the ActionRegistry.
103 *
104 * \param _action action to add
105 */
106 void registerAction(Action *_action);
107
108 /** Returns the vector with the tokens of all currently known Actions.
109 *
110 * \return list of all tokens
111 */
112 const ActionTokens_t getListOfActions() const;
113
114 /** Returns the trait to an Action.
115 *
116 * \param name name of Action
117 * \return const ref to its default Trait.
118 */
119 const ActionTrait& getActionsTrait(const std::string &name) const;
120
121 /** Print the current contents of the actionqueue as CLI instantiated list of Actions.
122 *
123 * This is useful for storing the current session.
124 *
125 * \param output output stream to print to
126 */
127 void outputAsCLI(std::ostream &output) const;
128
129 /** Print the current contents of the actionqueue as Python instantiated list of Actions.
130 *
131 * This is useful for storing the current session.
132 *
133 * \param output output stream to print to
134 */
135 void outputAsPython(std::ostream &output) const;
136
137 /** Undoes last called Acfriend void ::cleanUp();tion.
138 *
139 */
140 void undoLast();
141
142 /** Redoes last undone Action.
143 *
144 */
145 void redoLast();
146
147 /** Return status of last executed action.
148 *
149 * \return true - action executed correctly, false - else
150 */
151 bool getLastActionOk() const
152 { return lastActionOk; }
153
154#ifdef HAVE_ACTION_THREAD
155 boost::thread &getRunThread()
156 { return run_thread; }
157#endif
158
159 /** Getter to ref to list of status messages.
160 *
161 * This is meant for UIs to registers as Observables.
162 *
163 * \return ref to StatusList variable
164 */
165 ActionStatusList& getStatusList()
166 { return StatusList; }
167
168private:
169 //!> grant Action access to internal history functions.
170 friend class Action;
171 //!> grant CommandLineParser access to stop and clearQueue()
172 friend class ::CommandLineParser;
173
174 /** Wrapper function to add state to ActionHistory.
175 *
176 * \param _Action Action whose state to add
177 * \param _state state to add
178 */
179 void addElement(Action* _Action, ActionState::ptr _state);
180
181 /** Advocate function to add status message to the list.
182 *
183 */
184 void pushStatus(const std::string &_msg)
185 { StatusList.pushMessage(_msg); }
186
187 /** Wrapper function to clear ActionHistory.
188 *
189 */
190 void clear();
191
192 /** Clears all actions currently present in the actionqueues.
193 *
194 */
195 void clearQueue();
196
197#ifdef HAVE_ACTION_THREAD
198 /** Runs the ActionQueue.
199 *
200 */
201 void run();
202
203 friend void ::stopQueue();
204
205 /** Stops the internal thread.
206 *
207 */
208 void stop();
209
210 friend void ::waitQueue();
211
212 /** Wait till all currently queued actions are processed.
213 *
214 */
215 void wait();
216#endif
217
218 /** Insert an action after CurrentAction.
219 *
220 * This is implemented only to allow action's COMMAND to work. If we
221 * were to use queueAction, actions would come after all other already
222 * present actions.
223 */
224 void insertAction(Action *_action, enum Action::QueryOptions state);
225
226 /** Moves all action from tempqueue into real queue.
227 *
228 */
229 void insertTempQueue();
230
231private:
232 /** Private cstor for ActionQueue.
233 *
234 * Must be private as is singleton.
235 *
236 */
237 ActionQueue();
238
239 /** Dstor for ActionQueue.
240 *
241 */
242 ~ActionQueue();
243
244private:
245 friend const Action *Queuedetail::lastChanged<Action>();
246 static const Action *_lastchangedaction;
247
248 //!> ActionRegistry to spawn new actions
249 ActionRegistry *AR;
250
251 //!> ActionHistory is for undoing and redoing actions, requires ActionRegistry fully initialized
252 ActionHistory *history;
253
254 //!> internal actionqueue of actions
255 ActionQueue_t actionqueue;
256
257 //!> point to current action in actionqueue
258 size_t CurrentAction;
259
260 //!> internal temporary actionqueue of actions used by insertAction()
261 ActionQueue_t tempqueue;
262
263 //!> indicates that the last action has failed
264 bool lastActionOk;
265
266#ifdef HAVE_ACTION_THREAD
267 //!> internal mutex to synchronize access to queue
268 boost::mutex mtx_queue;
269
270 //!> conditional variable notifying when run_thread is idling
271 boost::condition_variable cond_idle;
272
273 //!> flag indicating whether run_thread is idle or not
274 bool run_thread_isIdle;
275
276 //!> internal mutex to synchronize access to run_thread_isIdle
277 boost::mutex mtx_run_thread_isIdle;
278#endif
279
280 //!> internal list of status messages from Actions for UIs to display
281 ActionStatusList StatusList;
282
283 // set run_thread to end such that others are initialized first (especially mutexes)
284#ifdef HAVE_ACTION_THREAD
285 //!> internal flag to tell whether run_thread is still running
286 bool run_thread_running;
287
288 //!> internal thread to call Actions
289 boost::thread run_thread;
290#endif
291};
292namespace Queuedetail {
293 template <> inline const Action* lastChanged<Action>() { return ActionQueue::_lastchangedaction; }
294}
295
296};
297
298#endif /* ACTIONQUEUE_HPP_ */
Note: See TracBrowser for help on using the repository browser.