Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
laser_filter_plugin.cpp
1 
2 /***************************************************************************
3  * laser_filter_plugin.cpp - Fawkes Laser Filter Plugin
4  *
5  * Created: Sun Mar 13 01:06:51 2011
6  * Copyright 2006-2011 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 "laser_filter_plugin.h"
24 
25 #include "filter_thread.h"
26 
27 #include <core/threading/barrier.h>
28 #include <map>
29 #include <set>
30 #include <memory>
31 
32 using namespace fawkes;
33 
34 /** @class LaserFilterPlugin "laser_filter_plugin.h"
35  * Laser filter plugin for Fawkes.
36  * This plugin filters laser data. It reads laser data from one or more
37  * interfaces, filters it, and writes to an output interface. It supports
38  * a virtually arbitrary number of active filters.
39  * @author Tim Niemueller
40  */
41 
42 /** Constructor.
43  * @param config Fawkes configuration
44  */
46  : Plugin(config)
47 {
48  __barrier = NULL;
49 
50  std::set<std::string> configs;
51  std::set<std::string> ignored_configs;
52  std::map<std::string, LaserFilterThread *> threads;
53 
54  std::string prefix = "/plugins/laser-filter/";
55 
56  // Read configurations and spawn LaserFilterThreads
57  std::auto_ptr<Configuration::ValueIterator> i(config->search(prefix.c_str()));
58  while (i->next()) {
59  std::string cfg_name = std::string(i->path()).substr(prefix.length());
60  cfg_name = cfg_name.substr(0, cfg_name.find("/"));
61 
62  if ( (configs.find(cfg_name) == configs.end()) &&
63  (ignored_configs.find(cfg_name) == ignored_configs.end()) ) {
64 
65  std::string cfg_prefix = prefix + cfg_name + "/";
66 
67  bool active = true;
68  try {
69  active = config->get_bool((cfg_prefix + "active").c_str());
70  } catch (Exception &e) {} // ignored, assume enabled
71 
72  try {
73  if (active) {
74  LaserFilterThread *thread = new LaserFilterThread(cfg_name, cfg_prefix);
75  thread_list.push_back(thread);
76  threads[cfg_name] = thread;
77  configs.insert(cfg_name);
78  } else {
79  //printf("Ignoring laser config %s\n", cfg_name.c_str());
80  ignored_configs.insert(cfg_name);
81  }
82  } catch(Exception &e) {
83  for (ThreadList::iterator i = thread_list.begin();
84  i != thread_list.end(); ++i) {
85  delete *i;
86  }
87  throw;
88  }
89  }
90  }
91 
92  if ( thread_list.empty() ) {
93  throw Exception("No active laser filters configured, aborting");
94  }
95 
96  // Read input and output information for spawned configurations
97  // for dependency detection
98  std::map<std::string, std::list<std::string> > inputs;
99  std::map<std::string, std::list<std::string> > outputs;
100  std::set<std::string>::iterator c, d;
101 
102  for (c = configs.begin(); c != configs.end(); ++c) {
103  std::string cinp = prefix + *c + "/in/";
104  std::list<std::string> cinputs;
105  std::auto_ptr<Configuration::ValueIterator> in(config->search(cinp.c_str()));
106  while (in->next()) {
107  if (in->is_string()) {
108  cinputs.push_back(in->get_string());
109  }
110  }
111 
112  std::string coutp = prefix + *c + "/out/";
113  std::list<std::string> coutputs;
114  std::auto_ptr<Configuration::ValueIterator> out(config->search(coutp.c_str()));
115  while (out->next()) {
116  if (out->is_string()) {
117  coutputs.push_back(out->get_string());
118  }
119  }
120 
121  inputs[*c] = cinputs;
122  outputs[*c] = coutputs;
123  }
124 
125  // Detect inter-thread dependencies, setup proper serialization by
126  // create a list of threads that one threads depends on and setting
127  // it. Setup common "end of filtering" barrier.
128  try {
129  bool has_deps = false;
130  for (c = configs.begin(); c != configs.end(); ++c) {
131 
132  //printf("Config %s\n", c->c_str());
133 
134  std::list<LaserFilterThread *> depthreads;
135 
136  std::list<std::string>::iterator i, o;
137  std::list<std::string> &cinputs = inputs[*c];
138  for (i = cinputs.begin(); i != cinputs.end(); ++i) {
139  //printf(" Input %s\n", i->c_str());
140 
141  for (d = configs.begin(); d != configs.end(); ++d) {
142  if (*c == *d) continue;
143  //printf(" Config %s\n", d->c_str());
144 
145  std::list<std::string> &coutputs = outputs[*d];
146  for (o = coutputs.begin(); o != coutputs.end(); ++o) {
147  //printf(" Output %s\n", o->c_str());
148  if (*i == *o) {
149  has_deps = true;
150  //printf(" *** Dep Thread matches %s for %s\n",
151  // d->c_str(), o->c_str());
152  depthreads.push_back(threads[*d]);
153  break;
154  }
155  }
156  }
157  }
158 
159  if (! depthreads.empty()) {
160  depthreads.sort();
161  depthreads.unique();
162  threads[*c]->set_wait_threads(depthreads);
163  }
164  }
165 
166  // If any dependencies have been detected, have all threads wait at
167  // a common "end of filtering" barrier, which allows for resetting
168  // a "need to wait for done" flag.
169  if (has_deps) {
170  std::map<std::string, LaserFilterThread *>::iterator t;
171  __barrier = new Barrier(threads.size());
172  for (t = threads.begin(); t != threads.end(); ++t) {
173  t->second->set_wait_barrier(__barrier);
174  }
175  }
176 
177  } catch (Exception &e) {
178  ThreadList::iterator t;
179  for (t = thread_list.begin(); t != thread_list.end(); ++t) {
180  delete *t;
181  }
182  throw;
183  }
184 }
185 
186 
187 LaserFilterPlugin::~LaserFilterPlugin()
188 {
189  delete __barrier;
190 }
191 
192 
193 PLUGIN_DESCRIPTION("Filter laser data in blackboard")
194 EXPORT_PLUGIN(LaserFilterPlugin)
Plugin interface class.
Definition: plugin.h:33
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
virtual ValueIterator * search(const char *path)=0
Iterator with search results.
virtual bool next()=0
Check if there is another element and advance to this if possible.
ThreadList & threads()
Get a list of threads.
Definition: plugin.cpp:110
virtual bool is_string() const =0
Check if current value is a string.
Base class for exceptions in Fawkes.
Definition: exception.h:36
ThreadList thread_list
Thread list member.
Definition: plugin.h:53
virtual std::string get_string() const =0
Get string value.
Laser filter thread.
Definition: filter_thread.h:46
virtual const char * path() const =0
Path of value.
void push_back(Thread *thread)
Add thread to the end.
Laser filter plugin for Fawkes.
LaserFilterPlugin(fawkes::Configuration *config)
Constructor.
Interface for configuration handling.
Definition: config.h:63
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
Definition: barrier.h:32