AAO DRAMA/DRAMA2 C++ Interface
DRAMA C++11 and later interface
monitor1.cpp
/* M O N I T O R 1
* Module name:
MONITOR1
* Function:
A simple DRAMA program demonstrating parameter monitors.
* Description:
Finds the program TESTTASK and monitors parameters within it.
This example uses a monitor based on the drama::thread::MonitorToParam
class. The class allows for parameters in this task to be updated
from the values of the monitored parameters.
* 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
* History:
08-May-2014 - TJF - Original version
* @(#) $Id$
*/
static const char *rcsId="@(#) $Id$";
static void *use_rcsId = (0 ? (void *)(&use_rcsId) : (void *) &rcsId);
#include "drama.hh"
#include "drama/path.hh"
#include <iostream>
/*
* Create a class used to implement our monitors. This is a sub-class of
* MonitorToParam which will update parameters in our task with the values
* of monitored parameters. We subclass MonitorToParam so that we can
* transform the name of the parameter being monitored to the name of
* the parameter we want updated.
*/
class MyMonitor : public drama::thread::MonitorToParam {
// Use the MonitorByType constructors.
using drama::thread::MonitorToParam::MonitorToParam;
// This overrides a method in MonitorToParam.
// Mark them as "override" to ensure we have the signature correct.
std::string Transform(const std::string &in) override;
};
/*
* Invoked to transform the name of a parameter being monitored to the
* name of a parameter in this task that we want the value copied to.
*/
std::string MyMonitor::Transform(const std::string &in)
{
// Just add the T_ prefix to the supplied name.
return std::string("T_") + in;
}
/*
* This function is invoked in a thread, to initiate and run the monitor.
*/
void MonitorThread(drama::Task *task)
{
try
{
/*
* We are not part of a DRAMA action, so we need a UFACE handler to
* deal with the messages.
*/
drama::thread::TUface ufaceHandler(task->TaskPtr());
/*
* Set up access to the testtask program.
*/
drama::Path testtask(task->TaskPtr(), "TESTTASK", "", "./testtask");
/*
* Get path to TESTTASK (loading if required and possible).
*/
testtask.GetPath(&ufaceHandler);
/*
* Create a monitor object, specifying a list of parameters in
* the TESTTASK task to be monitored.
*/
MyMonitor myMonitor(task->TaskPtr(), { "PARAM1" , "PARAM2", "PARAM3" });
try
{
ufaceHandler.MessageUser("About to run monitor");
myMonitor.Run(&testtask, &ufaceHandler);
}
catch (const drama::Exception &e)
{
/*
* If the above threw a DRAMA Run loop exit error, then
* this task was shutdown whilst we were running the monitor.
* In this case, we are not that worried and allow the thread
* to close down without error messages. But for any other
* reason, we re-throw the exception.
*/
if (e.dramaStatus() != DRAMA2__RUN_LOOP_EXIT)
throw e;
}
}
catch (...)
{
/*
* Ensure the DRAMA loop exits and re-throw the exception. The
* exception will be reported by the main program.
*/
throw;
}
/*
* If the thread completes (through it should not unless an exception occurs)
* signal DRAMA to exit.
*/
}
class Monitor : public drama::Task {
private:
std::future<void> _ufaceThreadFuture;
public:
Monitor() : drama::Task("MONITOR1"),
param1(TaskPtr(), "T_PARAM1", 0),
param2(TaskPtr(), "T_PARAM2", ""),
param3(TaskPtr(), "T_PARAM3", 0.0) {
/*
* Our only action is the EXIT action.
*/
/*
* By constructing one of these, we block all signals whilst
* the thread is being created, to avoid race conditions. The
* thread will block signals itself once it starts running. The
* destructor restores the signal mask.
*/
/*
* Start the thread which will do the monitors. This returns a future
* we can use to wait for the thread to exit.
*/
_ufaceThreadFuture = std::async(std::launch::async, MonitorThread, this);
}
/*
* This method will wait for a thread to exit and will throw if the
* monitor thread threw an exception.
*/
void WaitThreadExit(unsigned seconds) {
if (_ufaceThreadFuture.wait_for(std::chrono::seconds(seconds)) !=
std::future_status::ready)
{
DramaTHROW(DRAMA2__THREAD_TIMEOUT,
"UFACE Thread did not complete");
}
_ufaceThreadFuture.get(); // Will throw if thread did.
}
~Monitor() {
}
};
int main()
{
try
{
/*
* Make this program a DRAMA task named MONITOR.
*/
Monitor task;
/*
* Process DRAMA messages.
*/
task.RunDrama();
/*
* Wait for the threads to exit (3 seconds only, timeout causes exception).
*/
task.WaitThreadExit(3);
}
/*
* Deal with any exceptions.
*/
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.
virtual StatusType dramaStatus() const
Return the DRAMA Status code associated with the exception.
Definition exception.hh:404
An Exception class for exceptions thrown by DRAMA V2 classes.
Definition exception.hh:164
The class Parameter is used to implement DRAMA parameters containing primitive items.
Definition parameter.hh:108
A Class which provides access to DRAMA's message sending facilities.
Definition path.hh:689
virtual void Add(const std::string &name, MessageHandlerPtr obj, const std::string &descr="")
Add an action to the task.
Definition task.hh:696
std::weak_ptr< Task > TaskPtr()
Returns a weak pointer to the task.
Definition task.hh:975
A class which implements a DRAMA task.
Definition task.hh:441
virtual std::string Transform(const std::string &in)
Transform method, default implementation.
A class implementing Monitor which copies the value of a monitored parameter into one of the same nam...
Definition threadmonitor.hh:415
Constructing an object of this type will block all blockable UNIX signals in the current thread.
Definition thread.hh:586
A class which allows threads running in a User Interface or similar environments to send DRAMA messag...
Definition threaduface.hh:93
DRAMA 2 main include file.
#define DramaTHROW(status_, message_)
Throw a Drama exception.
Definition exception.hh:93
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:1322
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.
DRAMA 2 include file - Threaded monitoring classes.