diff --git a/src/liboncilla/Oncilla.cpp b/src/liboncilla/Oncilla.cpp index 0e18514..236068a 100644 --- a/src/liboncilla/Oncilla.cpp +++ b/src/liboncilla/Oncilla.cpp @@ -1,109 +1,119 @@ /* * Oncilla.cpp * * Created on: 15 dec. 2011 * Author: Alexandre Tuleu, Arne Nordmann */ #include "Oncilla.h" #include namespace rci { namespace oncilla { -::rci::oncilla::Synchronizer::Ptr Oncilla::s_synchronizer; +::rci::oncilla::Oncilla::SetOfBackend Oncilla::s_backends; std::string Oncilla::nameOfLeg(Leg l){ static const char * legNames[NUM_LEGS + 1] = { "Left Fore", //LEFT_FORE "Right Fore", //RIGHT_FORE "Left Hind", //LEFT_HIND "Right Hind", //RIGHT_HIND "Undefined" }; //oncly consider index in range [0 NUM_LEGS], defaulting to NUM_LEGS if out of bound. int index((l < 0 ) ? NUM_LEGS : (l > NUM_LEGS ? NUM_LEGS : l)); return legNames[index]; } +Oncilla::Oncilla(const OncillaBackend::Ptr & backend) + : d_backend(backend){ + init(); +} + Oncilla::Oncilla(){ - if(!s_synchronizer){ - if(!d_backend){ - BackendLoader bl; - //we have to keep alive the pointer or dlclose() will be called once - //We free him. Or we could add BackendLoader as a member of Oncilla - // I prefer only to have the Object creator interface. - d_backend = bl.SuitableBackend(); - } - s_synchronizer = d_backend->CreateSynchronizer(); - init(); - } + init(); } Oncilla::~Oncilla() { } void Oncilla::init() { + if(!d_backend){ + BackendLoader bl; + + d_backend = bl.SuitableBackend(); + } + + //If the backend get destroyed, then the plugin is dl_close(). So if + //we get some reference that are get from Oncilla object, and Oncilla + //object is destroyed, then we are sure the plugin is still loaded. + //we are not sure only if the shared_ptr are put in statix variable. + + s_backends.insert(d_backend); //never removed until end of program. + + d_synchronizer = d_backend->CreateSynchronizer(); + d_L0s.reserve(4); d_L1s.reserve(4); d_L2s.reserve(4); d_L3s.reserve(4); LIBONCILLA_FOREACH_LEG(l){ d_L0s.push_back(d_backend->CreateL0(l,Oncilla::nameOfLeg(l) + " Oncilla L0")); d_L1s.push_back(d_backend->CreateL1(l,Oncilla::nameOfLeg(l) + " Oncilla L1")); d_L2s.push_back(d_backend->CreateL2(l,Oncilla::nameOfLeg(l) + " Oncilla L2")); d_L3s.push_back(d_backend->CreateL3(l,Oncilla::nameOfLeg(l) + " Oncilla L3")); } d_trunk = d_backend->CreateTrunk(); d_supervisor = Supervisor::Ptr(new Supervisor(*d_backend)); - s_synchronizer->calibrateIfNeeded(); + d_synchronizer->calibrateIfNeeded(); } const L0::Ptr & Oncilla::getL0(Leg l) const { return this->d_L0s[l]; } const L1::Ptr & Oncilla::getL1(Leg l) const { return this->d_L1s[l]; } const L2::Ptr & Oncilla::getL2(Leg l) const { return this->d_L2s[l]; } const L3::Ptr & Oncilla::getL3(Leg l) const { return this->d_L3s[l]; } const Trunk::Ptr & Oncilla::getTrunk() const { return this->d_trunk; } const rci::oncilla::Synchronizer::Ptr & Oncilla::getSynchronizer() const { - if(!s_synchronizer){ + if(!d_synchronizer){ throw std::logic_error("Internal error : synchronizer seems unitialized" ", but it should never happen. Please report this bug."); } - return this->s_synchronizer; + return this->d_synchronizer; } const rci::oncilla::Supervisor::Ptr & Oncilla::getSupervisor() const { return d_supervisor; } } } diff --git a/src/liboncilla/Oncilla.h b/src/liboncilla/Oncilla.h index f55a802..729ad31 100644 --- a/src/liboncilla/Oncilla.h +++ b/src/liboncilla/Oncilla.h @@ -1,71 +1,75 @@ /* * Oncilla.h * * Created on: 15 dec. 2011 * Author: Alexandre Tuleu, Arne Nordmann */ #pragma once #include #include #include #include "common.h" #include "Supervisor.h" #include #include #include +#include + namespace rci { namespace oncilla { class BackendLoader; class Oncilla { public: typedef boost::shared_ptr Ptr; static std::string nameOfLeg(Leg l); Oncilla(); + Oncilla(const OncillaBackend::Ptr & backend); virtual ~Oncilla(); const L0::Ptr & getL0(Leg l) const; const L1::Ptr & getL1(Leg l) const; const L2::Ptr & getL2(Leg l) const; const L3::Ptr & getL3(Leg l) const; const Trunk::Ptr & getTrunk() const; const rci::oncilla::Synchronizer::Ptr & getSynchronizer() const; const rci::oncilla::Supervisor::Ptr & getSupervisor() const; private: typedef std::vector LegNames; - + typedef std::set SetOfBackend; void init(); - static rci::oncilla::Synchronizer::Ptr s_synchronizer; + static SetOfBackend s_backends; + + rci::oncilla::Synchronizer::Ptr d_synchronizer; - //beware that the object holded by liboncilla - //are create by the backend. therefore, the pointer has to destroyed after - //all the other member instance - OncillaBackend::Ptr d_backend; //should be first instance WHATSOEVER + //object cerated with teh backend depend on the backen existance, so this + // pointer should be first (even if we save the backends in the static set) + OncillaBackend::Ptr d_backend; std::vector d_L0s; std::vector d_L1s; std::vector d_L2s; std::vector d_L3s; Trunk::Ptr d_trunk; Supervisor::Ptr d_supervisor; }; } }