Urbi SDK Remote for C++  2.7.5
subsumption.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010-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 <libport/asio.hh>
00012 
00013 #include <urbi/uobject.hh>
00014 
00015 using namespace urbi;
00016 
00022 class subsumption: public UObject
00023 {
00024 public:
00025   subsumption(const std::string& n);
00027   int init(UVar& target);
00031   void createTimedOverride(const std::string& varName, int level, ufloat delay);
00033   void createOverride(const std::string& varName, int level);
00035   UVar level;
00036 private:
00037   class SUVar: public UVar
00038   {
00039   public:
00040     SUVar(const std::string& obj, const std::string& var, int level,
00041          ufloat delay = 0);
00042     friend class subsumption;
00043   private:
00044     int level_;
00045     ufloat timer_;
00046   };
00047   int onLevelChange(UVar& v);
00048   int onWrite(UVar& v);
00049   int onRead(UVar& v);
00050   void resetLevel(int oldLevel, int writeCount);
00051   UVar* target_;
00052   int writeCount_;
00053 };
00054 
00055 
00056 subsumption::subsumption(const std::string& n)
00057   : UObject(n)
00058   , target_(0)
00059   , writeCount_(0)
00060 {
00061   UBindFunction(subsumption, init);
00062 }
00063 
00064 int
00065 subsumption::init(UVar& target)
00066 {
00067   std::string targetName = target.get_name();
00068   UBindVar(subsumption, level);
00069   UBindFunction(subsumption, createOverride);
00070   UBindFunction(subsumption, createTimedOverride);
00071   UNotifyChange(level, &subsumption::onLevelChange);
00072   level = 0;
00073   target_ = new UVar(targetName);
00074   createOverride("val", 0);
00075   return 0;
00076 }
00077 
00078 void
00079 subsumption::createOverride(const std::string& name, int level)
00080 {
00081   createTimedOverride(name, level, 0);
00082 }
00083 
00084 void
00085 subsumption::createTimedOverride(const std::string& name, int level,
00086                                  ufloat timer)
00087 {
00088   SUVar* v = new SUVar(__name, name, level, timer);
00089   v->setOwned();
00090   UNotifyChange(*v, &subsumption::onWrite);
00091   UNotifyAccess(*v, &subsumption::onRead);
00092 }
00093 
00094 int
00095 subsumption::onLevelChange(UVar&)
00096 {
00097   writeCount_++;
00098   return 0;
00099 }
00100 
00101 int
00102 subsumption::onRead(UVar& v)
00103 {
00104   v = target_->val();
00105   return 0;
00106 }
00107 
00108 int
00109 subsumption::onWrite(UVar& v)
00110 {
00111   SUVar& sv = static_cast<SUVar&>(v);
00112   if ((int)level <= sv.level_)
00113   {
00114     *target_ = sv.val();
00115     if (sv.timer_)
00116     {
00117       int oldLevel = level;
00118       level = sv.level_;
00119       // Keep this line after the previous one.
00120       libport::asyncCall(boost::bind(&subsumption::resetLevel, this,
00121                                      oldLevel, writeCount_),
00122                          useconds_t(sv.timer_ * 1000000.0));
00123     }
00124   }
00125   return 0;
00126 }
00127 
00128 subsumption::SUVar::SUVar(const std::string& obj, const std::string& var,
00129                           int level, ufloat delay)
00130   : UVar(obj, var)
00131   , level_(level)
00132   , timer_(delay)
00133 {
00134 }
00135 
00136 void
00137 subsumption::resetLevel(int newLevel, int wc)
00138 {
00139   ctx_->lock();
00140   // Only reset if level was not written on since first trigger.
00141   if (writeCount_ == wc)
00142     level = newLevel;
00143   ctx_->unlock();
00144 }
00145 
00146 UStart(subsumption);