Fawkes API  Fawkes Development Version
manager.cpp
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