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
44using namespace std;
45using 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
68void
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
147void
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 */
170void
172{
173 features_.push_back(feature);
174}
175
176void
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
209void
211 Uuid instance_serial) noexcept
212{
213 skiller_if_removed_readers_.push_locked(instance_serial);
214}
215
216void
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(\"%s\")",
226 skiller_if_removed_readers_.front().get_string().c_str());
227 skiller_if_removed_readers_.pop();
228 }
229 skiller_if_removed_readers_.unlock();
230
231 lua_->do_string("skillenv.loop()");
232}
virtual void loop()
Code to execute in the thread.
virtual void init()
Initialize the thread.
Definition: exec_thread.cpp:69
void add_skiller_feature(SkillerFeature *feature)
Add a skiller feature.
void lua_restarted(fawkes::LuaContext *context)
Lua restart event.
void bb_interface_reader_removed(fawkes::Interface *interface, fawkes::Uuid instance_serial) noexcept
A reading instance has been closed for a watched interface.
virtual ~SkillerExecutionThread()
Destructor.
Definition: exec_thread.cpp:64
virtual void finalize()
Finalize the thread.
SkillerExecutionThread()
Constructor.
Definition: exec_thread.cpp:56
Skiller feature base class.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
Definition: blackboard.h:44
BlackBoard interface listener.
void bbil_add_reader_interface(Interface *interface)
Add an interface to the reader addition/removal watch list.
BlackBoard that traces interface ownership.
Definition: ownership.h:31
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: blackboard.cpp:212
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:185
virtual void close(Interface *interface)=0
Close interface.
Thread aspect to use blocked timing.
Clock * clock
By means of this member access to the clock is given.
Definition: clock.h:42
Component logger.
Definition: component.h:36
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:41
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
Base class for exceptions in Fawkes.
Definition: exception.h:36
void append(const char *format,...) noexcept
Append messages to the message list.
Definition: exception.cpp:333
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:80
void lock() const
Lock queue.
Definition: lock_queue.h:114
void unlock() const
Unlock list.
Definition: lock_queue.h:128
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:41
Lua C++ wrapper.
Definition: context.h:44
void push_string(const char *value)
Push string on top of stack.
Definition: context.cpp:839
void set_global(const char *name)
Set a global value.
Definition: context.cpp:991
void * to_usertype(int idx)
Retrieve stack value as a tolua++ user type.
Definition: context.cpp:1170
void push_nil()
Push nil on top of stack.
Definition: context.cpp:819
void process_fam_events()
Process FAM events.
Definition: context.cpp:1355
void remove_watcher(LuaContextWatcher *watcher)
Remove a context watcher.
Definition: context.cpp:1328
const char * to_string(int idx)
Retrieve stack value as string.
Definition: context.cpp:1140
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 create_table(int narr=0, int nrec=0)
Create a table on top of the stack.
Definition: context.cpp:954
void pop(int n)
Pop value(s) from stack.
Definition: context.cpp:918
void do_string(const char *format,...)
Execute string.
Definition: context.cpp:532
void set_table(int t_index=-3)
Set value of a table.
Definition: context.cpp:966
bool table_next(int idx)
Iterate to next entry of table.
Definition: context.cpp:1100
SkillerInterface Fawkes BlackBoard Interface.
Thread class encapsulation of pthreads.
Definition: thread.h:46
A convenience class for universally unique identifiers (UUIDs).
Definition: uuid.h:29
Fawkes library namespace.