Urbi SDK Remote for C++  2.7.5
all.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2011, Gostai S.A.S.
00003  *
00004  * This software is provided "as is" without warranty of any kind,
00005  * either expressed or implied, including but not limited to the
00006  * implied warranties of fitness for a particular purpose.
00007  *
00008  * See the LICENSE file for more information.
00009  */
00010 
00011 #include <iostream>
00012 #include <libport/cmath>
00013 #include <libport/compiler.hh>
00014 #include <libport/containers.hh>
00015 #include <libport/debug.hh>
00016 #include <libport/ufloat.hh>
00017 #include <libport/unistd.h>
00018 #include <sstream>
00019 #include <stdexcept>
00020 
00021 #include <urbi/uclient.hh>
00022 #undef URBI
00023 #include <urbi/uobject.hh>
00024 #include <urbi/input-port.hh>
00025 
00026 GD_CATEGORY(Test.All);
00027 
00029 static void*
00030 memdup(const void *data, size_t size)
00031 {
00032   return memcpy(malloc(size), data, size);
00033 }
00034 
00035 struct Point
00036 {
00037   Point()
00038     : x(0)
00039     , y(0)
00040   {}
00041   ufloat x,y;
00042 };
00043 
00044 struct Rect
00045 {
00046   Point a;
00047   Point b;
00048 };
00049 
00050 struct PointOfInterest
00051 {
00052   std::string sectorName;
00053   std::vector<Rect> subSectors;
00054   boost::unordered_map<std::string, Rect> byName;
00055 };
00056 
00057 URBI_REGISTER_STRUCT(Point, x, y);
00058 URBI_REGISTER_STRUCT(Rect, a, b);
00059 URBI_REGISTER_STRUCT(PointOfInterest, sectorName, subSectors, byName);
00060 
00061 
00062 class all: public urbi::UObject
00063 {
00064 public:
00065   typedef urbi::UObject super_type;
00066   pthread_t mainthread;
00067 
00068   inline void threadCheck() const
00069   {
00070     aver(mainthread == pthread_self());
00071   }
00072 
00073   all()
00074   {
00075     GD_INFO_TRACE("all default ctor");
00076     count = 0;
00077     mainthread = pthread_self();
00078     setup();
00079     init(1);
00080   }
00081 
00082   all(const std::string& name)
00083     : urbi::UObject(name)
00084   {
00085     GD_INFO_TRACE("all string ctor");
00086     count = 0;
00087     mainthread = pthread_self();
00088     if (getenv("CTOR_EXCEPTION") &&
00089         !strcmp(getenv("CTOR_EXCEPTION"), "true"))
00090       throw std::runtime_error("constructor failure");
00091     setup();
00092   }
00093 
00094   void setup()
00095   {
00096     UBindFunction(all, init);
00097     UBindFunction(all, setOwned);
00098     UBindFunction(all, setNotifyChange);
00099     UBindFunctions(all, multiRead, multiWrite);
00100 
00102     UBindFunction(all, setBypassNotifyChangeBinary);
00103     UBindFunction(all, setBypassNotifyChangeImage);
00104     UBindFunctions(all, markBypass, markRTP);
00105     UBindFunctions(all, selfWriteB, selfWriteI, selfWriteVD);
00106 
00107     UBindFunctions
00108       (all,
00109        setNotifyAccess, setNotifyChangeByName, setNotifyChangeByUVar,
00110        sendEvent8Args,
00111        unnotify,
00112        setThreadedNotifyChange, setThreadedNotifyChangeByUVar);
00113     UBindFunction(all, read);
00114     UBindFunction(all, write);
00115     UBindFunction(all, readByName);
00116     UBindFunction(all, readValByName);
00117     UBindFunction(all, writeByName);
00118     UBindFunction(all, writeByUVar);
00119     UBindFunction(all, writeOwnByName);
00120     UBindFunction(all, urbiWriteOwnByName);
00121     UBindFunction(all, sendString);
00122     UBindFunction(all, sendBuf);
00123     UBindFunction(all, sendPar);
00124     UBindFunction(all, typeOf);
00125     UBindFunction(all, uobjectName);
00126     UBindFunction(all, allUObjectName);
00127     UBindVar(all,a);
00128     UBindVar(all,a);
00129     UBindVars(all, b, c, d);
00130     UBindVar(all, initCalled);
00131     initCalled = 0;
00132     UBindVar(all, lastChange);
00133     UBindVar(all, lastAccess);
00134     UBindVar(all, lastChangeVal);
00135     lastChangeVal = -1;
00136     UBindVar(all, lastAccessVal);
00137     UBindVar(all, removeNotify);
00138     removeNotify = "";
00139     // Properties.
00140     UBindFunction(all, readProps);
00141     UBindFunction(all, writeProps);
00142 
00143     UBindFunction(all, writeD);
00144     UBindFunction(all, writeS);
00145     UBindFunction(all, writeL);
00146     UBindFunction(all, writeM); // M for Map
00147     UBindFunction(all, writeB);
00148     UBindFunction(all, makeCall);
00149     UBindFunction(all, writeBNone);
00150     UBindFunction(all, writeI);
00151     UBindFunction(all, writeSnd);
00152     UBindFunction(all, writeRI);
00153     UBindFunction(all, writeRSnd);
00154 
00155     UBindFunction(all, transmitD);
00156     UBindFunction(all, transmitS);
00157     UBindFunction(all, transmitL);
00158     UBindFunction(all, transmitM);
00159     UBindFunction(all, transmitB);
00160     UBindFunction(all, transmitI);
00161     UBindFunction(all, transmitSnd);
00162     UBindFunction(all, transmitO);
00163 
00164     UBindFunction(all, loop_yield);
00165     UBindFunction(urbi::UContext, side_effect_free_get);
00166     UBindFunction(urbi::UContext, side_effect_free_set);
00167     UBindFunction(urbi::UContext, yield);
00168     UBindFunction(urbi::UContext, yield_for);
00169     UBindFunction(urbi::UContext, yield_until_things_changed);
00170 
00171     UBindFunction(all, getDestructionCount);
00172 
00173     UBindFunction(all, invalidRead);
00174     UBindFunction(all, invalidWrite);
00175 
00176     UBindEvent(all, ev);
00177     UBindFunction(all, sendEvent);
00178     UBindFunction(all, sendEvent2Args);
00179     UBindFunction(all, sendNamedEvent);
00180 
00181     UBindFunction(all, throwException);
00182     UBindFunction(all, socketStats);
00183     UBindFunction(all, instanciate);
00184     UBindFunctions(all, area, translate, makeRect, multiTranslate,
00185                    transmitPointOfInterest, writePointOfInterest,
00186                    readPointOfInterest);
00187     UBindFunctionRename(all, area, "rectArea");
00188     UBindFunctions(all, pack, unpack);
00189     UBindVars(all, periodicWriteTarget, periodicWriteType, periodicWriteRate,
00190               periodicWriteCount, changeCount);
00191     periodicWriteCount = 1;
00192     UNotifyChange(periodicWriteRate, &all::onRateChange);
00193     vars[0] = &a;
00194     vars[1] = &b;
00195     vars[2] = &c;
00196     vars[3] = &d;
00197     vars[4] = &unbound;
00198     std::string name = "ia";
00199     for(int i=0; i<4; ++i)
00200     {
00201       name[1] = 'a' + i;
00202       ports[i] = new urbi::InputPort(this, name);
00203     }
00204     // 4 is unbound
00205     ports[4] = new urbi::InputPort();
00206     UBindFunctions(all, notifyWriteA, writeAD, writeAS, writeAB, writeAV,
00207                    manyWriteTest);
00208     UAt(all, boundev);
00209   }
00210 
00211   ~all()
00212   {
00213     ++destructionCount;
00214   }
00215 
00216   void multiWrite(int idx, int count, ufloat val)
00217   {
00218     for (int i=0; i<count; ++i)
00219       (*vars[idx]) = val+idx;
00220   }
00221 
00222   void multiRead(int idx, int count)
00223   {
00224     ufloat sum = 0;
00225     for (int i=0; i<count; ++i)
00226       sum += (ufloat)*vars[idx];
00227   }
00228 
00229   void boundev(ufloat v)
00230   {
00231     lastChange = "boundev";
00232     lastChangeVal = v;
00233   }
00234 
00235   void onRateChange(urbi::UVar&)
00236   {
00237     USetUpdate((ufloat)periodicWriteRate * 1000.0);
00238   }
00239 
00240   UObject* instanciate() const
00241   {
00242     return new all;
00243   }
00244 
00245   virtual int update()
00246   {
00247     int target = periodicWriteTarget;
00248     int type = periodicWriteType;
00249     GD_FINFO_DEBUG("update: type = %s, target = %s", type, target);
00250     for (int i=0; i<(int)periodicWriteCount; ++i)
00251     switch (type)
00252     {
00253     case urbi::DATA_STRING:
00254       *vars[target] = string_cast(libport::utime());
00255       break;
00256     case urbi::DATA_BINARY:
00257       selfWriteB(target, string_cast(libport::utime()));
00258       break;
00259     case urbi::DATA_DOUBLE:
00260     default:
00261       *vars[target] = libport::utime();
00262       break;
00263     }
00264     return 0;
00265   }
00266 
00267   int setBypassNotifyChangeBinary(const std::string& name)
00268   {
00269     threadCheck();
00270     UNotifyChange(name, &all::onBinaryBypass);
00271     return 0;
00272   }
00273 
00274   int setBypassNotifyChangeImage(const std::string& name)
00275   {
00276     threadCheck();
00277     UNotifyChange(name, &all::onImageBypass);
00278     return 0;
00279   }
00280 
00281   int markBypass(int id, bool state)
00282   {
00283     threadCheck();
00284     return vars[id]->setBypass(state);
00285   }
00286 
00287   int markRTP(int id, bool state)
00288   {
00289     vars[id]->useRTP(state);
00290     return 0;
00291   }
00292 
00293   void unnotify(int id)
00294   {
00295     if (id < 5)
00296       vars[id]->unnotify();
00297     else
00298       ports[id - 5]->unnotify();
00299   }
00300 
00301   int onBinaryBypass(urbi::UVar& var)
00302   {
00303     threadCheck();
00304     const urbi::UBinary& cb = var;
00305     GD_FINFO_DEBUG("onbin cptr %s", cb.common.data);
00306     urbi::UBinary& b = const_cast<urbi::UBinary&>(cb);
00307     for (unsigned int i=0; i<b.common.size; ++i)
00308       ((char*)b.common.data)[i]++;
00309     return 0;
00310   }
00311 
00312   void onImageBypass(urbi::UVar& var)
00313   {
00314     threadCheck();
00315     const urbi::UImage& cb = var;
00316     GD_FINFO_DEBUG("onimg cptr %s", (void*)cb.data);
00317     urbi::UImage& b = const_cast<urbi::UImage&>(cb);
00318     for (unsigned int i=0; i<b.size; ++i)
00319       b.data[i]++;
00320   }
00321 
00322   std::string selfWriteB(int idx, const std::string& content)
00323   {
00324     threadCheck();
00325     urbi::UBinary b;
00326     b.type = urbi::BINARY_UNKNOWN;
00327     // Dup since we want to test no-copy op: the other end will write.
00328     b.common.data = memdup(content.c_str(), content.size());
00329     b.common.size = content.size();
00330     GD_FINFO_DEBUG("writeB cptr %s", b.common.data);
00331     *vars[idx] = b;
00332     std::string res((char*)b.common.data, b.common.size);
00333     free(b.common.data);
00334     b.common.data = 0;
00335     return res;
00336   }
00337 
00338   std::string selfWriteI(int idx, const std::string& content)
00339   {
00340     threadCheck();
00341     urbi::UImage i;
00342     i.init();
00343     i.data = (unsigned char*)memdup(content.c_str(), content.size());
00344     i.size = content.length();
00345     GD_FINFO_DEBUG("writeI cptr %s", (void*)i.data);
00346     *vars[idx] = i;
00347     std::string res((char*)i.data, i.size);
00348     free(i.data);
00349     return res;
00350   }
00351 
00352   int writeOwnByName(const std::string& name, int val)
00353   {
00354     threadCheck();
00355     urbi::UVar v(__name + "." + name);
00356     v = val;
00357     return 0;
00358   }
00359 
00360   int urbiWriteOwnByName(const std::string& name, int val)
00361   {
00362     threadCheck();
00363     std::stringstream ss;
00364     ss << __name << "." << name << " = " << val << ";";
00365     send(ss.str());
00366     return 0;
00367   }
00368 
00369   void selfWriteVD(int i, std::vector<ufloat> v)
00370   {
00371     *vars[i] = v;
00372   }
00373 
00374   std::string typeOf(const std::string& name)
00375   {
00376     threadCheck();
00377     urbi::UVar v(name);
00378     v.syncValue();
00379     return v.val().format_string();
00380   }
00381 
00382   int init(int fail)
00383   {
00384     threadCheck();
00385     initCalled = 1;
00386     if (fail > 1)
00387       throw std::runtime_error("KABOOOM");
00388     return fail;
00389   }
00390 
00391   int setOwned(int id)
00392   {
00393     threadCheck();
00394     UOwned(*vars[id]);
00395     return 0;
00396   }
00397 
00398   int setNotifyChange(int id)
00399   {
00400     threadCheck();
00401     if (id < 5)
00402       UNotifyChange(*vars[id], &all::onChange);
00403     else
00404       UNotifyChange(*ports[id - 5], &all::onChange);
00405     return 0;
00406   }
00407 
00408   int setThreadedNotifyChange(int id)
00409   {
00410     threadCheck();
00411     if (id<5)
00412       UNotifyThreadedChange(*vars[id], &all::onThreadedChange, urbi::LOCK_FUNCTION);
00413     else
00414       UNotifyThreadedChange(*ports[id-5], &all::onThreadedChange, urbi::LOCK_FUNCTION);
00415     return 0;
00416   }
00417 
00418   int setThreadedNotifyChangeByUVar(urbi::UVar& v)
00419   {
00420     UNotifyThreadedChange(v, &all::onThreadedChange, urbi::LOCK_FUNCTION);
00421     return 0;
00422   }
00423 
00424   int setNotifyChangeByUVar(urbi::UVar& v)
00425   {
00426     threadCheck();
00427     UNotifyChange(v, &all::onChange);
00428     return 0;
00429   }
00430 
00431   int setNotifyAccess(int id)
00432   {
00433     threadCheck();
00434     UNotifyAccess(*vars[id], &all::onAccess);
00435     return 0;
00436   }
00437 
00438   int setNotifyChangeByName(const std::string& name)
00439   {
00440     threadCheck();
00441     UNotifyChange(name, &all::onChange);
00442     return 0;
00443   }
00444 
00445 
00446   int read(int id)
00447   {
00448     threadCheck();
00449     int v = *vars[id];
00450     return v;
00451   }
00452 
00453   int write(int id, int val)
00454   {
00455     threadCheck();
00456     *vars[id] = val;
00457     return val;
00458   }
00459 
00460   void invalidWrite()
00461   {
00462     threadCheck();
00463     urbi::UVar v;
00464     v = 12;
00465   }
00466 
00467   void invalidRead()
00468   {
00469     threadCheck();
00470     urbi::UVar v;
00471     int i = v;
00472     LIBPORT_USE(i);
00473   }
00474 
00475   int readByName(const std::string& name)
00476   {
00477     threadCheck();
00478     urbi::UVar v(name);
00479     return v;
00480   }
00481 
00482   urbi::UValue readValByName(const std::string& name)
00483   {
00484     urbi::UVar v(name);
00485     return v.val();
00486   }
00487   int writeByName(const std::string& name, int val)
00488   {
00489     threadCheck();
00490     urbi::UVar v(name);
00491     v = val;
00492     return val;
00493   }
00494 
00495   int writeByUVar(urbi::UVar v, urbi::UValue val)
00496   {
00497     threadCheck();
00498     v = val;
00499     return 0;
00500   }
00501 
00502   int onThreadedChange(urbi::UValue v)
00503   {
00504     lastChange = "<unknown>";
00505     changeCount = ++count;
00506     lastChangeVal = v;
00507     return 0;
00508   }
00509 
00510   int onChange(urbi::UVar& v)
00511   {
00512     GD_INFO_DUMP("entering onChange");
00513     lastChange = v.get_name();
00514     changeCount = ++count;
00515     if (v.type() == urbi::DATA_DOUBLE)
00516     {
00517       GD_FINFO_DUMP("onChange double %s", v.get_name());
00518       int val = v;
00519       lastChangeVal = val;
00520     }
00521     else if (v.type() == urbi::DATA_BINARY)
00522     {
00523       GD_FINFO_DUMP("onChange binary %s", v.get_name());
00524       urbi::UBinary b = v;
00525       lastChangeVal = b;
00526     }
00527     else
00528       GD_FINFO_DUMP("onChange unknown %s", v.get_name());
00529     if (removeNotify == v.get_name())
00530     {
00531       v.unnotify();
00532       removeNotify = "";
00533     }
00534     GD_INFO_DUMP("exiting onChange");
00535     return 0;
00536   }
00537 
00538   int onAccess(urbi::UVar& v)
00539   {
00540     threadCheck();
00541     static int val = 0;
00542     lastAccess = v.get_name();
00543     val++;
00544     v = val;
00545     lastAccessVal = val;
00546     if ((std::string)removeNotify == v.get_name())
00547     {
00548       v.unnotify();
00549       removeNotify = "";
00550     }
00551     return 0;
00552   }
00553 
00554   void
00555   sendEvent()
00556   {
00557     threadCheck();
00558     ev.emit();
00559   }
00560 
00561   void
00562   sendEvent2Args(urbi::UValue v1, urbi::UValue v2)
00563   {
00564     ev.emit(v1, v2);
00565   }
00566 
00567   void sendEvent8Args()
00568   {
00569     ev.emit(0, "foo", 5.1, 4, 5, 6, 7);
00570   }
00571 
00572 
00573   void
00574   sendNamedEvent(const std::string& name)
00575   {
00576     urbi::UEvent tempEv(name);
00577     tempEv.emit();
00578   }
00579 
00581   urbi::UList
00582   readProps(const std::string& name)
00583   {
00584     threadCheck();
00585     urbi::UVar v(name);
00586     urbi::UList res;
00587 
00588 #define APPEND(Value)                                   \
00589     res.array.push_back(new urbi::UValue(Value))
00590 
00591 #define APPEND_UFLOAT(Prop)                     \
00592     APPEND(static_cast<ufloat>(v.Prop))
00593 
00594     APPEND_UFLOAT(rangemin);
00595     APPEND_UFLOAT(rangemax);
00596     APPEND_UFLOAT(speedmin);
00597     APPEND_UFLOAT(speedmax);
00598     APPEND_UFLOAT(delta);
00599     urbi::UValue bl = v.blend;
00600     APPEND(bl);
00601     APPEND_UFLOAT(constant);
00602 #undef APPEND_UFLOAT
00603 #undef APPEND
00604 
00605     GD_FINFO_DEBUG("all.readProps: %s", res);
00606     return res;
00607   }
00608 
00609   int writeProps(const std::string& name, ufloat val)
00610   {
00611     threadCheck();
00612     urbi::UVar v(name);
00613     v.rangemin = val;
00614     v.rangemax = val;
00615     v.speedmin = val;
00616     v.speedmax = val;
00617     v.delta = val;
00618     v.blend = val;
00619     v.constant = (val>0);
00620     return 0;
00621   }
00622 
00623 
00626   int writeD(const std::string& name, ufloat val)
00627   {
00628     threadCheck();
00629     GD_FINFO_DEBUG("writeD %s", name);
00630     urbi::UVar v(name);
00631     v = val;
00632     return 0;
00633   }
00634 
00635   int writeS(const std::string& name, const std::string& val)
00636   {
00637     GD_FINFO_DEBUG("writeS %s", name);
00638     urbi::UVar v(name);
00639     v = val;
00640     return 0;
00641   }
00642 
00643   int writeL(const std::string& name, const std::string& val)
00644   {
00645     GD_FINFO_DEBUG("writeL %s", name);
00646     urbi::UVar v(name);
00647     urbi::UList l;
00648     l.array.push_back(new urbi::UValue(val));
00649     l.array.push_back(new urbi::UValue(42));
00650     v = l;
00651     return 0;
00652   }
00653 
00654   int writeM(const std::string& name, const std::string& val)
00655   {
00656     GD_FINFO_DEBUG("writeM %s", name);
00657     urbi::UVar v(name);
00658     urbi::UDictionary d;
00659     d[val] = 42;
00660     d["foo"] = urbi::UList();
00661     v = d;
00662     return 0;
00663   }
00664 
00665   int writeB(const std::string& name, const std::string& content)
00666   {
00667     urbi::UVar v(name);
00668     urbi::UBinary val;
00669     val.type = urbi::BINARY_UNKNOWN;
00670     val.common.size = content.length();
00671     val.common.data = malloc(content.length());
00672     memcpy(val.common.data, content.c_str(), content.length());
00673     v = val;
00674     return 0;
00675   }
00676 
00677   int writeBNone(const std::string& name, const std::string& content)
00678   {
00679     urbi::UVar v(name);
00680     urbi::UBinary val;
00681     val.common.size = content.length();
00682     val.common.data = malloc(content.length());
00683     memcpy(val.common.data, content.c_str(), content.length());
00684     v = val;
00685     return 0;
00686   }
00687 
00688   int writeI(const std::string& name, const std::string& content)
00689   {
00690     urbi::UVar v(name);
00691     urbi::UImage i;
00692     i.init();
00693     i.imageFormat = urbi::IMAGE_JPEG;
00694     i.width = i.height = 42;
00695     i.size = content.length();
00696     i.data = (unsigned char*)malloc(content.length());
00697     memcpy(i.data, content.c_str(), content.length());
00698     v = i;
00699     free(i.data);
00700     return 0;
00701   }
00702 
00703   int writeSnd(const std::string& name, const std::string& content)
00704   {
00705     urbi::UVar v(name);
00706     urbi::USound s;
00707     s.init();
00708     s.soundFormat = urbi::SOUND_RAW;
00709     s.rate = 42;
00710     s.size = content.length();
00711     s.channels = 1;
00712     s.sampleSize= 8;
00713     s.sampleFormat = urbi::SAMPLE_UNSIGNED;
00714     s.data = (char*)malloc(content.length());
00715     memcpy(s.data, content.c_str(), content.length());
00716     v = s;
00717     free(s.data);
00718     return 0;
00719   }
00720 
00721 
00722   int writeRI(const std::string& name, const std::string& content)
00723   {
00724     urbi::UVar v(name);
00725     urbi::UImage i = v;
00726     memcpy(i.data, content.c_str(), content.length());
00727     return 0;
00728   }
00729 
00730   int writeRSnd(const std::string& name, const std::string& content)
00731   {
00732     urbi::UVar v(name);
00733     urbi::USound i = v;
00734     memcpy(i.data, content.c_str(), content.length());
00735     return 0;
00736   }
00737 
00738 
00740   ufloat transmitD(ufloat v) const
00741   {
00742     threadCheck();
00743     return -(ufloat)v;
00744   }
00745 
00746   urbi::UList transmitL(urbi::UList l) const
00747   {
00748     urbi::UList r;
00749     for (unsigned int i=0; i<l.array.size(); i++)
00750       r.array.push_back(new urbi::UValue(*l.array[l.array.size()-i-1]));
00751     return r;
00752   }
00753 
00754   urbi::UDictionary transmitM(urbi::UDictionary d) const
00755   {
00756     urbi::UDictionary r;
00757     foreach (const urbi::UDictionary::value_type& t, d)
00758       r[t.first] = t.second;
00759     return r;
00760   }
00761 
00762   std::string transmitS(const std::string& name) const
00763   {
00764     return name.substr(1, name.length()-2);
00765   }
00766 
00767   urbi::UBinary transmitB(urbi::UBinary b) const
00768   {
00769     urbi::UBinary res(b);
00770     unsigned char* data = static_cast<unsigned char*>(res.common.data);
00771     for (size_t i = 0; i < res.common.size; ++i)
00772       data[i] -= 1;
00773     data[res.common.size - 1] = '\n';
00774     return res;
00775   }
00776 
00777   urbi::UImage transmitI(urbi::UImage im) const
00778   {
00779     for (unsigned int i=0; i<im.size; i++)
00780       im.data[i] -= 1;
00781     return im;
00782   }
00783 
00784   urbi::USound transmitSnd(urbi::USound im) const
00785   {
00786     for (unsigned int i=0; i<im.size; i++)
00787       im.data[i] -= 1;
00788     return im;
00789   }
00790 
00791   urbi::UObject* transmitO(UObject* o) const
00792   {
00793     return o;
00794   }
00795 
00796   int sendString(const std::string& s)
00797   {
00798     threadCheck();
00799     send(s.c_str());
00800     return 0;
00801   }
00802 
00803   int sendBuf(const std::string& b, int l)
00804   {
00805     send(const_cast<void*>(static_cast<const void*>(b.c_str())), l);
00806     return 0;
00807   }
00808 
00809   int sendPar()
00810   {
00811     URBI((Object.a = 123,));
00812     return 0;
00813   }
00814 
00815   void loop_yield(long duration)
00816   {
00817     libport::utime_t end = libport::utime() + duration;
00818     while (libport::utime() < end)
00819     {
00820       yield();
00821       usleep(1000);
00822     }
00823   }
00824 
00825   int getDestructionCount() const
00826   {
00827     return destructionCount;
00828   }
00829 
00830   std::string uobjectName(UObject* n)
00831   {
00832     threadCheck();
00833     if (!n)
00834       return std::string();
00835     else
00836       return n->__name;
00837   }
00838 
00839   std::string allUObjectName(all* n)
00840   {
00841     return uobjectName(n);
00842   }
00843 
00844   void notifyWriteA(const std::string& target, int func)
00845   {
00846     switch(func)
00847     {
00848     case 0:
00849       UNotifyChange(target, &all::writeAD);
00850       break;
00851     case 1:
00852       UNotifyChange(target, &all::writeAS);
00853       break;
00854     case 2:
00855       UNotifyChange(target, &all::writeAB);
00856       break;
00857     case 3:
00858       UNotifyChange(target, &all::writeAV);
00859     }
00860   }
00861 
00862   void writeAD(ufloat d) { a = d; }
00863 
00864   void writeAS(const std::string& s) {a = s;}
00865 
00866   void writeAB(urbi::UBinary b) { a=b;}
00867 
00868   void writeAV(urbi::UValue v) { a=v;}
00869 
00870   void makeCall(const std::string& obj, const std::string& func,
00871                 urbi::UList args)
00872   {
00873     threadCheck();
00874     switch (args.size())
00875     {
00876 #define CASE(Num, ...)                                  \
00877       case Num: call(obj, func, ## __VA_ARGS__); break;
00878       CASE(0);
00879       CASE(1, args[0]);
00880       CASE(2, args[0], args[1]);
00881       CASE(3, args[0], args[1], args[2]);
00882       CASE(4, args[0], args[1], args[2], args[3]);
00883 #undef CASE
00884     default:
00885       throw std::runtime_error("Not implemented");
00886     }
00887   }
00888 
00889   void throwException(bool stdexcept)
00890   {
00891     if (stdexcept)
00892       throw std::runtime_error("KABOOM");
00893     else
00894       throw "KABOOM";
00895   }
00896 
00897   std::vector<unsigned long> socketStats()
00898   {
00899     std::vector<unsigned long> res;
00900     urbi::UClient* cl = urbi::getDefaultClient();
00901     if (!cl)
00902       return res;
00903    res.push_back(cl->bytesSent());
00904    res.push_back(cl->bytesReceived());
00905    return res;
00906   }
00907 
00908   // Test templates UVar.as, UVar.==, UVar.fill
00909   void manyWriteTest(int i)
00910   {
00911     #define CHECK                                     \
00912     if (d.size() !=2 || d[0] != 1 || d[1] != 2)       \
00913       throw std::runtime_error("vector is not what we expect")
00914     std::vector<ufloat> d;
00915     d.push_back(1);
00916     d.push_back(2);
00917     urbi::UVar& v =*vars[i];
00918     v = d;
00919     d = v.as(&d);
00920     CHECK;
00921     d = v.as<std::vector<ufloat> >();
00922     CHECK;
00923     v.fill(d);
00924     if (!(v == d))
00925       throw std::runtime_error("v != d");
00926     CHECK;
00927     boost::unordered_map<std::string, UObject*> vu;
00928     vu["coin"] = this;
00929     a = vu;
00930     a.fill(vu);
00931     if (!libport::mhas(vu, "coin") || vu["coin"] != this)
00932       throw std::runtime_error("hash is not what we expect");
00933   }
00934 
00935   ufloat area(Rect r)
00936   {
00937     return libport::round((r.a.x-r.b.x) * (r.a.y  - r.b.y));
00938   }
00939 
00940   PointOfInterest transmitPointOfInterest(PointOfInterest p)
00941   {
00942     return p;
00943   }
00944 
00945   void writePointOfInterest(urbi::UVar& target, PointOfInterest p)
00946   {
00947     target = p;
00948   }
00949 
00950   PointOfInterest readPointOfInterest(urbi::UVar& source)
00951   {
00952     source.syncValue();
00953     return source.as((PointOfInterest*)0);
00954   }
00955 
00956   Rect translate(Rect r, Point v)
00957   {
00958     r.a.x += v.x;
00959     r.a.y += v.y;
00960     r.b.x += v.x;
00961     r.b.y += v.y;
00962     return r;
00963   }
00964 
00965   Rect makeRect()
00966   {
00967     return Rect();
00968   }
00969 
00970   std::vector<Rect> multiTranslate(std::vector<Rect> src, Point v)
00971   {
00972     foreach(Rect& r, src)
00973       r = translate(r, v);
00974     return src;
00975   }
00976 
00977   std::vector<ufloat> unpack(UPackedData<ufloat> d)
00978   {
00979     return d;
00980   }
00981 
00982   UPackedData<ufloat> pack(std::vector<ufloat> d)
00983   {
00984     return d;
00985   }
00986   urbi::UVar a, b, c, d, unbound;
00987   urbi::UVar* vars[10];
00988   urbi::InputPort* ports[5];
00989   urbi::UEvent ev;
00990 
00991   //name of var that trigerred notifyChange
00992   urbi::UVar lastChange;
00993   //value read on said var
00994   urbi::UVar lastChangeVal;
00995   //name of var that triggered notifyAccess
00996   urbi::UVar lastAccess;
00997   //value written to said var
00998   urbi::UVar lastAccessVal;
00999   //Set to 0 in ctor, 1 in init
01000   urbi::UVar initCalled;
01001 
01002   // Periodic write target (0, 1 or 2 for a, b or c)
01003   urbi::UVar periodicWriteTarget;
01004   // Write rate (seconds)
01005   urbi::UVar periodicWriteRate;
01006   // Write data type
01007   urbi::UVar periodicWriteType;
01008   // Number of writes per call
01009   urbi::UVar periodicWriteCount;
01010 
01011   // If an UVar with the name in removeNotify reaches a callback,
01012   // unnotify will be called.
01013   urbi::UVar removeNotify;
01014   // Number of calls to onChange
01015   urbi::UVar changeCount;
01016   // Cached value to ensure consistency in remote mode.
01017   int count;
01018   static int destructionCount;
01019 };
01020 
01021 int all::destructionCount = 0;
01022 
01023 ::urbi::URBIStarter<all>
01024     starter1(urbi::isPluginMode() ? "all"  : "remall"),
01025     starter2(urbi::isPluginMode() ? "all2" : "remall2");