Fawkes API  Fawkes Development Version
exec_thread.cpp
1 
2 /***************************************************************************
3  * exec_thread.cpp - Fawkes Skiller: Execution Thread
4  *
5  * Created: Mon Feb 18 10:30:17 2008
6  * Copyright 2006-2009 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "exec_thread.h"
24 
25 #include <core/exceptions/software.h>
26 #include <core/exceptions/system.h>
27 #include <core/threading/mutex.h>
28 #include <logging/component.h>
29 #ifdef SKILLER_TIMETRACKING
30 # include <utils/time/tracker.h>
31 #endif
32 
33 #include <lua/context.h>
34 #include <lua/interface_importer.h>
35 
36 #include <interfaces/SkillerInterface.h>
37 #include <interfaces/SkillerDebugInterface.h>
38 
39 #include <lua.hpp>
40 #include <tolua++.h>
41 
42 #include <string>
43 #include <cstring>
44 
45 using namespace std;
46 using namespace fawkes;
47 
48 /** @class SkillerExecutionThread "exec_thread.h"
49  * Skiller Execution Thread.
50  * This thread runs and controls the Lua interpreter and passes data into the
51  * execution engine.
52  *
53  * @author Tim Niemueller
54  */
55 
56 /** Constructor. */
58  : Thread("SkillerExecutionThread", Thread::OPMODE_WAITFORWAKEUP),
59  BlockedTimingAspect(BlockedTimingAspect::WAKEUP_HOOK_SKILL),
60  BlackBoardInterfaceListener("SkillerExecutionThread")
61 {
62  __continuous_run = false;
63  __continuous_reset = false;
64  __error_written = false;
65 
66  __lua = NULL;
67 }
68 
69 
70 /** Destructor. */
72 {
73 }
74 
75 /** Clean up when init failed.
76  * You may only call this from init(). Never ever call it from anywhere
77  * else!
78  */
79 void
80 SkillerExecutionThread::init_failure_cleanup()
81 {
82  try {
83  if ( __skiller_if ) blackboard->close(__skiller_if);
84  if ( __skdbg_if ) blackboard->close(__skdbg_if);
85 
86  delete __lua_ifi;
87  delete __clog;
88 
89  } catch (...) {
90  // we really screwed up, can't do anything about it, ignore error, logger is
91  // initialized since this method is only called from init() which is only called if
92  // all aspects had been initialized successfully
93  logger->log_error(name(), "Really screwed up while finalizing, aborting cleanup. "
94  "Fawkes is no longer in a clean state. Restart!");
95  }
96 }
97 
98 
99 void
101 {
102  __last_exclusive_controller = 0;
103  __reader_just_left = false;
104  __continuous_run = false;
105  __continuous_reset = false;
106  __skdbg_what = "ACTIVE";
107  __skdbg_graphdir = "TB";
108  __skdbg_graphcolored = true;
109  __clog = NULL;
110  __sksf_pushed = false;
111 
112  try {
113  __cfg_skillspace = config->get_string("/skiller/skillspace");
114  __cfg_watch_files = config->get_bool("/skiller/watch_files");
115  } catch (Exception &e) {
116  e.append("Insufficient configuration for Skiller");
117  throw;
118  }
119 
120  logger->log_debug("SkillerExecutionThread", "Skill space: %s", __cfg_skillspace.c_str());
121 
122  __clog = new ComponentLogger(logger, "SkillerLua");
123 
124  __lua = NULL;
125  __lua_ifi = NULL;
126  __skiller_if = NULL;
127  __skdbg_if = NULL;
128 
129  std::string reading_prefix = "/skiller/interfaces/" + __cfg_skillspace + "/reading/";
130  std::string writing_prefix = "/skiller/interfaces/" + __cfg_skillspace + "/writing/";
131 
132  try {
133  __skiller_if = blackboard->open_for_writing<SkillerInterface>("Skiller");
134  __skdbg_if = blackboard->open_for_writing<SkillerDebugInterface>("Skiller");
135 
136  __lua = new LuaContext();
137  if (__cfg_watch_files) {
138  __lua->setup_fam(/* auto restart */ true, /* conc thread */ false);
139  }
140 
141  __lua_ifi = new LuaInterfaceImporter(__lua, blackboard, config, logger);
142  __lua_ifi->open_reading_interfaces(reading_prefix);
143  __lua_ifi->open_writing_interfaces(writing_prefix);
144  __lua_ifi->add_interface("skdbg", __skdbg_if);
145  __lua_ifi->add_interface("skiller", __skiller_if);
146 
147  __lua->add_package_dir(LUADIR);
148  __lua->add_cpackage_dir(LUALIBDIR);
149 
150  __lua->add_package("fawkesutils");
151  __lua->add_package("fawkesconfig");
152  __lua->add_package("fawkeslogging");
153  __lua->add_package("fawkesinterface");
154  __lua->add_package("fawkesgeometry");
155 #ifdef HAVE_TF
156  __lua->add_package("fawkestf");
157 #endif
158 
159  __lua->set_string("SKILLSPACE", __cfg_skillspace.c_str());
160  __lua->set_usertype("config", config, "Configuration", "fawkes");
161  __lua->set_usertype("logger", __clog, "ComponentLogger", "fawkes");
162  __lua->set_usertype("clock", clock, "Clock", "fawkes");
163 #ifdef HAVE_TF
164  __lua->set_usertype("tf", tf_listener, "Transformer", "fawkes::tf");
165 #endif
166 
167  __lua_ifi->push_interfaces();
168 
169  __lua->set_start_script(LUADIR"/skiller/start.lua");
170 
171  __skiller_if->set_skill_string("");
172  __skiller_if->set_status(SkillerInterface::S_INACTIVE);
173  __skiller_if->write();
174 
175  __skdbg_if->set_graph("");
176  __skdbg_if->set_graph_fsm("ACTIVE");
177 
178  } catch (Exception &e) {
179  init_failure_cleanup();
180  throw;
181  }
182 
183  // We want to know if our reader leaves and closes the interface
184  bbil_add_reader_interface(__skiller_if);
186 
187 #ifdef SKILLER_TIMETRACKING
188  __tt = new TimeTracker();
189  __ttc_total = __tt->add_class("Total");
190  __ttc_msgproc = __tt->add_class("Message Processing");
191  __ttc_luaprep = __tt->add_class("Lua Preparation");
192  __ttc_luaexec = __tt->add_class("Lua Execution");
193  __ttc_publish = __tt->add_class("Publishing");
194  __tt_loopcount = 0;
195 #endif
196 }
197 
198 
199 void
201 {
202 #ifdef SKILLER_TIMETRACKING
203  delete __tt;
204 #endif
205  delete __lua_ifi;
206 
208  blackboard->close(__skiller_if);
209  blackboard->close(__skdbg_if);
210 
211  delete __lua;
212  delete __clog;
213 }
214 
215 
216 void
218  unsigned int instance_serial) throw()
219 {
220  if ( instance_serial == __skiller_if->exclusive_controller() ) {
221  logger->log_debug("SkillerExecutionThread", "Controlling interface instance was closed, "
222  "revoking exclusive control");
223 
224  __last_exclusive_controller = instance_serial;
225  __reader_just_left = true;
226 
227  __skiller_if->set_exclusive_controller(0);
228  __skiller_if->write();
229  }
230 }
231 
232 
233 
234 /** Determines the skill status and writes it to the BB.
235  * This method assumes that it is called from within loop() and lua_mutex is locked.
236  * @param curss current skill string
237  */
238 void
239 SkillerExecutionThread::publish_skill_status(std::string &curss)
240 {
241  //const char *sst = "Unknown";
242  LUA_INTEGER running = 0, final = 0, failed = 0;
243 
244  SkillerInterface::SkillStatusEnum old_status = __skiller_if->status();
245  SkillerInterface::SkillStatusEnum new_status = __skiller_if->status();
246 
247  try {
248 
249  if ( curss == "" ) {
250  // nothing running, we're inactive
251  //sst = "S_INACTIVE/empty";
252  __skiller_if->set_status(SkillerInterface::S_INACTIVE);
253 
254  } else { // Stack:
255  __lua->get_global("skillenv"); // skillenv
256 
257  __lua->get_field(-1, "get_status"); // skillenv skillenv.get_status
258  if ( __lua->is_function(-1) ) {
259  __lua->pcall(0, 3); // skillenv running final failed
260  running = __lua->to_integer(-3);
261  final = __lua->to_integer(-2);
262  failed = __lua->to_integer(-1);
263 
264  __lua->pop(4); // ---
265  } else {
266  __lua->pop(2); // ---
267  throw LuaRuntimeException("C++:publish_skill_status", "skillenv.get_status is not a function");
268  }
269 
270  if ( failed > 0 ) {
271  //sst = "S_FAILED";
272  new_status = SkillerInterface::S_FAILED;
273  } else if ( (final > 0) && (running == 0) ) {
274  //sst = "S_FINAL";
275  new_status = SkillerInterface::S_FINAL;
276  } else if ( running > 0 ) {
277  //sst = "S_RUNNING";
278  new_status = SkillerInterface::S_RUNNING;
279  } else {
280  // all zero
281  //sst = "S_INACTIVE";
282  new_status = SkillerInterface::S_INACTIVE;
283  }
284  }
285 
286  if ( (old_status != new_status) ||
287  (curss != __skiller_if->skill_string()) ||
288  (__skiller_if->is_continuous() != __continuous_run) ) {
289 
290  /*
291  logger->log_debug("SkillerExecutionThread", "Status is %s (%i vs. %i)"
292  "(running %i, final: %i, failed: %i)",
293  sst, old_status, new_status, running, final, failed);
294  */
295 
296  __skiller_if->set_skill_string(curss.c_str());
297  __skiller_if->set_continuous(__continuous_run);
298 
299  __skiller_if->set_status(new_status);
300 
301  if ( ! __error_written && (new_status == SkillerInterface::S_FAILED) ) {
302  publish_error();
303  __error_written = __continuous_run;
304  } else if (new_status == SkillerInterface::S_RUNNING ||
305  new_status == SkillerInterface::S_FINAL) {
306  __skiller_if->set_error("");
307  __error_written = false;
308  }
309 
310  __skiller_if->write();
311  }
312 
313  } catch (Exception &e) {
314  logger->log_error("SkillerExecutionThread", "Failed to retrieve skill status");
315  logger->log_error("SkillerExecutionThread", e);
316  try {
317  __skiller_if->set_status(SkillerInterface::S_FAILED);
318  } catch (Exception &e2) {
319  logger->log_error("SkillerExecutionThread", "Failed to set FAILED as skill "
320  "status value during error handling");
321  logger->log_error("SkillerExecutionThread", e2);
322  }
323  }
324 
325 }
326 
327 
328 void
329 SkillerExecutionThread::publish_skdbg()
330 {
331  try {
332  __lua->do_string("skillenv.write_skiller_debug(interfaces.writing.skdbg, \"%s\", \"%s\", %s)",
333  __skdbg_what.c_str(), __skdbg_graphdir.c_str(),
334  __skdbg_graphcolored ? "true" : "false");
335  } catch (Exception &e) {
336  logger->log_warn("SkillerExecutionThread", "Error writing graph");
337  logger->log_warn("SkillerExecutionThread", e);
338  }
339 }
340 
341 void
342 SkillerExecutionThread::lua_loop_reset()
343 {
344  try {
345  __lua->do_string("skillenv.reset_loop()");
346  } catch (Exception &e) {
347  logger->log_warn("SkillerExecutionThread", "Lua Loop Reset failed");
348  logger->log_warn("SkillerExecutionThread", e);
349  }
350 }
351 
352 
353 void
354 SkillerExecutionThread::publish_error()
355 {
356  try {
357  __lua->do_string("skillenv.write_fsm_error(skillenv.get_skill_fsm(skillenv.get_active_skills()), interfaces.writing.skiller)");
358  } catch (Exception &e) {
359  logger->log_warn("SkillerExecutionThread", "Error writing error");
360  logger->log_warn("SkillerExecutionThread", e);
361  __skiller_if->set_error("Failed to set Lua error");
362  __skiller_if->write();
363  }
364 }
365 
366 
367 void
368 SkillerExecutionThread::process_skdbg_messages()
369 {
370  while ( ! __skdbg_if->msgq_empty() ) {
373  logger->log_warn(name(), "Setting skiller debug what to: %s", m->graph_fsm());
374  __skdbg_what = m->graph_fsm();
377  switch (m->graph_dir()) {
378  case SkillerDebugInterface::GD_BOTTOM_TOP: __skdbg_graphdir = "BT"; break;
379  case SkillerDebugInterface::GD_LEFT_RIGHT: __skdbg_graphdir = "LR"; break;
380  case SkillerDebugInterface::GD_RIGHT_LEFT: __skdbg_graphdir = "RL"; break;
381  default: __skdbg_graphdir = "TB"; break;
382  }
383 
386  __skdbg_graphcolored = m->is_graph_colored();
387  }
388 
389  __skdbg_if->msgq_pop();
390  }
391 }
392 
393 
394 void
396 {
397 #ifdef SKILLER_TIMETRACKING
398  __tt->ping_start(__ttc_total);
399 #endif
400 #ifdef HAVE_INOTIFY
401  __lua->process_fam_events();
402 #endif
403  __lua_ifi->read();
404 
405  // Current skill string
406  std::string curss = "";
407 
408  unsigned int excl_ctrl = __skiller_if->exclusive_controller();
409  bool write_skiller_if = false;
410  bool last_was_continuous = __continuous_run;
411 
412 #ifdef SKILLER_TIMETRACKING
413  __tt->ping_start(__ttc_msgproc);
414 #endif
415  process_skdbg_messages();
416 
417  while ( ! __skiller_if->msgq_empty() ) {
419  Message *m = __skiller_if->msgq_first();
420  if ( excl_ctrl == 0 ) {
421  logger->log_debug("SkillerExecutionThread", "%s is new exclusive controller",
422  m->sender_thread_name());
423  __skiller_if->set_exclusive_controller(m->sender_id());
424  write_skiller_if = true;
425  excl_ctrl = m->sender_id();
426  } else if (excl_ctrl == m->sender_id()) {
427  // ignored
428  } else {
429  logger->log_warn("SkillerExecutionThread", "%s tried to acquire "
430  "exclusive control, but another controller exists "
431  "already", m->sender_thread_name());
432  }
433 
434  } else if ( __skiller_if->msgq_first_is<SkillerInterface::ReleaseControlMessage>() ) {
435  Message *m = __skiller_if->msgq_first();
436  if ( excl_ctrl == m->sender_id() ) {
437  logger->log_debug("SkillerExecutionThread", "%s releases exclusive control",
438  m->sender_thread_name());
439 
440  if ( __continuous_run ) {
441  __continuous_run = false;
442  __continuous_reset = true;
443  }
444  __last_exclusive_controller = __skiller_if->exclusive_controller();
445  __skiller_if->set_exclusive_controller(0);
446  write_skiller_if = true;
447  excl_ctrl = 0;
448  } else {
449  if ( !__reader_just_left || (m->sender_id() != __last_exclusive_controller)) {
450  logger->log_warn("SkillerExecutionThread", "%s tried to release exclusive control, "
451  "it's not the controller", m->sender_thread_name());
452  }
453  }
454  } else if ( __skiller_if->msgq_first_is<SkillerInterface::ExecSkillMessage>() ) {
456 
457  if ( m->sender_id() == excl_ctrl ) {
458  if ( curss != "" ) {
459  logger->log_warn("SkillerExecutionThread", "More than one skill string enqueued, "
460  "ignoring previous string (%s).", curss.c_str());
461  }
462  logger->log_debug("SkillerExecutionThread", "%s wants me to execute '%s'",
463  m->sender_thread_name(), m->skill_string());
464 
465  if ( __continuous_run ) {
466  __continuous_run = false;
467  __continuous_reset = true;
468  }
469  curss = m->skill_string();
470  } else {
471  logger->log_debug("SkillerExecutionThread", "%s tries to exec while not controller",
472  m->sender_thread_name());
473  }
474 
475  } else if ( __skiller_if->msgq_first_is<SkillerInterface::ExecSkillContinuousMessage>() ) {
477 
478  if ( m->sender_id() == excl_ctrl ) {
479  if ( curss != "" ) {
480  logger->log_warn("SkillerExecutionThread", "More than one skill string enqueued, "
481  "ignoring successive string (%s).", m->skill_string());
482  } else {
483  logger->log_debug("SkillerExecutionThread", "%s wants me to continuously execute '%s'",
484  m->sender_thread_name(), m->skill_string());
485 
486  curss = m->skill_string();
487  __continuous_reset = last_was_continuous; // reset if cont exec was in progress
488  __continuous_run = true;
489  }
490  } else {
491  logger->log_debug("SkillerExecutionThread", "%s tries to exec while not controller",
492  m->sender_thread_name());
493  }
494 
495  } else if ( __skiller_if->msgq_first_is<SkillerInterface::StopExecMessage>() ) {
497 
498  if ( (m->sender_id() == excl_ctrl) ||
499  (__reader_just_left && (m->sender_id() == __last_exclusive_controller)) ) {
500  logger->log_debug("SkillerExecutionThread", "Stopping continuous execution");
501  if ( __continuous_run ) {
502  __continuous_run = false;
503  __continuous_reset = true;
504  curss = "";
505  }
506  } else {
507  logger->log_debug("SkillerExecutionThread", "%s tries to stop exec while not controller",
508  m->sender_thread_name());
509  }
510  } else {
511  logger->log_warn("SkillerExecutionThread", "Unhandled message of type %s in "
512  "skiller interface", __skiller_if->msgq_first()->type());
513  }
514 
515  __skiller_if->msgq_pop();
516  }
517 
518  if ( __continuous_run && (curss == "") ) {
519  curss = __skiller_if->skill_string();
520  }
521 
522 #ifdef SKILLER_TIMETRACKING
523  __tt->ping_end(__ttc_msgproc);
524 #endif
525 
526  if ( __continuous_reset ) {
527  logger->log_debug("SkillerExecutionThread", "Continuous reset forced"); try {
528  if (__sksf_pushed) {
529  __sksf_pushed = false;
530  __lua->pop(1); // ---
531  }
532  __lua->do_string("skillenv.reset_all()");
533  } catch (Exception &e) {
534  logger->log_warn("SkillerExecutionThread", "Caught exception while resetting skills, ignored, output follows");
535  logger->log_warn("SkillerExecutionThread", e);
536  }
537 
538  __skiller_if->set_status(SkillerInterface::S_INACTIVE);
539  __skiller_if->set_skill_string("");
540 
541  //We're not resetting, because this is information someone might need...
542  //__skiller_if->set_error("");
543  __error_written = false;
544  __continuous_reset = false;
545  write_skiller_if = true;
546  }
547 
548  if ( write_skiller_if ) __skiller_if->write();
549 
550  if ( curss != "" ) {
551  // We've got something to execute
552 
553 #ifdef SKILLER_TIMETRACKING
554  __tt->ping_start(__ttc_luaprep);
555 #endif
556 
557  // we're in continuous mode, reset status for this new loop
558  if ( __continuous_run ) {
559  // was continuous execution, status has to be cleaned up anyway
560  //logger->log_debug("SkillerExecutionThread", "Resetting skill status in continuous mode");
561  try {
562  __lua->do_string("skillenv.reset_status()");
563  } catch (Exception &e) {
564  logger->log_warn("SkillerExecutionThread", "Caught exception while resetting status, ignored, output follows");
565  logger->log_warn("SkillerExecutionThread", e);
566  }
567  }
568 
569  try {
570  if (! __sksf_pushed) {
571  // Stack:
572  __lua->load_string(curss.c_str()); // sksf (skill string function)
573  __lua->do_string("return skillenv.gensandbox()"); // sksf, sandbox
574  __lua->setfenv(); // sksf
575  __sksf_pushed = true;
576  }
577 #ifdef SKILLER_TIMETRACKING
578  __tt->ping_end(__ttc_luaprep);
579  __tt->ping_start(__ttc_luaexec);
580 #endif
581  __lua->push_value(-1); // sksf sksf
582  __lua->pcall(); // sksf
583 
584  } catch (Exception &e) {
585  logger->log_error("SkillerExecutionThread", e);
586  __skiller_if->set_error("Skill string execution failed with Lua error, see log");
587  __skiller_if->write();
588  __continuous_reset = true;
589  __continuous_run = false;
590  }
591 #ifdef SKILLER_TIMETRACKING
592  __tt->ping_end(__ttc_luaexec);
593 #endif
594 
595  if ( ! __continuous_run ) {
596  // was one-shot execution, cleanup
597  logger->log_debug("SkillerExecutionThread", "Resetting skills");
598  try {
599  if (__sksf_pushed) {
600  __sksf_pushed = false;
601  __lua->pop(1); // ---
602  }
603  __lua->do_string("skillenv.reset_all()");
604  } catch (Exception &e) {
605  logger->log_warn("SkillerExecutionThread", "Caught exception while resetting skills, ignored, output follows");
606  logger->log_warn("SkillerExecutionThread", e);
607  }
608  }
609 
610  } // end if (curss != "")
611 
612 #ifdef SKILLER_TIMETRACKING
613  __tt->ping_start(__ttc_publish);
614 #endif
615  publish_skill_status(curss);
616  publish_skdbg();
617  lua_loop_reset();
618 
619  __reader_just_left = false;
620 
621  __lua_ifi->write();
622 #ifdef SKILLER_TIMETRACKING
623  __tt->ping_end(__ttc_publish);
624  __tt->ping_end(__ttc_total);
625  if (++__tt_loopcount >= SKILLER_TT_MOD) {
626  //logger->log_debug("Lua", "Stack size: %i", __lua->stack_size());
627  __tt_loopcount = 0;
628  __tt->print_to_stdout();
629  }
630 #endif
631 }
SkillerDebugInterface Fawkes BlackBoard Interface.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:43
virtual ~SkillerExecutionThread()
Destructor.
Definition: exec_thread.cpp:71
bool msgq_empty()
Check if queue is empty.
Definition: interface.cpp:972
uint32_t exclusive_controller() const
Get exclusive_controller value.
SkillStatusEnum status() const
Get status value.
virtual void loop()
Code to execute in the thread.
SkillerExecutionThread()
Constructor.
Definition: exec_thread.cpp:57
const char * type() const
Get message type.
Definition: message.cpp:378
void bb_interface_reader_removed(fawkes::Interface *interface, unsigned int instance_serial)
A reading instance has been closed for a watched interface.
void set_exclusive_controller(const uint32_t new_exclusive_controller)
Set exclusive_controller value.
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
StopExecMessage Fawkes BlackBoard Interface Message.
void pop(int n)
Pop value(s) from stack.
Definition: context.cpp:854
STL namespace.
GraphDirectionEnum graph_dir() const
Get graph_dir value.
ReleaseControlMessage Fawkes BlackBoard Interface Message.
void load_string(const char *s)
Load Lua string.
Definition: context.cpp:501
SkillStatusEnum
This determines the current status of skill execution.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: blackboard.cpp:200
Thread class encapsulation of pthreads.
Definition: thread.h:42
SetGraphMessage Fawkes BlackBoard Interface Message.
void write()
Write from local copy into BlackBoard memory.
Definition: interface.cpp:495
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:80
char * graph_fsm() const
Get graph_fsm value.
void open_writing_interfaces(std::string &prefix)
Open interfaces for writing.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:44
AcquireControlMessage Fawkes BlackBoard Interface Message.
virtual Interface * open_for_writing(const char *interface_type, const char *identifier)=0
Open interface for writing.
Clock * clock
By means of this member access to the clock is given.
Definition: clock.h:45
bool is_continuous() const
Get continuous value.
Thread aspect to use blocked timing.
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:174
void msgq_pop()
Erase first message from queue.
Definition: interface.cpp:1118
void push_value(int idx)
Push a copy of the element at the given index on top of the stack.
Definition: context.cpp:799
void set_error(const char *new_error)
Set error value.
void pcall(int nargs=0, int nresults=0, int errfunc=0)
Protected call.
Definition: context.cpp:529
Base class for exceptions in Fawkes.
Definition: exception.h:36
Message * msgq_first()
Get the first message from the message queue.
Definition: interface.cpp:1104
const char * sender_thread_name() const
Get sender of message.
Definition: message.cpp:335
void do_string(const char *format,...)
Execute string.
Definition: context.cpp:471
Lua interface importer.
void setfenv(int idx=-2)
Set function environment.
Definition: context.cpp:1204
void open_reading_interfaces(std::string &prefix)
Open interfaces for reading.
unsigned int sender_id() const
Get ID of sender.
Definition: message.cpp:345
Lua C++ wrapper.
Definition: context.h:47
bool running() const
Check if the thread is running.
Definition: thread.cpp:835
void get_field(int idx, const char *k)
Get named value from table.
Definition: context.cpp:959
Time tracking utility.
Definition: tracker.h:38
ExecSkillMessage Fawkes BlackBoard Interface Message.
lua_Integer to_integer(int idx)
Retrieve stack value as integer.
Definition: context.cpp:1060
bool msgq_first_is()
Check if first message has desired type.
Definition: interface.h:305
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
Component logger.
Definition: component.h:35
const char * name() const
Get name of thread.
Definition: thread.h:95
void add_interface(std::string varname, Interface *interface)
Add a single interface to be pushed to the context.
SetGraphColoredMessage Fawkes BlackBoard Interface Message.
void read()
Read from all reading interfaces.
void process_fam_events()
Process FAM events.
Definition: context.cpp:1233
void bbil_add_reader_interface(Interface *interface)
Add an interface to the reader addition/removal watch list.
virtual void init()
Initialize the thread.
char * skill_string() const
Get skill_string value.
void get_global(const char *name)
Get global variable.
Definition: context.cpp:1016
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
void set_continuous(const bool new_continuous)
Set continuous value.
bool is_function(int idx)
Check if stack value is a function.
Definition: context.cpp:1115
void set_skill_string(const char *new_skill_string)
Set skill_string value.
char * skill_string() const
Get skill_string value.
Lua runtime exception.
Definition: exceptions.h:30
void write()
Write all writing interfaces.
SkillerInterface Fawkes BlackBoard Interface.
virtual void finalize()
Finalize the thread.
void set_status(const SkillStatusEnum new_status)
Set status value.
ExecSkillContinuousMessage Fawkes BlackBoard Interface Message.
bool is_graph_colored() const
Get graph_colored value.
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:44
SetGraphDirectionMessage Fawkes BlackBoard Interface Message.
char * skill_string() const
Get skill_string value.
void push_interfaces()
Push interfaces to Lua environment.
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
BlackBoard interface listener.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
Definition: blackboard.h:43
virtual void close(Interface *interface)=0
Close interface.