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 "skiller_feature.h"
26 
27 #include <core/exceptions/software.h>
28 #include <core/exceptions/system.h>
29 #include <core/threading/mutex.h>
30 #include <logging/component.h>
31 #ifdef SKILLER_TIMETRACKING
32 # include <utils/time/tracker.h>
33 #endif
34 
35 #include <interfaces/SkillerDebugInterface.h>
36 #include <interfaces/SkillerInterface.h>
37 #include <lua/context.h>
38 
39 #include <cstring>
40 #include <lua.hpp>
41 #include <string>
42 #include <tolua++.h>
43 
44 using namespace std;
45 using namespace fawkes;
46 
47 /** @class SkillerExecutionThread "exec_thread.h"
48  * Skiller Execution Thread.
49  * This thread runs and controls the Lua interpreter and passes data into the
50  * execution engine.
51  *
52  * @author Tim Niemueller
53  */
54 
55 /** Constructor. */
57 : Thread("SkillerExecutionThread", Thread::OPMODE_WAITFORWAKEUP),
58  BlockedTimingAspect(BlockedTimingAspect::WAKEUP_HOOK_SKILL),
59  BlackBoardInterfaceListener("SkillerExecutionThread")
60 {
61 }
62 
63 /** Destructor. */
65 {
66 }
67 
68 void
70 {
71  try {
72  cfg_skillspace_ = config->get_string("/skiller/skillspace");
73  cfg_watch_files_ = config->get_bool("/skiller/watch_files");
74  } catch (Exception &e) {
75  e.append("Insufficient configuration for Skiller");
76  throw;
77  }
78 
79  logger->log_debug("SkillerExecutionThread", "Skill space: %s", cfg_skillspace_.c_str());
80  clog_ = new ComponentLogger(logger, "SkillerLua");
81 
82  lua_ = NULL;
83  bbo_ = NULL;
84  skiller_if_ = NULL;
85 
86  try {
87  skiller_if_ = blackboard->open_for_reading<SkillerInterface>("Skiller");
88 
89  lua_ = new LuaContext();
90  if (cfg_watch_files_) {
91  lua_->setup_fam(/* auto restart */ true, /* conc thread */ false);
92  }
93 
94  lua_->add_package_dir(LUADIR, /* prefix */ true);
95  lua_->add_cpackage_dir(LUALIBDIR, /* prefix */ true);
96 
97  lua_->add_package("fawkesutils");
98  lua_->add_package("fawkesconfig");
99  lua_->add_package("fawkeslogging");
100  lua_->add_package("fawkesinterface");
101  lua_->add_package("fawkesblackboard");
102 #ifdef HAVE_TF
103  lua_->add_package("fawkestf");
104 #endif
105 
106  bbo_ = new BlackBoardWithOwnership(blackboard, "SkillerLua");
107 
108  lua_->set_string("SKILLSPACE", cfg_skillspace_.c_str());
109  lua_->set_string("LUADIR", LUADIR);
110  lua_->set_usertype("config", config, "Configuration", "fawkes");
111  lua_->set_usertype("logger", clog_, "ComponentLogger", "fawkes");
112  lua_->set_usertype("clock", clock, "Clock", "fawkes");
113  lua_->set_usertype("blackboard", bbo_, "BlackBoard", "fawkes");
114 #ifdef HAVE_TF
115  lua_->set_usertype("tf", tf_listener, "Transformer", "fawkes::tf");
116 #endif
117 
118  lua_->create_table();
119  lua_->set_global("features_env_template");
120 
121  std::list<SkillerFeature *>::iterator f;
122  for (f = features_.begin(); f != features_.end(); ++f) {
123  (*f)->init_lua_context(lua_);
124  }
125 
126  lua_->set_finalization_calls("skiller.fawkes.finalize()",
127  "skiller.fawkes.finalize_prepare()",
128  "skiller.fawkes.finalize_cancel()");
129 
130  lua_->set_start_script(LUADIR "/skiller/fawkes/start.lua");
131 
132  lua_->add_watcher(this);
133 
134  } catch (Exception &e) {
135  blackboard->close(skiller_if_);
136  delete lua_;
137  delete bbo_;
138  delete clog_;
139  throw;
140  }
141 
142  // We want to know if our reader leaves and closes the interface
143  bbil_add_reader_interface(skiller_if_);
145 }
146 
147 void
149 {
150  lua_->remove_watcher(this);
151 
153  blackboard->close(skiller_if_);
154 
155  std::list<SkillerFeature *>::iterator f;
156  for (f = features_.begin(); f != features_.end(); ++f) {
157  (*f)->finalize_lua_context(lua_);
158  }
159 
160  delete lua_;
161  delete clog_;
162  delete bbo_;
163 }
164 
165 /** Add a skiller feature.
166  * Note that this has to be done before the SkillerExecutionThread is initialized
167  * at this time (an extension to do this at run-time might follow later).
168  * @param feature feature to add
169  */
170 void
172 {
173  features_.push_back(feature);
174 }
175 
176 void
178 {
179  context->create_table();
180  context->set_global("features_env_template");
181 
182  std::list<SkillerFeature *>::iterator f;
183  for (f = features_.begin(); f != features_.end(); ++f) {
184  (*f)->init_lua_context(context);
185  }
186 
187  // move writing interfaces
188  lua_->do_string("return fawkes.interface_initializer.finalize_prepare()");
189 
190  context->create_table();
191 
192  lua_->push_nil();
193  while (lua_->table_next(-2)) {
194  void *udata = lua_->to_usertype(-1);
195  if (udata) {
196  std::string type, id;
197  Interface::parse_uid(lua_->to_string(-2), type, id);
198  context->do_string("require(\"interfaces.%s\")", type.c_str());
199  context->push_string(lua_->to_string(-2));
200  context->push_usertype(udata, type.c_str(), "fawkes");
201  context->set_table(-3);
202  lua_->pop(1);
203  }
204  }
205 
206  context->set_global("interfaces_writing_preload");
207 }
208 
209 void
211  unsigned int instance_serial) throw()
212 {
213  skiller_if_removed_readers_.push_locked(instance_serial);
214 }
215 
216 void
218 {
219 #ifdef HAVE_INOTIFY
220  lua_->process_fam_events();
221 #endif
222 
223  skiller_if_removed_readers_.lock();
224  while (!skiller_if_removed_readers_.empty()) {
225  lua_->do_string("skiller.fawkes.notify_reader_removed(%u)",
226  skiller_if_removed_readers_.front());
227  skiller_if_removed_readers_.pop();
228  }
229  skiller_if_removed_readers_.unlock();
230 
231  lua_->do_string("skillenv.loop()");
232 }
virtual ~SkillerExecutionThread()
Destructor.
Definition: exec_thread.cpp:64
virtual void loop()
Code to execute in the thread.
void unlock() const
Unlock list.
Definition: lock_queue.h:128
SkillerExecutionThread()
Constructor.
Definition: exec_thread.cpp:56
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:918
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: blackboard.cpp:212
Thread class encapsulation of pthreads.
Definition: thread.h:45
void remove_watcher(LuaContextWatcher *watcher)
Remove a context watcher.
Definition: context.cpp:1328
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:78
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:41
void set_table(int t_index=-3)
Set value of a table.
Definition: context.cpp:966
Clock * clock
By means of this member access to the clock is given.
Definition: clock.h:42
Thread aspect to use blocked timing.
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:185
void lua_restarted(fawkes::LuaContext *context)
Lua restart event.
void push_nil()
Push nil on top of stack.
Definition: context.cpp:819
Base class for exceptions in Fawkes.
Definition: exception.h:35
void do_string(const char *format,...)
Execute string.
Definition: context.cpp:532
Lua C++ wrapper.
Definition: context.h:43
BlackBoard that traces interface ownership.
Definition: ownership.h:30
void push_usertype(void *data, const char *type_name, const char *name_space=0)
Push usertype on top of stack.
Definition: context.cpp:882
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:839
void process_fam_events()
Process FAM events.
Definition: context.cpp:1355
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:69
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
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:114
bool table_next(int idx)
Iterate to next entry of table.
Definition: context.cpp:1100
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:991
void create_table(int narr=0, int nrec=0)
Create a table on top of the stack.
Definition: context.cpp:954
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:41
void * to_usertype(int idx)
Retrieve stack value as a tolua++ user type.
Definition: context.cpp:1170
const char * to_string(int idx)
Retrieve stack value as string.
Definition: context.cpp:1140
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:333
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.