AAO DRAMA/DRAMA2 C++ Interface
DRAMA C++11 and later interface
threaduface.hh
Go to the documentation of this file.
1#ifndef _DRAMA2_THREADUFACE_INC
2#define _DRAMA2_THREADUFACE_INC
17/*
18 * History:
19 07-Apr-2014 - TJF - Original version
20 18-Jan-2018 - TJF - TUface constructor now takes a name for log entries associated
21 with the thread running the uface context.
22
23
24 * The above ID is for Doxygen, this one has the format ACMM is looking for.
25 * "@(#) $Id$"
26 */
28#include "drama/thread.hh"
29#include <thread>
30#include <queue>
31#include <deque>
32#include <map>
33#include <chrono>
34#include <future>
35#include <condition_variable>
36namespace drama {
37
38 namespace thread {
39
53 void SignalDramaToExit(std::weak_ptr<Task> dramaTask,
65 // TMessHandler and RunDramaExitNotifier are abstract only.
66 class TUface : public TMessHandler, public RunDramaExitNotifier {
67
68 private:
69 /*
70 * Pointer to the DRAMA task we are part of.
71 * The pointer is const - we never change it after the constructor.
72 * The task pointed to is NOT const - since we can operate on it.
73 */
74 std::weak_ptr<Task> _theTask;
75 EntryInfo _entryInfo; // UFACE entry details.
76
77 /*
78 * A set of points to UFACE which are used by the logger only
79 * via RegisterThreadNoDramaCtx()
80 */
81 static std::set<TUface *> _loggerOnly;
82
83 public:
84
100 TUface(std::weak_ptr<Task> dramaTask,
101 const std::string &logThreadName="TUface::TUface");
106 virtual ~TUface();
107
108
120 virtual int RunDramaHasExited() override;
137 virtual bool JoinThreads(std::chrono::steady_clock::time_point until) override;
138
139 public:
140
145 std::shared_ptr<Task> GetTask() const override {
146 return std::shared_ptr<Task>(_theTask);
148
168 void MessageUser(const std::string &text) const override;
169
196 template<typename... Types>
197#ifndef RUNNING_DOXYGEN
198 D2_FMT_DEPRECATED("Replace MessageUser() by MessageUserF(). See MessageUserF() page for details.")
199#endif
200 void MessageUser(const char *format, Types... args) {
201 /*
202 * Our approach is to write the output to a string, via
203 * SafePrintf(), then output that in one operation. Since
204 * std::ostream devices will then do the output in one operation.
205 */
206 std::stringstream sstrm;
208 MessageUser(sstrm.str());
209
210
211 }
212
229 template<typename... Args>
230 void MessageUserF(const fmt::format_string<Args...> fmt, Args&&... args) {
231
232 MessageUser(fmt::vformat(fmt.get(), fmt::make_format_args(args...)));
233 }
234
265 Task::mutexType & Lock() const override;
266
275 Dits___CurActType GetMessageContext() const override;
276
281 virtual const EntryInfo & GetEntry() const {
282 return _entryInfo;
283 }
294
295 /*
296 * We save the address in a set.
297 */
298 if (! ___LoggerOnlyUFACEItem(this))
299 _loggerOnly.insert(this);
300 }
311 static bool ___LoggerOnlyUFACEItem(TUface *pnt);
312
313 private:
314 Dits___CurActType _ufaceCtxDetails;
315
316 /*
317 * A map which contains all the events we are waiting on.
318 * (one per subsidiary thread).
319 */
320 WaitEventMapType _waitEventMap;
321
322
323 void MessageReceived();
324 void ProcessSubsidiaryMessage();
325 /*
326 * Invoked by DRAMA when a UFACE message is received.
327 */
328 static void UfaceMessageHandler(StatusType *);
329
330 /*
331 * Invoke when the thread is ending (TUface destructor invoked
332 * - will make any outstanding events into orphans.
333 */
334 void OrphanOutstandingEvents();
335
336
337 protected:
341 void GrabEntryInfo() {
342 _entryInfo.SetFromDits();
343 }
344
345
354 void ClearWait(bool complete) override;
355
356 /*
357 * Return a pointer to the event details for the specified thread.
358 */
359 WaitEventDetails *FindWaitEventDetails(std::thread::id)
360 override;
361
362
370 WaitEventDetails * WaitForTransactionStart() {
371 std::thread::id threadId(std::this_thread::get_id());
372 auto mapItem = _waitEventMap.find(threadId);
373 assert (mapItem != _waitEventMap.end());
374 return (&(mapItem->second));
375 }
376
385 const WaitEventData &details,
386 TransEvtInfo * const eventInfo,
387 sds::IdPtr * const arg) {
388
389
390 *eventInfo = details.eventInfo;
391 /*
392 * If the user wants the argument, return it.
393 */
394 if (arg)
395 {
396 *arg = details.arg;
398 // Should complain here (throw exception?) if queue not empty
399 ClearWait(details.eventInfo.complete);
400
401 }
402
403
404 };
405
406 } // namespace thread
407} // namespace drama
408
409#endif
void SetFromDits()
Grab the information of interest from DITS.
Definition entryinfo.hh:123
The EntryInfo class is used to access details about a DRAMA message event (and entry to an action).
Definition entryinfo.hh:106
A Class which provides access to DRAMA's message sending facilities.
Definition path.hh:689
Class used to arrange for notifications when the RunDrama exits.
Definition task.hh:393
std::recursive_timed_mutex mutexType
Defines the type of our mutex.
Definition task.hh:466
This interface class must be implemented by classes which have threads waiting for messages.
Definition thread.hh:308
static bool ___LoggerOnlyUFACEItem(TUface *pnt)
Indicate if logger only UFACE item created when Logger::RegisterThreadNoDramaCtx() was invoked (Actua...
void MessageUser(const std::string &text) const override
Use DRAMA to send a message to the user.
void WaitForTransactionFinish(const WaitEventData &details, TransEvtInfo *const eventInfo, sds::IdPtr *const arg)
The wait for transaction operation has finished - tidy up.
Definition threaduface.hh:411
std::shared_ptr< Task > GetTask() const override
Get a reference to the DRAMA task we are part of.
Definition threaduface.hh:172
void SetupWaitEvent(DitsTransIdType tid, drama::Path *pathObj) override
Sets up a wait event for this thread.
virtual const EntryInfo & GetEntry() const
Return the entry details.
Definition threaduface.hh:308
TUface(std::weak_ptr< Task > dramaTask, const std::string &logThreadName="TUface::TUface")
Create a DRAMA action/message handler object which runs a thread when the Obey message is received.
Task::mutexType & Lock() const override
Reference the DRAMA Task lock.
virtual ~TUface()
TUface destructor.
void MessageUser(const char *format, Types... args)
Use DRAMA to send a message to the user - safe format.
Definition threaduface.hh:227
void MessageUserF(const fmt::format_string< Args... > fmt, Args &&... args)
Use DRAMA to send a message to the user - format using fmt::format.
Definition threaduface.hh:257
virtual bool JoinThreads(std::chrono::steady_clock::time_point until) override
Invoked when the drama::task::RunDrama() loop exits.
void ClearWait(bool complete) override
Clear the thread' waiting flag in _waitEventMap.
WaitEventDetails * WaitForTransactionStart()
Initiate waiting for a transaction and return a pointer to the item the wait event details.
Definition threaduface.hh:397
virtual int RunDramaHasExited() override
Invoked when the drama::task::RunDrama() loop exits.
Dits___CurActType GetMessageContext() const override
Get the DRAMA Context associated with the UFACE event.
void ___SetLoggerOnlyUFACEItem()
Indicate that this UFACE item is for a thread which invoked Logger::RegisterThreadNoDramaCtx() withou...
Definition threaduface.hh:320
void GrabEntryInfo()
Fetch the DRAMA Entry information.
Definition threaduface.hh:368
A class which allows threads running in a User Interface or similar environments to send DRAMA messag...
Definition threaduface.hh:93
DRAMA 2 include file - Message Handler class definition.
std::shared_ptr< Id > IdPtr
A shared pointer for sds::Id items.
Definition sds.hh:3613
void SignalDramaToExit(std::weak_ptr< Task > dramaTask, StatusType exitStatus=STATUS__OK)
Signal to DRAMA that this task should exit.
void CreateRunDramaTask()
Create and run a DRAMA task, with standard exception handling.
Definition task.hh:1339
void SafePrintf(std::ostream &ostream, const char *str)
Safe formatted write to a stream.
The drama namespace contains all the classes, types etc of the DRAMA 2 implementation.
Definition drama.hh:99
Structure is used to store details about a DRAMA reschedule message relating to a transaction,...
Definition task.hh:134
DRAMA 2 include file - Code common to DRAMA 2 features supporting threading.