AAO DRAMA/DRAMA2 C++ Interface
DRAMA C++11 and later interface
threadbasic.cpp
/* T H R E A D B A S I C
* Module name:
threadbasic.cpp
* Function:
Test the basic threading facilities of a DRAMA 2 task.
* Description:
Responds to the following commands
TEST - Basic threading example, action implemented
as a thread, which itself starts a subsidiary
thread. Both threads will wait for a kick, with
5 and 10 second timeouts.
TEST2 - A clone of TEST. Used to confirm we can run two
at the same time.
EXIT - Cause this task to exit.
* Language:
C++
* Copyright (c) Australian Astronomical Observatory, 2014.
Not to be used for commercial purposes without permission.
No warranty of any form unless subject to a specific agreement.
* Support: Tony Farrell, AAO
* @(#) $Id$
*/
#include "drama.hh"
#include "drama/sds.hh"
#include <thread>
#include <iostream>
#include <typeinfo>
class Polymorphic {virtual void member(){}};
class TestAction;
static void SecondThread(TestAction *);
class TestAction : public drama::thread::TAction {
public:
TestAction(std::weak_ptr<drama::Task> theTask) : TAction(theTask) {}
private:
void ActionThread(const drama::sds::Id &obeyArg) override {
#if 0
fprintf(stderr,"threadbasic::ActionThread() invoked, arg=%d, addr=%p\n",
(int)SdsIdType(obeyArg), (void *)(&obeyArg));
#endif
if (obeyArg)
{
std::string MyArgument;
obeyArg.Get("Argument1", &MyArgument);
MessageUser(std::string("Obey Argument is:") + MyArgument);
}
else
{
MessageUser("No argument to obey");
}
/*
* Send a message to the user. (Method of the ActionThread class)
*/
MessageUser("Starting second thread , formated float arg=%, name = %", 23.33, GetActionName());
std::thread childThread(SecondThread, this);
MessageUser("Waiting for kick");
/*
* Create an sds::Id item. We need a std::shared_ptr<> to it, which
* is what IdPtr is
*/
drama::sds::IdPtr Arg{std::make_shared<drama::sds::Id>()};
/*
* Wait for a kick message, with a timeout of 5 seconds.
*
* We pass in our IdPtr item Arg above, so that
* we can get any argument to the message.
*
* WaitForKickTimeIn() returns true if the kick message was received,
* false for a timeout.
*/
if (WaitForKickTimeoutIn(5, &Arg))
{
MessageUser("First thread, received kick");
if (*Arg)
{
std::string MyArgument;
Arg->Get("Argument1", &MyArgument);
MessageUser(MyArgument);
}
}
else
{
MessageUser("First thread, wait for kick timed out");
}
MessageUser("First thread Waiting to join child thread");
childThread.join();
MessageUser("First thread, child has joined");
//DramaTHROW("Test of throw from thread");
//Polymorphic * pb = 0;
//typeid(*pb); // throws a bad_typeid exception
MessageUser("Thread completing");
outArg.Put("Argument1", "Completion Argument.");
SetReturnArg(&outArg);
#if 0
fprintf(stderr,"threadbasic::ActionThread() exiting\n");
#endif
}
};
static void SecondThread(TestAction *action)
{
action->MessageUser("Second thread running, sending trigger");
trigArg.Put("Argument1", "Hi there:");
trigArg.Put("Argument2", "Trigger from second thread");
action->SendTrigger(trigArg);
/*
* Create an sds::Id item. We need a std::shared_ptr<> to it, which
* is what IdPtr is
*/
drama::sds::IdPtr Arg{std::make_shared<drama::sds::Id>()};
/*
* Wait for a kick message, with a timeout of 5 seconds.
*
* We pass in our IdPtr item Arg above, so that
* we can get any argument to the message.
*
* WaitForKickTimeIn() returns true if the kick message was received,
* false for a timeout.
*/
if (action->WaitForKickTimeoutIn(10, &Arg))
{
action->MessageUser("Second thread, received kick.");
if (*Arg)
{
std::string MyArgument;
Arg->Get("Argument1", &MyArgument);
action->MessageUser(MyArgument);
}
}
else
{
action->MessageUser("Second thread, wait for kick time out.");
}
}
class ThreadBasic : public drama::Task {
private:
TestAction TestActionObj;
TestAction Test2ActionObj;
public:
ThreadBasic() : drama::Task("THREADBASIC"), TestActionObj(TaskPtr()), Test2ActionObj(TaskPtr()) {
Add("TEST", drama::MessageHandlerPtr(&TestActionObj, drama::nodel()));
Add("TEST2", drama::MessageHandlerPtr(&Test2ActionObj, drama::nodel()));
}
}
};
int main()
{
try
{
// Make this program a DRAMA task named ticker
ThreadBasic task;
// Process DRAMA messages.
task.RunDrama();
}
catch (const drama::Exception &e)
{
e.Print();
exit (e.statusAsSysExitCode());
}
catch (const std::exception &e)
{
std::cerr << "std::exception thrown by task.RunDrama"
<< e.what()
<< std::endl;
exit(1);
}
return 0;
}
virtual int statusAsSysExitCode() const
Return a system exit code based on the DRAMA Status.
Definition exception.hh:424
virtual void Print(FILE *file=stderr, bool include_stacktrace=false) const
Print exception details to a file.
An Exception class for exceptions thrown by DRAMA V2 classes.
Definition exception.hh:164
virtual void Add(const std::string &name, MessageHandlerPtr obj, const std::string &descr="")
Add an action to the task.
Definition task.hh:696
A class which implements a DRAMA task.
Definition task.hh:441
void Get(const unsigned long length, T *const data, unsigned long *actlen=nullptr, const unsigned long offset=0) const
Get data from an SDS item.
Definition sds.hh:1547
static Id CreateArgStruct(const std::string &name="ArgStructure")
Factory constructor which creates a new "Arg" style SDS structure.
A C++ Interface to the handling SDS structures.
Definition sds.hh:428
bool WaitForKickTimeoutIn(const std::chrono::duration< Rep, Period > &rel_time, sds::IdPtr *const arg=0)
Block the current thread until a kick for the action is received or a duration has passed.
Definition threadaction.hh:813
void MessageUser(const std::string &text) const override
Use DRAMA to send a message to the user.
std::string GetActionName() const
Return the name of the action this thread is implementing.
Definition threadaction.hh:1303
void SetReturnArg(const sds::Id &arg, bool copy=true)
Set the argument to be sent as part of the action completion message.
Definition threadaction.hh:946
A class which implements a DRAMA Action with runs a thread.
Definition threadaction.hh:199
DRAMA 2 main include file.
std::shared_ptr< Id > IdPtr
A shared pointer for sds::Id items.
Definition sds.hh:3318
void CreateRunDramaTask()
Create and run a DRAMA task, with standard exception handling.
Definition task.hh:1322
std::shared_ptr< MessageHandler > MessageHandlerPtr
This type is used for passing MessageHandler object addresses around.
Definition messagehandler.hh:101
Request SimpleExitAction(drama::MessageHandler *messageHandler)
A function which implements a simple exit action.
The drama namespace contains all the classes, types etc of the DRAMA 2 implementation.
Definition drama.hh:93
DRAMA 2 include file - Sds class definition.
Declare an operator to be used as a deletion operator by std::shared_ptr.
Definition task.hh:114