AAO DRAMA/DRAMA2 C++ 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: ACMM:Drama2/examples/monitor1.cpp,v 1.45+ 22-Feb-2016 14:09:53+11 tjf $
*/
static const char *rcsId="@(#) $Id: ACMM:Drama2/examples/monitor1.cpp,v 1.45+ 22-Feb-2016 14:09:53+11 tjf $";
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 (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.
*/
drama::thread::SignalBlocker threadSignalBlocker;
/*
* 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 (drama::Exception &e)
{
e.Print();
exit (e.statusAsSysExitCode());
}
catch (std::exception &e)
{
std::cerr << "std::exception thrown by task.RunDrama"
<< e.what()
<< std::endl;
exit(1);
}
return 0;
}

Click here for the DRAMA home page and here for the AAO home page.

For more information, contact tjf@aao.gov.au 

Generated on Mon Feb 22 2016 15:57:52 for AAO DRAMA/DRAMA2 C++ Interface by doxygen 1.8.10