uobject.cc

Go to the documentation of this file.
00001 
00021 #include <iostream>
00022 #include <sstream>
00023 #include <list>
00024 
00025 #include "urbi/uobject.hh"
00026 
00027 #include "urbi/usyncclient.hh"
00028 #include "urbi/uexternal.hh"
00029 
00030 //#define LIBURBIDEBUG
00031 
00033 namespace urbi
00034 {
00035   UObject* dummyUObject;
00036 
00037   STATIC_INSTANCE(UStartlist, objectlist);
00038   STATIC_INSTANCE(UStartlistHub, objecthublist);
00039 
00040   UVarTable varmap;
00041   UTable functionmap;
00042   UTable monitormap;
00043   UTable accessmap;
00044   UTable eventmap;
00045   UTable eventendmap;
00046 
00047   UTimerTable timermap;
00048   UTimerTable updatemap;
00049 
00050   UCallbackAction dispatcher(const UMessage& msg);
00051   UCallbackAction debug(const UMessage& msg);
00052 
00053 
00054   UVar& cast(UValue& v, UVar*)
00055   {
00056     return (*((UVar*)v.storage));
00057   };
00058 
00059 
00060   UBinary cast(UValue& v, UBinary*)
00061   {
00062     if (v.type != DATA_BINARY)
00063       return UBinary();
00064     return UBinary(*v.binary);
00065   }
00066 
00067 
00068   UList cast(UValue& v, UList*)
00069   {
00070     if (v.type != DATA_LIST)
00071       return UList();
00072     return UList(*v.list);
00073   }
00074 
00075   UObjectStruct cast(UValue& v, UObjectStruct*)
00076   {
00077     if (v.type != DATA_OBJECT)
00078       return UObjectStruct();
00079     return UObjectStruct(*v.object);
00080   }
00081 
00082   const char* cast(UValue &v, const char**)
00083   {
00084     static const char* er = "invalid";
00085     if (v.type != DATA_STRING)
00086       return er;
00087     return v.stringValue->c_str();
00088   }
00089 
00090   std::ostream& unarmorAndSend(const char* a);
00091 
00092   void uobject_unarmorAndSend(const char* a)
00093   {
00094     unarmorAndSend(a);
00095   }
00096 
00097   void send(const char* a)
00098   {
00099     std::ostream& s = getDefaultClient() == 0 ? std::cerr
00100       : ((UAbstractClient*)getDefaultClient())->getStream();
00101     s << a;
00102   }
00103 
00104   void send(void* buf, int size)
00105   {
00106     std::ostream& s = getDefaultClient() == 0 ? std::cerr
00107       : ((UAbstractClient*)getDefaultClient())->getStream();
00108     s.rdbuf()->sputn(static_cast<char*> (buf), size);
00109   }
00110 
00111 
00112   // **************************************************************************
00114   UGenericCallback::UGenericCallback(const std::string& objname,
00115                                      const std::string& type,
00116                                      const std::string& name,
00117                                      int size,  UTable& t)
00118     : objname (objname), name (name)
00119   {
00120     nbparam = size;
00121 
00122     if (type == "function" || type== "event" || type == "eventend")
00123       {
00124         std::ostringstream oss;
00125         oss << size;
00126         this->name = this->name + "__" + oss.str();
00127       }
00128     t[this->name].push_back(this);
00129 
00130     std::cout << "Registering " << type << " " << name << " " << size
00131               << " into " << this->name
00132               << " from " << objname
00133               << std::endl;
00134 
00135     if (type == "var")
00136       URBI(()) << "external " << type << " "
00137                << name << " from " << objname << ";";
00138 
00139     if (type == "event" || type == "function")
00140       URBI(()) << "external " << type << "(" << size << ") "
00141                << name << " from " << objname << ";";
00142 
00143     if (type == "varaccess")
00144       echo("Warning: NotifyAccess facility is not available for modules in "
00145            "remote mode.\n");
00146   };
00147 
00149   UGenericCallback::UGenericCallback(const std::string& objname,
00150                                      const std::string& type,
00151                                      const std::string& name, UTable& t)
00152     : objname(objname), name(name)
00153   {
00154     t[this->name].push_back(this);
00155     URBI(()) << "external " << type << " " << name << ";";
00156   };
00157 
00158   UGenericCallback::~UGenericCallback()
00159   {
00160   };
00161 
00162 
00163   // **************************************************************************
00165 
00166   UTimerCallback::UTimerCallback(const std::string& objname,
00167                                  ufloat period, UTimerTable& tt)
00168     : period(period),
00169       objname(objname)
00170   {
00171     tt.push_back(this);
00172     lastTimeCalled = -9999999;
00173     std::ostringstream os;
00174     os << "timer"<<tt.size();
00175     //register oursselves as an event
00176     std::string cbname = os.str();
00177 
00178     // needed by MSVC
00179     //createUCallback(objname, "event", this, &UTimerCallback::call, objname +
00180     //                "." + cbname, eventmap);
00181     new UCallbackvoid0<UTimerCallback> (objname, "event", this,
00182                                         &UTimerCallback::call,
00183                                         objname + '.' + cbname, eventmap);
00184 
00185     os.str("");
00186     os.clear();
00187     os << "timer_" << objname << ": every(" << period << ") { emit "
00188        << (objname + '.' + cbname) << ";};";
00189     URBI(()) << os.str();
00190   }
00191 
00192   UTimerCallback::~UTimerCallback()
00193   {
00194   }
00195 
00196   // **************************************************************************
00197   //  Monitoring functions
00198 
00200   void
00201   UObject::USync(UVar&)
00202   {
00203     //UNotifyChange(v, &UObject::voidfun);
00204   }
00205 
00206   // **************************************************************************
00208   UObject::UObject(const std::string& s)
00209     : __name(s),
00210       classname(s),
00211       derived(false),
00212       remote (true),
00213       load(s, "load")
00214   {
00215     objecthub = 0;
00216     autogroup = false;
00217 
00218     URBI(()) << "class " << __name << "{};";
00219     URBI(()) << "external object " << __name << ";";
00220     period = -1;
00221 
00222     // default
00223     load = 1;
00224   }
00225 
00227   UObject::UObject(int index)
00228     : derived(false),
00229       remote (true)
00230   {
00231     std::stringstream ss;
00232     ss << "dummy" << index;
00233     __name = ss.str();
00234     classname = __name;
00235     objecthub = 0;
00236     autogroup = false;
00237     period = -1;
00238   }
00239 
00240 
00243   namespace
00244   {
00245     void
00246     cleanTable(UTable& t, const std::string& name)
00247     {
00248       std::list<UTable::iterator> todelete;
00249       for (UTable::iterator it = t.begin();
00250            it != t.end();
00251            ++it)
00252         {
00253           std::list<UGenericCallback*>& tocheck = (*it).second;
00254           for (std::list<UGenericCallback*>::iterator it2 = tocheck.begin();
00255                it2 != tocheck.end();
00256                )
00257             {
00258               if ((*it2)->objname == name)
00259                 {
00260                   delete *it2;
00261                   it2 = tocheck.erase(it2);
00262                 }
00263               else
00264                 ++it2;
00265             }
00266 
00267           if (tocheck.empty())
00268             todelete.push_back(it);
00269         }
00270 
00271       for (std::list<UTable::iterator>::iterator dit = todelete.begin();
00272            dit != todelete.end();
00273            ++dit)
00274         t.erase(*dit);
00275     }
00276   }
00277 
00279   void
00280   UObject::clean()
00281   {
00282     cleanTable(monitormap, __name);
00283     cleanTable(accessmap, __name);
00284     cleanTable(functionmap, __name);
00285     cleanTable(eventmap, __name);
00286     cleanTable(eventendmap, __name);
00287 
00288     if (objecthub)
00289       objecthub->members.remove(this);
00290   }
00291 
00292 
00294   UObject::~UObject()
00295   {
00296     clean();
00297   }
00298 
00299   void
00300   UObject::UJoinGroup(const std::string& gpname)
00301   {
00302     std::string groupregister = "addgroup " + gpname +" { "+__name+"};";
00303     uobject_unarmorAndSend(groupregister.c_str());
00304   }
00305 
00306   void
00307   UObject::USetUpdate(ufloat t)
00308   {
00309     std::ostringstream os;
00310     if (period != -1)
00311       {
00312         //kill previous timer
00313         os << "stop maintimer_" << __name << ";";
00314         URBI(())<<os.str();
00315       }
00316     period = t;
00317     if (period <= 0)
00318       period = 1;
00319     std::string cbname = __name + ".maintimer";
00320     createUCallback(__name, "event",
00321                     this, &UObject::update, cbname, eventmap);
00322     os.str("");
00323     os.clear();
00324     os << "maintimer_" << __name << ": every(" << period << ") "
00325     "{ emit "<<cbname<<";};";
00326     URBI(()) << os.str();
00327   }
00328 
00329   // This part is specific for standalone linux objects
00330   // LIBURBI 'Module mode'
00331 
00332   UCallbackAction
00333   dispatcher(const UMessage& msg)
00334   {
00335     //check message type
00336     if (msg.type != MESSAGE_DATA || msg.value->type != DATA_LIST)
00337       {
00338         msg.client.printf("Component Error: "
00339                           "unknown message content, type %d\n",
00340                           (int) msg.type);
00341         return URBI_CONTINUE;
00342       }
00343 
00344     UList& array = *msg.value->list;
00345 
00346     if (array.size()<2)
00347       {
00348         msg.client.printf("Component Error: Invalid number "
00349                           "of arguments in the server message: %d\n",
00350                           array.size());
00351         return URBI_CONTINUE;
00352       }
00353 
00354     if (array[0].type != DATA_DOUBLE)
00355       {
00356         msg.client.printf("Component Error: "
00357                           "unknown server message type %d\n",
00358                           (int) array[0].type);
00359         return URBI_CONTINUE;
00360       }
00361 
00362     // UEM_ASSIGNVALUE
00363     if ((USystemExternalMessage)(int)array[0] == UEM_ASSIGNVALUE)
00364       {
00365         UVarTable::iterator varmapfind = varmap.find(array[1]);
00366         if (varmapfind != varmap.end())
00367           for (std::list<UVar*>::iterator it = varmapfind->second.begin();
00368                it != varmapfind->second.end();
00369                ++it)
00370             (*it)->__update(array[2]);
00371 
00372         UTable::iterator monitormapfind = monitormap.find(array[1]);
00373         for (std::list<UGenericCallback*>::iterator
00374              cbit = monitormapfind->second.begin();
00375              cbit != monitormapfind->second.end();
00376              ++cbit)
00377         {
00378           // test of return value here
00379           UList u;
00380           u.array.push_back(new UValue());
00381           u[0].storage = (*cbit)->storage;
00382           (*cbit)->__evalcall(u);
00383         }
00384       }
00385 
00386     // UEM_EVALFUNCTION
00387     else if ((USystemExternalMessage)(int)array[0] == UEM_EVALFUNCTION)
00388       {
00389         /* For the moment, this iteration is useless since the list will
00390          * contain one and only one element. There is no function overloading
00391          * yet and still it would probably use a unique name identifier, hence
00392          * a single element list again. */
00393         if (functionmap.find(array[1]) != functionmap.end())
00394           {
00395             std::list<UGenericCallback*> tmpfun = functionmap[array[1]];
00396             std::list<UGenericCallback*>::iterator tmpfunit = tmpfun.begin();
00397             array.setOffset(3);
00398             UValue retval = (*tmpfunit)->__evalcall(array);
00399             array.setOffset(0);
00400             if (retval.type == DATA_VOID)
00401               URBI(()) << "var " << (std::string) array[2];
00402             else
00403               {
00404                 URBI(()) << (std::string) array[2] << "=";
00405                 getDefaultClient()->send(retval);//I'd rather not use << for bins
00406               }
00407             URBI(()) << ";";
00408           }
00409         else
00410           msg.client.printf("Component Error: %s function unknown.\n",
00411                             ((std::string) array[1]).c_str());
00412       }
00413 
00414     // UEM_EMITEVENT
00415     else if ((USystemExternalMessage)(int)array[0] == UEM_EMITEVENT)
00416       {
00417         if (eventmap.find(array[1]) != eventmap.end())
00418           {
00419             std::list<UGenericCallback*>  tmpfun = eventmap[array[1]];
00420             for (std::list<UGenericCallback*>::iterator tmpfunit = tmpfun.begin();
00421                  tmpfunit != tmpfun.end();
00422                  ++tmpfunit)
00423               {
00424                 array.setOffset(2);
00425                 (*tmpfunit)->__evalcall(array);
00426                 array.setOffset(0);
00427               }
00428           }
00429       }
00430 
00431     // UEM_ENDEVENT
00432     else if ((USystemExternalMessage)(int)array[0] == UEM_ENDEVENT)
00433       {
00434         if (eventendmap.find(array[1]) != eventendmap.end())
00435           {
00436             std::list<UGenericCallback*>  tmpfun = eventendmap[array[1]];
00437             for (std::list<UGenericCallback*>::iterator tmpfunit = tmpfun.begin();
00438                  tmpfunit != tmpfun.end();
00439                  ++tmpfunit)
00440               {
00441                 array.setOffset(2);
00442                 (*tmpfunit)->__evalcall(array);
00443                 array.setOffset(0);
00444               }
00445           }
00446       }
00447 
00448     // UEM_NEW
00449     else if ((USystemExternalMessage)(int)array[0] == UEM_NEW)
00450       {
00451         std::list<baseURBIStarter*>::iterator found = objectlist->end();
00452         for (std::list<baseURBIStarter*>::iterator retr = objectlist->begin();
00453              retr != objectlist->end();
00454              ++retr)
00455           if ((*retr)->name == (std::string)array[2])
00456             if (found != objectlist->end())
00457               msg.client.printf("Double object definition %s\n",
00458                                 (*retr)->name.c_str());
00459             else
00460               found = retr;
00461 
00462         if (found == objectlist->end())
00463           msg.client.printf("Unknown object definition %s\n",
00464                             ((std::string) array[2]).c_str());
00465         else
00466           (*found)->copy((std::string) array[1]);
00467 
00468       }
00469 
00470     // UEM_DELETE
00471     else if ((USystemExternalMessage)(int)array[0] == UEM_DELETE)
00472       {
00473         std::list<baseURBIStarter*>::iterator found = objectlist->end();
00474         for (std::list<baseURBIStarter*>::iterator retr = objectlist->begin();
00475              retr != objectlist->end();
00476              ++retr)
00477           if ((*retr)->name == (std::string)array[1])
00478             if (found != objectlist->end())
00479               msg.client.printf("Double object definition %s\n",
00480                                 (*retr)->name.c_str());
00481             else
00482               found = retr;
00483 
00484         if (found == objectlist->end())
00485           msg.client.printf("Unknown object definition %s\n",
00486                             ((std::string) array[1]).c_str());
00487         else
00488           {
00489             // remove the object from objectlist or terminate
00490             // the component if there is nothing left
00491             if (objectlist->size() == 1)
00492               exit(0);
00493             else
00494               {
00495                 // delete the object
00496                 delete (*found);
00497               }
00498           }
00499       }
00500 
00501 
00502     // DEFAULT
00503     else
00504       msg.client.printf("Component Error: "
00505                         "unknown server message type number %d\n",
00506                         (int)array[0]);
00507 
00508     return URBI_CONTINUE;
00509   }
00510 
00511 
00512 
00513 
00514   // **************************************************************************
00516   UObjectHub::UObjectHub(const std::string& s) : name(s)
00517   {
00518   }
00519 
00521   UObjectHub::~UObjectHub()
00522   {
00523   }
00524 
00525   void
00526   UObjectHub::USetUpdate(ufloat t)
00527   {
00528     period = t;
00529     // nothing happend in remote mode...
00530   }
00531 
00532   int
00533   UObjectHub::updateGlobal()
00534   {
00535     for (UObjectList::iterator it = members.begin();
00536          it != members.end();
00537          ++it)
00538       (*it)->update();
00539     update();
00540     return 0;
00541   }
00542 
00543   void
00544   UObjectHub::addMember(UObject* obj)
00545   {
00546     members.push_back(obj);
00547   }
00548 
00549   UObjectList*
00550   UObjectHub::getSubClass(const std::string& subclass)
00551   {
00552     UObjectList* res = new UObjectList();
00553     for (UObjectList::iterator it = members.begin();
00554          it != members.end();
00555          ++it)
00556       if ((*it)->classname == subclass)
00557         res->push_back(*it);
00558 
00559     return res;
00560   }
00561 
00562 
00564   UObjectHub*
00565   getUObjectHub(const std::string& name)
00566   {
00567     for (UStartlistHub::iterator retr = objecthublist->begin();
00568          retr != objecthublist->end();
00569          ++retr)
00570       if ((*retr)->name == name)
00571         return (*retr)->getUObjectHub();
00572 
00573     return 0;
00574   }
00575 
00577   UObject*
00578   getUObject(const std::string& name)
00579   {
00580     for (UStartlist::iterator retr = objectlist->begin();
00581          retr != objectlist->end();
00582          ++retr)
00583       if ((*retr)->name == name)
00584         return (*retr)->getUObject();
00585 
00586     return 0;
00587   }
00588 
00590   void
00591   echo(const char* format, ...)
00592   {
00593     va_list arg;
00594     va_start(arg, format);
00595     vfprintf(stderr, format, arg);
00596     va_end(arg);
00597   }
00598 
00599 
00600 
00601   // **************************************************************************
00602   // Other functions
00603 
00604   UCallbackAction
00605   debug(const UMessage& msg)
00606   {
00607     std::stringstream mesg;
00608     mesg<<msg;
00609     msg.client.printf("DEBUG: got a message  : %s\n",
00610                       mesg.str().c_str());
00611 
00612     return URBI_CONTINUE;
00613   }
00614 
00615 
00616   void
00617   main(int argc, char* argv[])
00618   {
00619     // Retrieving command line arguments
00620     if (argc!=2)
00621       {
00622         std::cout << "usage:\n"
00623                   << argv[0] << " <URBI Server IP>" << std::endl;
00624         exit(0);
00625       }
00626 
00627     //serverIP = argv[1];
00628     std::cout << "Running Remote Component '" << argv[0]
00629               << "' on " << argv[1] << std::endl;
00630     //we need a usyncclient connect(argv[1]);
00631     new USyncClient(argv[1]);
00632 
00633 
00634 #ifdef LIBURBIDEBUG
00635     getDefaultClient()->setWildcardCallback( callback (&debug));
00636 #else
00637     getDefaultClient()->setErrorCallback( callback (&debug));
00638 #endif
00639 
00640     getDefaultClient()->setCallback(&dispatcher,
00641                                     externalModuleTag.c_str());
00642 
00643     dummyUObject = new UObject (0);
00644     for (UStartlist::iterator retr = objectlist->begin();
00645          retr != objectlist->end();
00646          ++retr)
00647       (*retr)->init((*retr)->name);
00648   }
00649 
00650 } // namespace urbi

Generated on Tue Apr 10 17:45:44 2007 for URBISDK by  doxygen 1.5.1