42 bool attachedTerminal;
56 attachedToPort(false),
57 attachedTerminal(false)
64 yCInfo(RFMODULE,
"Listening to terminal (type \"quit\" to stop module).");
66 while (!(isEof || isStopping() || owner.
isStopping())) {
76 for (
size_t i = 0; i < reply.
size(); i++) {
83 yCInfo(RFMODULE,
"Command not understood -- %s.", str.c_str());
87 yCDebug(RFMODULE,
"terminal shutting down\n");
94 attachedToPort =
true;
102 attachedToPort =
true;
110 attachedTerminal =
true;
119 return attachedTerminal;
125 yCWarning(RFMODULE,
"Critical: stopping thread, this might hang.");
136 if (!cmd.
read(connection)) {
141 bool result = owner.safeRespond(cmd, response);
142 if (response.
size() >= 1) {
144 if (writer !=
nullptr) {
146 for (
size_t i = 1; i < response.
size(); i++) {
157 response.
write(*writer);
188 bool singleton_run_module;
196 singleton_run_module(false),
197 respond_handler(nullptr),
198 threaded_handler(nullptr)
205 delete respond_handler;
206 delete threaded_handler;
213 return threaded_handler !=
nullptr;
218 delete threaded_handler;
219 threaded_handler =
nullptr;
225 return singleton_run_module;
229 singleton_run_module =
true;
238 if (mPriv->threaded_handler !=
nullptr) {
239 return mPriv->threaded_handler->getKey();
251 yCInfo(RFMODULE,
"Aborting (calling abort())...");
254 yCInfo(RFMODULE,
"[try %d of 3] Trying to shut down.", ct);
282 static void handler_sigbreak(
int sig)
284 yarp::os::impl::raise(SIGINT);
301 yCInfo(RFMODULE,
"RFModule::RFModule() signal handling currently only good for one module.");
305 yarp::os::impl::signal(SIGBREAK, handler_sigbreak);
308 yarp::os::impl::signal(SIGINT,
handler);
309 yarp::os::impl::signal(SIGTERM,
handler);
328 if (mPriv->getSingletonRunModule()) {
331 mPriv->setSingletonRunModule();
359 if (sleepPeriod > 1) {
368 yCInfo(RFMODULE,
"RFModule closing.");
369 if (mPriv->respond_handler->isTerminalAttached()) {
370 yCWarning(RFMODULE,
"Module attached to terminal calling exit() to quit.");
371 yCWarning(RFMODULE,
"You should be aware that this is not a good way to stop a module. Effects will be:");
372 yCWarning(RFMODULE,
"- class destructors will NOT be called");
373 yCWarning(RFMODULE,
"- code in the main after runModule() will NOT be executed");
374 yCWarning(RFMODULE,
"This happens because in your module you called attachTerminal() and we don't have a portable way to quit a module that is listening to the terminal.");
375 yCWarning(RFMODULE,
"At the moment the only way to have the module quit correctly is to avoid listening to terminal (i.e. do not call attachTerminal()).");
376 yCWarning(RFMODULE,
"This will also make this annoying message go away.");
387 yCInfo(RFMODULE,
"RFModule finished.");
394 if (mPriv->getSingletonRunModule()) {
399 yCInfo(RFMODULE,
"RFModule failed to open.");
408 if (mPriv->getSingletonRunModule()) {
412 if (!mPriv->newThreadHandler()) {
413 yCError(RFMODULE,
"RFModule handling thread failed to allocate.");
417 if (!mPriv->threaded_handler->start()) {
418 yCError(RFMODULE,
"RFModule handling thread failed to start.");
428 if (mPriv->getSingletonRunModule()) {
433 yCError(RFMODULE,
"RFModule failed to open.");
450 return basicRespond(command, reply);
461 mPriv->respond_handler->attach(source);
468 mPriv->respond_handler->attach(source);
475 mPriv->respond_handler->attachTerminal();
482 mPriv->respond_handler->detachTerminal();
504 yCError(RFMODULE,
"interruptModule() returned an error there could be problems shutting down the module.");
521 if (mPriv->threaded_handler !=
nullptr) {
522 if (mPriv->threaded_handler->join(seconds)) {
523 mPriv->deleteThreadHandler();
526 yCWarning(RFMODULE,
"RFModule joinModule() timed out.");
529 yCWarning(RFMODULE,
"Cannot call join: RFModule runModule() is not currently threaded.");
536 if (subName.empty()) {
540 std::string base = name;
544 if (subName[0] !=
'/') {
545 yCWarning(RFMODULE,
"SubName in getName() does not begin with \"/\" this suggest you expect getName() to follow a deprecated behavior.");
546 yCWarning(RFMODULE,
"I am now adding \"/\" between %s and %s but you should not rely on this.", name.c_str(), subName.c_str());
564 bool ok =
respond(command, reply);
567 ok = basicRespond(command, reply);
573 bool RFModule::basicRespond(
const Bottle& command,
Bottle& reply)
579 reply.addVocab(Vocab::
encode(
"bye"));
583 reply.
addString(
"command not recognized");
static void handler(int sig)
bool attach(yarp::os::RpcServer &source)
bool attach(yarp::os::Port &source)
void run() override
Main body of the new thread.
RFModuleRespondHandler(RFModule &owner)
bool isTerminalAttached()
bool read(yarp::os::ConnectionReader &connection) override
Handler for reading messages from the network, and passing them on to the respond() method.
void run() override
Main body of the new thread.
RFModuleThreadedHandler(RFModule &owner)
bool getSingletonRunModule()
RFModuleThreadedHandler * threaded_handler
void setSingletonRunModule()
void deleteThreadHandler()
RFModuleRespondHandler * respond_handler
A simple collection of objects that can be described and transmitted in a portable way.
void add(const Value &value)
Add a Value to the bottle, at the end of the list.
size_type size() const
Gets the number of elements in the bottle.
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
void addString(const char *str)
Places a string in the bottle, at the end of the list.
std::string toString() const override
Gives a human-readable textual representation of the bottle.
An interface for reading from a network connection.
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
An interface for writing to a network connection.
virtual bool isTextMode() const =0
Check if the connection is text mode.
static void initMinimum()
Basic system initialization, not including plugins.
static void finiMinimum()
Deinitialization, excluding plugins.
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
A mini-server for network communication.
void setReader(PortReader &reader) override
Set an external reader for port data.
A base-class for standard YARP modules that supports ResourceFinder.
virtual ~RFModule()
Destructor.
virtual int runModule()
Calls updateModule() until that returns false.
bool attachTerminal()
Make any input from standard input (usually the keyboard) go to the respond() method.
virtual bool updateModule()=0
Override this to do whatever your module needs to do.
bool joinModule(double seconds=-1)
The function returns when the thread execution has completed.
virtual bool close()
Close function.
void setName(const char *name)
Set the name of the module.
virtual bool respond(const Bottle &command, Bottle &reply)
Respond to a message.
virtual bool attach(yarp::os::Port &source)
Make any input from a Port object go to the respond() method.
virtual bool configure(yarp::os::ResourceFinder &rf)
Configure the module, pass a ResourceFinder object to the module.
virtual int getThreadKey()
return the Thread unique identifier
virtual bool interruptModule()
Try to halt any ongoing operations by threads managed by the module.
bool safeRespond(const Bottle &command, Bottle &reply)
Wrapper around respond() that is guaranteed to process system messages.
bool detachTerminal()
Detach terminal.
void stopModule(bool wait=false)
Ask the module to stop.
virtual int runModuleThreaded()
Calls updateModule() on a separate thread until that returns false.
bool isStopping()
Check if the module should stop.
virtual double getPeriod()
You can override this to control the approximate periodicity at which updateModule() is called by run...
std::string getName(const std::string &subName="")
Return name of module, as set with setName().
Helper class for finding config files and other external resources.
A port that is specialized as an RPC server.
An abstraction for a thread of execution.
static long int getKeyOfCaller()
Get a unique identifier for the calling thread.
bool stop()
Stop the thread.
bool start()
Start the new thread running.
A single value (typically within a Bottle).
virtual bool isList() const
Checks if value is a list.
virtual Bottle * asList() const
Get list value.
std::string toString() const override
Return a standard text representation of the content of the object.
virtual std::int32_t asVocab() const
Get vocabulary identifier as an integer.
#define yCInfo(component,...)
#define yCError(component,...)
#define yCWarning(component,...)
#define yCDebug(component,...)
#define YARP_OS_LOG_COMPONENT(name, name_string)
void useSystemClock()
Configure YARP to use system time (this is the default).
void yield()
The calling thread releases its remaining quantum upon calling this function.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
void delay(double seconds)
Wait for a certain number of seconds.
NetInt32 encode(const std::string &str)
Convert a string into a vocabulary identifier.
std::string readString(bool *eof)
The components from which ports and connections are built.
An interface to the operating system, including Port based communication.
constexpr yarp::conf::vocab32_t createVocab(char a, char b=0, char c=0, char d=0)
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
The main, catch-all namespace for YARP.