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 #include "skiller_feature.h"
25 
26 #include <core/exceptions/software.h>
27 #include <core/exceptions/system.h>
28 #include <core/threading/mutex.h>
29 #include <logging/component.h>
30 #ifdef SKILLER_TIMETRACKING
31 # include <utils/time/tracker.h>
32 #endif
33 
34 #include <lua/context.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 }
63 
64 
65 /** Destructor. */
67 {
68 }
69 
70 
71 void
73 {
74  try {
75  __cfg_skillspace = config->get_string("/skiller/skillspace");
76  __cfg_watch_files = config->get_bool("/skiller/watch_files");
77  } catch (Exception &e) {
78  e.append("Insufficient configuration for Skiller");
79  throw;
80  }
81 
82  logger->log_debug("SkillerExecutionThread", "Skill space: %s", __cfg_skillspace.c_str());
83  __clog = new ComponentLogger(logger, "SkillerLua");
84 
85  __lua = NULL;
86  __bbo = NULL;
87  __skiller_if = NULL;
88 
89  try {
90  __skiller_if = blackboard->open_for_reading<SkillerInterface>("Skiller");
91 
92  __lua = new LuaContext();
93  if (__cfg_watch_files) {
94  __lua->setup_fam(/* auto restart */ true, /* conc thread */ false);
95  }
96 
97  __lua->add_package_dir(LUADIR, /* prefix */ true);
98  __lua->add_cpackage_dir(LUALIBDIR, /* prefix */ true);
99 
100  __lua->add_package("fawkesutils");
101  __lua->add_package("fawkesconfig");
102  __lua->add_package("fawkeslogging");
103  __lua->add_package("fawkesinterface");
104  __lua->add_package("fawkesblackboard");
105 #ifdef HAVE_TF
106  __lua->add_package("fawkestf");
107 #endif
108 
109  __bbo = new BlackBoardWithOwnership(blackboard, "SkillerLua");
110 
111  __lua->set_string("SKILLSPACE", __cfg_skillspace.c_str());
112  __lua->set_string("LUADIR", LUADIR);
113  __lua->set_usertype("config", config, "Configuration", "fawkes");
114  __lua->set_usertype("logger", __clog, "ComponentLogger", "fawkes");
115  __lua->set_usertype("clock", clock, "Clock", "fawkes");
116  __lua->set_usertype("blackboard", __bbo, "BlackBoard", "fawkes");
117 #ifdef HAVE_TF
118  __lua->set_usertype("tf", tf_listener, "Transformer", "fawkes::tf");
119 #endif
120 
121  __lua->create_table();
122  __lua->set_global("features_env_template");
123 
124  std::list<SkillerFeature *>::iterator f;
125  for (f = __features.begin(); f != __features.end(); ++f) {
126  (*f)->init_lua_context(__lua);
127  }
128 
129  __lua->set_finalization_calls("skiller.fawkes.finalize()",
130  "skiller.fawkes.finalize_prepare()",
131  "skiller.fawkes.finalize_cancel()");
132 
133  __lua->set_start_script(LUADIR"/skiller/fawkes/start.lua");
134 
135  __lua->add_watcher(this);
136 
137  } catch (Exception &e) {
138  blackboard->close(__skiller_if);
139  delete __lua;
140  delete __bbo;
141  delete __clog;
142  throw;
143  }
144 
145  // We want to know if our reader leaves and closes the interface
146  bbil_add_reader_interface(__skiller_if);
148 
149 }
150 
151 
152 void
154 {
155  __lua->remove_watcher(this);
156 
158  blackboard->close(__skiller_if);
159 
160  std::list<SkillerFeature *>::iterator f;
161  for (f = __features.begin(); f != __features.end(); ++f) {
162  (*f)->finalize_lua_context(__lua);
163  }
164 
165  delete __lua;
166  delete __clog;
167  delete __bbo;
168 }
169 
170 
171 /** Add a skiller feature.
172  * Note that this has to be done before the SkillerExecutionThread is initialized
173  * at this time (an extension to do this at run-time might follow later).
174  * @param feature feature to add
175  */
176 void
178 {
179  __features.push_back(feature);
180 }
181 
182 
183 void
185 {
186  context->create_table();
187  context->set_global("features_env_template");
188 
189  std::list<SkillerFeature *>::iterator f;
190  for (f = __features.begin(); f != __features.end(); ++f) {
191  (*f)->init_lua_context(context);
192  }
193 
194  // move writing interfaces
195  __lua->do_string("return fawkes.interface_initializer.finalize_prepare()");
196 
197  context->create_table();
198 
199  __lua->push_nil();
200  while (__lua->table_next(-2) ) {
201  void * udata = __lua->to_usertype(-1);
202  if (udata) {
203  std::string type, id;
204  Interface::parse_uid(__lua->to_string(-2), type, id);
205  context->do_string("require(\"interfaces.%s\")", type.c_str());
206  context->push_string(__lua->to_string(-2));
207  context->push_usertype(udata, type.c_str(), "fawkes");
208  context->set_table(-3);
209  __lua->pop(1);
210  }
211  }
212 
213  context->set_global("interfaces_writing_preload");
214 }
215 
216 
217 void
219  unsigned int instance_serial) throw()
220 {
221  __skiller_if_removed_readers.push_locked(instance_serial);
222 }
223 
224 
225 void
227 {
228 #ifdef HAVE_INOTIFY
229  __lua->process_fam_events();
230 #endif
231 
232  __skiller_if_removed_readers.lock();
233  while (! __skiller_if_removed_readers.empty()) {
234  __lua->do_string("skiller.fawkes.notify_reader_removed(%u)", __skiller_if_removed_readers.front());
235  __skiller_if_removed_readers.pop();
236  }
237  __skiller_if_removed_readers.unlock();
238 
239  __lua->do_string("skillenv.loop()");
240 }
virtual ~SkillerExecutionThread()
Destructor.
Definition: exec_thread.cpp:66
virtual void loop()
Code to execute in the thread.
void unlock() const
Unlock list.
Definition: lock_queue.h:131
SkillerExecutionThread()
Constructor.
Definition: exec_thread.cpp:57
void bb_interface_reader_removed(fawkes::Interface *interface, unsigned int instance_serial)
A reading instance has been closed for a watched interface.
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
void pop(int n)
Pop value(s) from stack.
Definition: context.cpp:964
STL namespace.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: blackboard.cpp:218
Thread class encapsulation of pthreads.
Definition: thread.h:42
void remove_watcher(LuaContextWatcher *watcher)
Remove a context watcher.
Definition: context.cpp:1406
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:44
void set_table(int t_index=-3)
Set value of a table.
Definition: context.cpp:1015
Clock * clock
By means of this member access to the clock is given.
Definition: clock.h:45
Thread aspect to use blocked timing.
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:190
void lua_restarted(fawkes::LuaContext *context)
Lua restart event.
void push_nil()
Push nil on top of stack.
Definition: context.cpp:856
Base class for exceptions in Fawkes.
Definition: exception.h:36
void do_string(const char *format,...)
Execute string.
Definition: context.cpp:548
Lua C++ wrapper.
Definition: context.h:47
BlackBoard that traces interface ownership.
Definition: ownership.h:34
void push_usertype(void *data, const char *type_name, const char *name_space=0)
Push usertype on top of stack.
Definition: context.cpp:925
void add_skiller_feature(SkillerFeature *feature)
Add a skiller feature.
Component logger.
Definition: component.h:35
void push_string(const char *value)
Push string on top of stack.
Definition: context.cpp:878
void process_fam_events()
Process FAM events.
Definition: context.cpp:1436
void bbil_add_reader_interface(Interface *interface)
Add an interface to the reader addition/removal watch list.
virtual void init()
Initialize the thread.
Definition: exec_thread.cpp:72
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
void push_locked(const Type &x)
Push element to queue with lock protection.
Definition: lock_queue.h:139
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
void lock() const
Lock queue.
Definition: lock_queue.h:115
bool table_next(int idx)
Iterate to next entry of table.
Definition: context.cpp:1160
SkillerInterface Fawkes BlackBoard Interface.
Skiller feature base class.
virtual void finalize()
Finalize the thread.
void set_global(const char *name)
Set a global value.
Definition: context.cpp:1042
void create_table(int narr=0, int nrec=0)
Create a table on top of the stack.
Definition: context.cpp:1002
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:44
void * to_usertype(int idx)
Retrieve stack value as a tolua++ user type.
Definition: context.cpp:1236
const char * to_string(int idx)
Retrieve stack value as string.
Definition: context.cpp:1204
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:44
virtual void close(Interface *interface)=0
Close interface.