Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * manager.cpp - Fawkes Aspect Manager 00004 * 00005 * Created: Thu Nov 25 00:34:06 2010 (based on inifin.h) 00006 * Copyright 2006-2010 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <aspect/manager.h> 00025 #include <aspect/inifins/aspect_provider.h> 00026 #include <aspect/inifins/blackboard.h> 00027 #include <aspect/inifins/blocked_timing.h> 00028 #include <aspect/inifins/clock.h> 00029 #include <aspect/inifins/configurable.h> 00030 #include <aspect/inifins/fawkes_network.h> 00031 #include <aspect/inifins/logger.h> 00032 #include <aspect/inifins/logging.h> 00033 #include <aspect/inifins/mainloop.h> 00034 #include <aspect/inifins/network.h> 00035 #include <aspect/inifins/plugin_director.h> 00036 #include <aspect/inifins/thread_producer.h> 00037 #include <aspect/inifins/time_source.h> 00038 #include <aspect/inifins/vision_master.h> 00039 #include <aspect/inifins/vision.h> 00040 #ifdef HAVE_WEBVIEW 00041 # include <aspect/inifins/webview.h> 00042 #endif 00043 #ifdef HAVE_TF 00044 # include <aspect/inifins/tf.h> 00045 #endif 00046 #ifdef HAVE_PCL 00047 # include <aspect/inifins/pointcloud.h> 00048 #endif 00049 00050 namespace fawkes { 00051 #if 0 /* just to make Emacs auto-indent happy */ 00052 } 00053 #endif 00054 00055 /** @class AspectManager <aspect/manager.h> 00056 * Aspect and aspect initializer/finalizer manager. 00057 * This class is the central gatekeeper to aspects for the main application. 00058 * It manages the initializers/finalizers and thus the aspects which are 00059 * currently available in the system. It assures that these are not removed 00060 * before the last thread with an aspect is gone. 00061 * @author Tim Niemueller 00062 */ 00063 00064 /** Constructor. */ 00065 AspectManager::~AspectManager() 00066 { 00067 std::map<std::string, AspectIniFin *>::iterator i; 00068 for (i = __default_inifins.begin(); i != __default_inifins.end(); ++i) { 00069 delete i->second; 00070 } 00071 __default_inifins.clear(); 00072 } 00073 00074 /** Register initializer/finalizer. 00075 * @param inifin aspect initializer/finalizer to register 00076 */ 00077 void 00078 AspectManager::register_inifin(AspectIniFin *inifin) 00079 { 00080 if (__inifins.find(inifin->get_aspect_name()) != __inifins.end()) { 00081 throw Exception("An initializer for %s has already been registered", 00082 inifin->get_aspect_name()); 00083 } 00084 __inifins[inifin->get_aspect_name()] = inifin; 00085 } 00086 00087 /** Unregister initializer/finalizer. 00088 * @param inifin aspect initializer/finalizer to unregister 00089 */ 00090 void 00091 AspectManager::unregister_inifin(AspectIniFin *inifin) 00092 { 00093 if (__inifins.find(inifin->get_aspect_name()) == __inifins.end()) { 00094 throw Exception("An initializer for %s has not been registered", 00095 inifin->get_aspect_name()); 00096 } 00097 if (! __threads[inifin->get_aspect_name()].empty()) { 00098 throw Exception("Threads with the %s aspect are still alive, cannot " 00099 "unregister the aspect", inifin->get_aspect_name()); 00100 } 00101 __inifins.erase(inifin->get_aspect_name()); 00102 __threads.erase(inifin->get_aspect_name()); 00103 } 00104 00105 /** Check if threads for a particular aspect still exist. 00106 * @param aspect_name name of the aspect to check for 00107 * @return true if thread for the given aspect have been registered, 00108 * false otherwise 00109 */ 00110 bool 00111 AspectManager::has_threads_for_aspect(const char *aspect_name) 00112 { 00113 return (__threads.find(aspect_name) != __threads.end()) && 00114 (! __threads[aspect_name].empty()); 00115 } 00116 00117 void 00118 AspectManager::init(Thread *thread) 00119 { 00120 Aspect *aspected_thread = dynamic_cast<Aspect *>(thread); 00121 if (aspected_thread != NULL) { // thread has aspects to initialize 00122 const std::list<const char *> &aspects = aspected_thread->get_aspects(); 00123 00124 std::list<const char *> initialized; 00125 00126 try { 00127 std::list<const char *>::const_iterator i; 00128 for (i = aspects.begin(); i != aspects.end(); ++i) { 00129 if (__inifins.find(*i) == __inifins.end()) { 00130 throw CannotInitializeThreadException("Thread '%s' has the %s, " 00131 "but no initiliazer is known.", 00132 thread->name(), *i); 00133 } 00134 __inifins[*i]->init(thread); 00135 initialized.push_back(*i); 00136 } 00137 00138 for (i = aspects.begin(); i != aspects.end(); ++i) { 00139 __threads[*i].push_back(thread); 00140 } 00141 } catch (CannotInitializeThreadException &e) { 00142 std::list<const char *>::const_reverse_iterator i; 00143 for (i = initialized.rbegin(); i != initialized.rend(); ++i) { 00144 __inifins[*i]->finalize(thread); 00145 } 00146 throw; 00147 } catch (Exception &e) { 00148 std::list<const char *>::const_reverse_iterator i; 00149 for (i = initialized.rbegin(); i != initialized.rend(); ++i) { 00150 __inifins[*i]->finalize(thread); 00151 } 00152 CannotInitializeThreadException ce; 00153 ce.append(e); 00154 throw ce; 00155 } 00156 } 00157 } 00158 00159 void AspectManager::finalize(Thread *thread) 00160 { 00161 Aspect *aspected_thread = dynamic_cast<Aspect *>(thread); 00162 if (aspected_thread != NULL) { // thread has aspects to finalize 00163 const std::list<const char *> &aspects = aspected_thread->get_aspects(); 00164 00165 std::list<const char *>::const_iterator i; 00166 for (i = aspects.begin(); i != aspects.end(); ++i) { 00167 if (__inifins.find(*i) == __inifins.end()) { 00168 throw CannotFinalizeThreadException("Thread '%s' has the %s, " 00169 "but no finalizer is known.", 00170 thread->name(), *i); 00171 } 00172 __inifins[*i]->finalize(thread); 00173 } 00174 00175 // We remove the threads afterwards, because we assume that the plugin 00176 // will not be unloaded, if the finalization throws an exception. 00177 for (i = aspects.begin(); i != aspects.end(); ++i) { 00178 __threads[*i].remove(thread); 00179 } 00180 } 00181 } 00182 00183 00184 bool 00185 AspectManager::prepare_finalize(Thread *thread) 00186 { 00187 Aspect *aspected_thread = dynamic_cast<Aspect *>(thread); 00188 if (aspected_thread != NULL) { // thread has aspects to finalize 00189 const std::list<const char *> &aspects = aspected_thread->get_aspects(); 00190 00191 std::list<const char *>::const_iterator i; 00192 for (i = aspects.begin(); i != aspects.end(); ++i) { 00193 if (__inifins.find(*i) == __inifins.end()) { 00194 throw CannotFinalizeThreadException("Thread '%s' has the %s, " 00195 "but no finalizer is known.", 00196 thread->name(), *i); 00197 } 00198 if (!__inifins[*i]->prepare_finalize(thread)) { 00199 return false; 00200 } 00201 } 00202 } 00203 00204 return true; 00205 } 00206 00207 /** Register default aspect initializer/finalizer. 00208 * This loads initializer/finalizer of all aspects which are in the 00209 * Fawkes aspect library. 00210 * @param blackboard blackboard for BlackBoardAspect and TransformAspect 00211 * @param collector thread collector for ThreadProducerAspect 00212 * @param config configuration for ConfigurableAspect 00213 * @param clock clock for ClockAspect 00214 * @param logger logger for LoggingAspect 00215 * @param fnethub Fawkes network hub for FawkesNetworkAspect 00216 * @param mloop_employer Main loop employer for MainLoopAspect 00217 * @param logger_employer logger employer for LoggerAspect 00218 * @param btexec blocked timing executor for MainLoopAspect 00219 * @param nnresolver network name resolver for NetworkAspect 00220 * @param service_publisher service publisher for NetworkAspect 00221 * @param service_browser service browser for NetworkAspect 00222 * @param pmanager plugin manager for PluginDirectorAspect 00223 */ 00224 void 00225 AspectManager::register_default_inifins(BlackBoard *blackboard, 00226 ThreadCollector *collector, 00227 Configuration *config, 00228 Logger *logger, 00229 Clock *clock, 00230 FawkesNetworkHub *fnethub, 00231 MainLoopEmployer *mloop_employer, 00232 LoggerEmployer *logger_employer, 00233 BlockedTimingExecutor *btexec, 00234 NetworkNameResolver *nnresolver, 00235 ServicePublisher *service_publisher, 00236 ServiceBrowser *service_browser, 00237 PluginManager *pmanager) 00238 { 00239 if (! __default_inifins.empty()) return; 00240 00241 AspectProviderAspectIniFin *prov_aif = new AspectProviderAspectIniFin(this); 00242 BlackBoardAspectIniFin *bb_aif = new BlackBoardAspectIniFin(blackboard); 00243 BlockedTimingAspectIniFin *bt_aif = new BlockedTimingAspectIniFin(); 00244 ClockAspectIniFin *clock_aif = new ClockAspectIniFin(clock); 00245 ConfigurableAspectIniFin *conf_aif = new ConfigurableAspectIniFin(config); 00246 FawkesNetworkAspectIniFin *fnet_aif = new FawkesNetworkAspectIniFin(fnethub); 00247 LoggerAspectIniFin *logger_aif = new LoggerAspectIniFin(logger_employer); 00248 LoggingAspectIniFin *log_aif = new LoggingAspectIniFin(logger); 00249 MainLoopAspectIniFin *mloop_aif = new MainLoopAspectIniFin(mloop_employer, 00250 btexec); 00251 NetworkAspectIniFin *net_aif = new NetworkAspectIniFin(nnresolver, 00252 service_publisher, 00253 service_browser); 00254 PluginDirectorAspectIniFin *plug_aif = new PluginDirectorAspectIniFin(pmanager); 00255 ThreadProducerAspectIniFin *tp_aif = new ThreadProducerAspectIniFin(collector); 00256 TimeSourceAspectIniFin *ts_aif = new TimeSourceAspectIniFin(clock); 00257 VisionMasterAspectIniFin *vm_aif = new VisionMasterAspectIniFin(); 00258 VisionAspectIniFin *vis_aif = new VisionAspectIniFin(vm_aif); 00259 #ifdef HAVE_WEBVIEW 00260 WebviewAspectIniFin *web_aif = new WebviewAspectIniFin(); 00261 #endif 00262 #ifdef HAVE_TF 00263 TransformAspectIniFin *tf_aif = new TransformAspectIniFin(blackboard); 00264 #endif 00265 #ifdef HAVE_PCL 00266 PointCloudAspectIniFin *pcl_aif = new PointCloudAspectIniFin(); 00267 #endif 00268 00269 00270 __default_inifins[prov_aif->get_aspect_name()] = prov_aif; 00271 __default_inifins[bb_aif->get_aspect_name()] = bb_aif; 00272 __default_inifins[bt_aif->get_aspect_name()] = bt_aif; 00273 __default_inifins[clock_aif->get_aspect_name()] = clock_aif; 00274 __default_inifins[conf_aif->get_aspect_name()] = conf_aif; 00275 __default_inifins[fnet_aif->get_aspect_name()] = fnet_aif; 00276 __default_inifins[logger_aif->get_aspect_name()] = logger_aif; 00277 __default_inifins[log_aif->get_aspect_name()] = log_aif; 00278 __default_inifins[mloop_aif->get_aspect_name()] = mloop_aif; 00279 __default_inifins[net_aif->get_aspect_name()] = net_aif; 00280 __default_inifins[plug_aif->get_aspect_name()] = plug_aif; 00281 __default_inifins[tp_aif->get_aspect_name()] = tp_aif; 00282 __default_inifins[ts_aif->get_aspect_name()] = ts_aif; 00283 __default_inifins[vm_aif->get_aspect_name()] = vm_aif; 00284 __default_inifins[vis_aif->get_aspect_name()] = vis_aif; 00285 #ifdef HAVE_WEBVIEW 00286 __default_inifins[web_aif->get_aspect_name()] = web_aif; 00287 #endif 00288 #ifdef HAVE_TF 00289 __default_inifins[tf_aif->get_aspect_name()] = tf_aif; 00290 #endif 00291 #ifdef HAVE_PCL 00292 __default_inifins[pcl_aif->get_aspect_name()] = pcl_aif; 00293 #endif 00294 00295 std::map<std::string, AspectIniFin *>::iterator i; 00296 for (i = __default_inifins.begin(); i != __default_inifins.end(); ++i) { 00297 __inifins[i->first] = i->second; 00298 } 00299 } 00300 00301 } // end namespace fawkes