Fawkes API
Fawkes Development Version
|
24 #include <aspect/manager.h>
25 #include <baseapp/main_thread.h>
26 #include <config/config.h>
27 #include <core/exceptions/system.h>
28 #include <core/macros.h>
29 #include <core/threading/interruptible_barrier.h>
30 #include <core/threading/mutex_locker.h>
31 #include <core/version.h>
32 #include <plugin/loader.h>
33 #include <plugin/manager.h>
34 #include <utils/time/clock.h>
35 #include <utils/time/wait.h>
69 const char * load_plugins,
70 const char * default_plugin)
71 :
Thread(
"FawkesMainThread")
73 plugin_manager_ = plugin_manager;
74 thread_manager_ = thread_manager;
75 syncpoint_manager_ = syncpoint_manager;
76 multi_logger_ = multi_logger;
79 mainloop_thread_ = NULL;
80 mainloop_mutex_ =
new Mutex();
85 load_plugins_ = strdup(load_plugins);
88 default_plugin_ = NULL;
90 default_plugin_ = strdup(default_plugin);
96 loop_start_ =
new Time(clock_);
97 loop_end_ =
new Time(clock_);
99 max_thread_time_usec_ = config_->
get_uint(
"/fawkes/mainapp/max_thread_time");
101 max_thread_time_usec_ = 30000;
102 multi_logger_->
log_info(
"FawkesMainApp",
"Maximum thread time not set, assuming 30ms.");
104 max_thread_time_nanosec_ = max_thread_time_usec_ * 1000;
108 desired_loop_time_usec_ = config_->
get_uint(
"/fawkes/mainapp/desired_loop_time");
109 if (desired_loop_time_usec_ > 0) {
110 time_wait_ =
new TimeWait(clock_, desired_loop_time_usec_);
113 desired_loop_time_usec_ = 0;
114 multi_logger_->
log_info(
"FawkesMainApp",
"Desired loop time not set, assuming 0");
117 desired_loop_time_sec_ = (float)desired_loop_time_usec_ / 1000000.f;
120 enable_looptime_warnings_ = config_->
get_bool(
"/fawkes/mainapp/enable_looptime_warnings");
121 if (!enable_looptime_warnings_) {
122 multi_logger_->
log_debug(
name(),
"loop time warnings are disabled");
125 enable_looptime_warnings_ =
true;
139 FawkesMainThread::destruct()
143 }
catch (CouldNotOpenFileException &e) {
144 if (e.get_errno() == EACCES) {
145 multi_logger_->
log_warn(
"FawkesMainThread",
146 "Cannot write to dump file, "
148 multi_logger_->
log_warn(
"FawkesMainThread",
149 "permission for file or "
151 multi_logger_->
log_warn(
"FawkesMainThread",
152 "usually happens if running "
154 multi_logger_->
log_warn(
"FawkesMainThread",
155 "installed Fawkes as non-root "
157 multi_logger_->
log_warn(
"FawkesMainThread",
158 "configuration changes to the "
160 multi_logger_->
log_warn(
"FawkesMainThread",
161 "database (set as non-default "
164 multi_logger_->
log_warn(
"FawkesMainThread",
165 "Failed to dump default "
166 "config (open), exception follows.");
167 multi_logger_->
log_warn(
"FawkesMainThread", e);
169 }
catch (Exception &e) {
170 multi_logger_->
log_warn(
"FawkesMainThread",
171 "Failed to dump default config, "
172 "exception follows.");
173 multi_logger_->
log_warn(
"FawkesMainThread", e);
179 free(default_plugin_);
185 delete mainloop_barrier_;
186 delete mainloop_mutex_;
196 init_barrier_ =
new Barrier(2);
200 init_barrier_->
wait();
201 delete (init_barrier_);
209 std::vector<BlockedTimingAspect::WakeupHook> hooks;
222 for (std::vector<BlockedTimingAspect::WakeupHook>::const_iterator it = hooks.begin();
225 syncpoints_start_hook_.push_back(syncpoint_manager_->
get_syncpoint(
227 syncpoints_start_hook_.back()->register_emitter(
"FawkesMainThread");
228 syncpoints_end_hook_.push_back(syncpoint_manager_->
get_syncpoint(
232 multi_logger_->
log_error(
"FawkesMainThread",
"Failed to acquire mainloop syncpoint");
239 plugin_manager_->
load(load_plugins_);
241 multi_logger_->
log_error(
"FawkesMainThread",
242 "Failed to load plugins %s, "
245 multi_logger_->
log_error(
"FawkesMainThread", e);
251 if (default_plugin_ && (strcmp(
"default", default_plugin_) != 0)) {
252 plugin_manager_->
load(default_plugin_);
258 multi_logger_->
log_error(
"FawkesMainThread",
259 "Failed to load default "
260 "plugins, exception follows");
261 multi_logger_->
log_error(
"FawkesMainThread", e);
266 if (!load_plugins_) {
268 plugin_manager_->
load(
"default");
273 multi_logger_->
log_error(
"FawkesMainThread",
274 "Failed to load default "
275 "plugins, exception follows");
276 multi_logger_->
log_error(
"FawkesMainThread", e);
279 multi_logger_->
log_error(
"FawkesMainThread",
280 "Failed to load default "
281 "plugins, exception follows");
282 multi_logger_->
log_error(
"FawkesMainThread", e);
287 init_barrier_->
wait();
294 mainloop_mutex_->
lock();
296 mainloop_thread_ = mainloop_thread;
297 mainloop_mutex_->
unlock();
305 multi_logger_->
log_debug(
"FawkesMainThread",
"No timed threads exist, waiting");
308 multi_logger_->
log_debug(
"FawkesMainThread",
309 "Timed threads have been added, "
310 "running main loop now");
312 multi_logger_->
log_debug(
"FawkesMainThread",
"Waiting for timed threads interrupted");
317 plugin_manager_->
lock();
328 mainloop_mutex_->
lock();
330 if (unlikely(mainloop_thread_ != NULL)) {
332 if (likely(mainloop_thread_ != NULL)) {
333 mainloop_thread_->
wakeup(mainloop_barrier_);
334 mainloop_barrier_->
wait();
337 multi_logger_->
log_warn(
"FawkesMainThread", e);
340 uint num_hooks = syncpoints_start_hook_.size();
341 if (syncpoints_end_hook_.size() != num_hooks) {
344 "Hook syncpoints are not initialized properly, not waking up any threads!");
346 for (uint i = 0; i < num_hooks; i++) {
347 syncpoints_start_hook_[i]->emit(
"FawkesMainThread");
348 syncpoints_end_hook_[i]->reltime_wait_for_all(
"FawkesMainThread",
350 max_thread_time_nanosec_);
354 mainloop_mutex_->
unlock();
360 if (!recovered_threads_.empty()) {
363 if (enable_looptime_warnings_) {
364 if (recovered_threads_.size() == 1) {
365 multi_logger_->
log_warn(
"FawkesMainThread",
366 "The thread %s could be "
367 "recovered and resumes normal operation",
368 recovered_threads_.front().c_str());
371 for (std::list<std::string>::iterator i = recovered_threads_.begin();
372 i != recovered_threads_.end();
377 multi_logger_->
log_warn(
"FawkesMainThread",
378 "The following threads could be "
379 "recovered and resumed normal operation: %s",
383 recovered_threads_.clear();
386 if (desired_loop_time_sec_ > 0) {
388 float loop_time = *loop_end_ - loop_start_;
389 if (enable_looptime_warnings_) {
392 if (loop_time > 1.1 * desired_loop_time_sec_) {
393 multi_logger_->
log_warn(
"FawkesMainThread",
394 "Loop time exceeded, "
395 "desired: %f sec (%u usec), actual: %f sec",
396 desired_loop_time_sec_,
397 desired_loop_time_usec_,
403 plugin_manager_->
unlock();
411 multi_logger_->
log_warn(
"FawkesMainThread",
412 "Exception caught while executing default main "
414 multi_logger_->
log_warn(
"FawkesMainThread", e);
415 }
catch (std::exception &e) {
416 multi_logger_->
log_warn(
"FawkesMainThread",
417 "STL Exception caught while executing default main "
418 "loop, ignoring. (what: %s)",
431 return multi_logger_;
447 init_mutex_ =
new Mutex();
448 init_running_ =
true;
450 sigint_running_ =
false;
451 register_signals_ = register_signals;
456 if (register_signals_) {
466 if (register_signals_) {
479 init_running_ =
false;
482 fmt_->logger()->log_info(
"FawkesMainThread",
483 "Fawkes %s startup complete",
484 FAWKES_VERSION_STRING);
485 init_mutex_->unlock();
488 init_mutex_->unlock();
498 if ((signum == SIGINT) && !sigint_running_) {
505 sigint_running_ =
true;
507 }
else if (signum == SIGALRM) {
510 printf(
"\nFawkes shutdown and finalization procedure still running.\n"
511 "Hit Ctrl-C again to force immediate exit.\n\n");
513 }
else if ((signum == SIGTERM) || sigint_running_) {
void lock()
Lock this mutex.
@ WAKEUP_HOOK_WORLDSTATE
world state thread
virtual void log_error(const char *component, const char *format,...)
Log error message.
static std::string blocked_timing_hook_to_start_syncpoint(WakeupHook hook)
Get the syncpoint identifier corresponding to the start of a wakeup hook.
This class gives access to SyncPoints.
virtual void try_recover(std::list< std::string > &recovered_threads)
Try to recover threads.
Runner(FawkesMainThread *fmt, bool register_signals=true)
Constructor.
void unlock()
Unlock plugin manager.
Mutex mutual exclusion lock.
void lock()
Lock plugin manager.
virtual bool timed_threads_exist()
Check if any timed threads exist.
bool wait(unsigned int timeout_sec, unsigned int timeout_nanosec)
Wait for other threads.
Log through multiple loggers.
@ WAKEUP_HOOK_SENSOR_PREPARE
sensor data preparation thread, convert acquired data to usable format
void wakeup()
Wake up thread.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
The current system call has been interrupted (for instance by a signal).
@ WAKEUP_HOOK_THINK
think thread (agent)
virtual void wait_for_timed_threads()
Wait for timed threads.
void interrupt()
Interrupt the barrier.
void handle_signal(int signum)
Handle signals.
void yield()
Yield the processor to another thread or process.
void run()
Run main thread.
static void ignore(int signum)
Ignore a signal.
Time & stamp_systime()
Set this time to the current system time.
const char * name() const
Get name of thread.
This exception is thrown if the requested plugin could not be loaded.
MultiLogger * logger() const
Get logger.
Fawkes default main thread.
void unlock()
Unlock the mutex.
static SignalHandler * register_handler(int signum, SignalHandler *handler)
Register a SignalHandler for a signal.
void test_cancel()
Set cancellation point.
Interface for configuration handling.
FawkesMainThread(Configuration *config, MultiLogger *multi_logger, ThreadManager *thread_manager, SyncPointManager *syncpoint_manager, PluginManager *plugin_manager, const char *load_plugins, const char *default_plugin=0)
Constructor.
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
@ WAKEUP_HOOK_SENSOR_PROCESS
sensor data processing thread
void full_start()
Start the thread and wait until once() completes.
std::string plugin_name() const
Get name of plugin which failed to load.
void exit()
Exit the thread.
static void unregister_handler(int signum)
Unregister a SignalHandler for a signal.
RefPtr< SyncPoint > get_syncpoint(const std::string &component, const std::string &identifier)
Get a SyncPoint.
@ WAKEUP_HOOK_ACT_EXEC
act execution thread
Fawkes library namespace.
virtual void loop()
Code to execute in the thread.
void load(const std::string &plugin_list)
Load plugin.
@ WAKEUP_HOOK_PRE_LOOP
before each loop
@ WAKEUP_HOOK_ACT
act thread (motor module etc.)
@ CANCEL_DISABLED
thread cannot be cancelled
virtual void once()
Execute an action exactly once.
Base application thread manager.
void mark_start()
Mark start of loop.
virtual ~FawkesMainThread()
Destructor.
Mutex * loopinterrupt_antistarve_mutex
Mutex to avoid starvation when trying to lock loop_mutex.
A class for handling time.
static std::string blocked_timing_hook_to_end_syncpoint(WakeupHook hook)
Get the syncpoint identifier corresponding to the end of a wakeup hook.
Thread class encapsulation of pthreads.
void start(bool wait=true)
Call this method to start the thread.
static void set_cancel_state(CancelState new_state, CancelState *old_state=0)
Set the cancel state of the current thread.
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
void wait_systime()
Wait until minimum loop time has been reached in real time.
static Clock * instance()
Clock initializer.
virtual void set_mainloop_thread(Thread *mainloop_thread)
Set a new main loop.
virtual void try_dump()=0
Try to dump configuration.
@ WAKEUP_HOOK_POST_LOOP
run after loop
@ WAKEUP_HOOK_SKILL
skill thread (skill module)
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
virtual void wait()
Wait for other threads.
@ WAKEUP_HOOK_SENSOR_ACQUIRE
sensor acquisition thread, acquire data from sensor
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Base class for exceptions in Fawkes.