SimEventOS.C

00001 /*! @file Simulations/SimEventOS.C Stab to run a simulation modules configures with an xml file */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00034 // $HeadURL: $
00035 // $Id: $
00036 //
00037 
00038 #include "Component/JobServerConfigurator.H"
00039 #include "Component/ModelManager.H"
00040 #include "Image/Image.H"
00041 #include "Image/Pixels.H"
00042 #include "Image/Point2D.H"
00043 #include "Media/SimFrameSeries.H"
00044 #include "Neuro/NeuroOpts.H"
00045 #include "Raster/Raster.H"
00046 #include "Simulation/SimEventQueueConfigurator.H"
00047 #include "Simulation/SimEventQueue.H"
00048 #include "Util/AllocAux.H"
00049 #include "Util/Pause.H"
00050 #include "Util/Types.H"
00051 #include "Util/csignals.H"
00052 #include "Util/log.H"
00053 #include "Util/sformat.H"
00054 #include "Util/StringUtil.H"
00055 #include "Util/Timer.H"
00056 #include "rutz/trace.h"
00057 
00058 #include <signal.h>
00059 #include <stdio.h>
00060 #include <sys/types.h>
00061 #include <dlfcn.h>
00062 
00063 #ifdef HAVE_LIBXML
00064 #include <libxml/parser.h>
00065 #include <libxml/tree.h>
00066 #endif
00067 
00068 typedef int mainLoopFunc(const int argc, const char** argv);
00069 
00070 mainLoopFunc* loadObject(ModelManager& manager,
00071  const std::string& libFile,
00072  const std::string& name, 
00073  const std::string& mainOverrideName = "")
00074 {
00075         void* libPtr = dlopen(libFile.c_str(), RTLD_NOW  | RTLD_GLOBAL);
00076         if (!libPtr)
00077                 LFATAL("Can not load library: %s (%s)", libFile.c_str(), dlerror());
00078 
00079   std::string modInstFuncName = "createModule" + name;
00080         dlerror(); //reset any errors
00081         createSimEventModule* createObj = (createSimEventModule*) dlsym(libPtr, modInstFuncName.c_str());
00082 
00083         if (!createObj)
00084                 LFATAL("Can not find the %s symbol: %s. \nCheck the module Name", modInstFuncName.c_str(), dlerror());
00085 
00086   mainLoopFunc* mainLoop = NULL;
00087   if(mainOverrideName != "")
00088   {
00089     dlerror(); //reset any errors
00090      mainLoop = (mainLoopFunc*) dlsym(libPtr, mainOverrideName.c_str());
00091      if(!mainLoop)
00092        LFATAL("Can not find mainLoop symbol (%s): %s. \nCheck the module Name", mainOverrideName.c_str(), dlerror());
00093     
00094   }
00095 
00096   nub::ref<SimModule> obj = createObj(manager);
00097   manager.addSubComponent(obj);
00098 
00099   //dlclose(libPtr);
00100 
00101   return mainLoop;
00102 }
00103 
00104 void getNodeMatchText(xmlDocPtr doc, xmlNodePtr nodePtr,
00105                                   const char* nodeName, std::string &result)
00106 {
00107   xmlChar *tmp = NULL;
00108   if (!xmlStrcmp(nodePtr->name, (const xmlChar *)nodeName))
00109     tmp = xmlNodeListGetString(doc, nodePtr->xmlChildrenNode, 1);
00110 
00111   if (tmp != NULL) {
00112     result = std::string((const char*)tmp);
00113     xmlFree(tmp);
00114   }
00115 }
00116 
00117 mainLoopFunc* configModules(const char* xmlFile, ModelManager& manager,
00118  const int argc, const char **argv, bool skipFirstArgs)
00119 {
00120         std::vector<const char*> argvals;
00121 
00122   int argcnt=0;
00123 
00124   for(int i=0; i<argc; i++)
00125         {
00126                 if (skipFirstArgs && (i==1) ) continue;
00127                 argvals.push_back(argv[i]);
00128                 argcnt++;
00129         }
00130 
00131 
00132   // check if the file exists:
00133   xmlDocPtr doc = xmlReadFile(xmlFile, NULL, 0);
00134   if (doc == NULL) {
00135     LFATAL("Failed to parse %s", xmlFile);
00136   }
00137 
00138   /* Get the root element node */
00139   xmlNode *root_element = xmlDocGetRootElement(doc);
00140 
00141   // look for object annotations
00142   xmlNodePtr cur = root_element; //->xmlChildrenNode; //dont care about top level
00143 
00144   //Skip the top level if scenes is in the name
00145   if ((!xmlStrcmp(cur->name, (const xmlChar *)"SimModules")))
00146     cur = root_element->xmlChildrenNode; //dont care about top level
00147         
00148   mainLoopFunc* mainLoop = NULL;
00149 
00150         while (cur != NULL) {
00151                 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Module"))) {
00152                         // get the  scene data:
00153                         xmlNodePtr modulePtr = cur->xmlChildrenNode;
00154 
00155                         std::string name, location, mainLoopFuncName;
00156 
00157       while(modulePtr != NULL) { // read the attributes and polygons
00158         getNodeMatchText(doc, modulePtr, "Name", name);
00159         getNodeMatchText(doc, modulePtr, "Location", location);
00160         getNodeMatchText(doc, modulePtr, "MainLoop", mainLoopFuncName);
00161 
00162         //Process the args
00163         if ((!xmlStrcmp(modulePtr->name, (const xmlChar *)"Args"))) {
00164           xmlNodePtr argPtr = modulePtr->xmlChildrenNode;
00165 
00166           while(argPtr != NULL)
00167           {
00168 
00169             if ((!xmlStrcmp(argPtr->name, (const xmlChar *)"arg"))) {
00170               xmlChar* name = xmlGetProp(argPtr, (const xmlChar*)"name");
00171               xmlChar* value = xmlGetProp(argPtr, (const xmlChar*)"value");
00172 
00173               std::string arg = "--" + std::string((const char*)name) +
00174                                 "=" + std::string((const char*)value);
00175               argvals.push_back(strdup(arg.c_str()));
00176               argcnt++;
00177 
00178               xmlFree(name);
00179               xmlFree(value);
00180             }
00181             argPtr = argPtr->next;
00182           }
00183           
00184         }
00185         
00186                                 modulePtr = modulePtr->next;
00187                         }
00188 
00189                         mainLoopFunc* tmpMainLoop = loadObject(manager, location, name, mainLoopFuncName);
00190       if(tmpMainLoop)
00191       {
00192         if(!mainLoop)
00193           mainLoop = tmpMainLoop;
00194         else
00195           LFATAL("ERROR! Two Main Loops Defined In XML!");
00196       }
00197 
00198                 }
00199                 cur = cur->next;
00200         }
00201   xmlFreeDoc(doc);
00202   xmlCleanupParser();
00203 
00204         if (manager.parseCommandLine(
00205                                 (const int)argcnt, &argvals[0], "", 0, 0) == false)
00206     LFATAL("Bad Arguments!");
00207 
00208   return mainLoop;
00209 }
00210 
00211 volatile int signum = 0;
00212 
00213 void* RunSimOS(void* seq_p)
00214 {
00215   nub::ref<SimEventQueue> seq = *((nub::ref<SimEventQueue>*)seq_p);
00216 
00217   PauseWaiter p;
00218   SimStatus status = SIM_CONTINUE;
00219 
00220   Timer timer;
00221         //main loop:
00222   while(status == SIM_CONTINUE)
00223   {
00224     // Are we in pause mode, if so, hold execution:
00225     if (p.checkPause()) continue;
00226 
00227     if (signum != 0) {
00228       char msg[255];
00229       snprintf(msg, 255, "quitting because %s was caught", signame(signum));
00230       LINFO("%s", msg);
00231       seq->post(rutz::make_shared(new SimEventBreak(seq.get(), msg)));
00232       status = seq->evolve();
00233       break;
00234     }
00235     // Evolve for one time step and switch to the next one:
00236     status = seq->evolve();
00237   }
00238   pthread_exit(NULL);
00239 }
00240 
00241 int main(const int argc, const char **argv)
00242 {
00243   // 'volatile' because we will modify this from signal handlers
00244 
00245   // catch signals and redirect them for a clean exit (in particular,
00246   // this gives us a chance to do useful things like flush and close
00247   // output files that would otherwise be left in a bogus state, like
00248   // mpeg output files):
00249   catchsignals(&signum);
00250 
00251   MYLOGVERB = LOG_INFO;
00252   ModelManager manager("SimEvent Kernel");
00253 
00254   nub::ref<SimEventQueueConfigurator>
00255     seqc(new SimEventQueueConfigurator(manager));
00256   manager.addSubComponent(seqc);
00257 
00258   // Request a bunch of option aliases (shortcuts to lists of options):
00259   REQUEST_OPTIONALIAS_NEURO(manager);
00260 
00261   std::string xmlFile = std::string(getenv("HOME")) + "/.SimEventOS.xml";
00262 
00263   mainLoopFunc* mainLoop = NULL;
00264         if (argc > 1)
00265         {
00266                         if (argv[1][0] != '-') //This is an xml file, use it
00267                                         mainLoop = configModules(argv[1], manager, argc, argv, true);
00268                   else
00269                                         mainLoop = configModules(xmlFile.c_str(), manager, argc, argv, false);
00270         } else {
00271                         mainLoop = configModules(xmlFile.c_str(), manager, argc, argv, false);
00272         }
00273 
00274   nub::ref<SimEventQueue> seq = seqc->getQ();
00275 
00276   manager.start();
00277 
00278   // temporary, for debugging...
00279   seq->printCallbacks();
00280 
00281 
00282   //Start up our SimEventOS runtime thread
00283   pthread_t SimOSThread;
00284   int rc = pthread_create(&SimOSThread, NULL, RunSimOS, (void*)(&seq));
00285 
00286   //Execute an overridden mainloop if it exists
00287   if(mainLoop)
00288     rc = mainLoop(argc, argv);
00289 
00290   //Wait for the SimOSThread loop to finish
00291   void* status;
00292   rc = pthread_join(SimOSThread, &status);
00293     
00294   // print final memory allocation stats
00295   LINFO("Simulation terminated.");
00296 
00297   // stop all our ModelComponents
00298   manager.stop();
00299 
00300   return rc;
00301 }
Generated on Sun May 8 08:06:50 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3