5 #include "CppContainer.hxx"
6 #include "CppComponent.hxx"
7 #include "Exception.hxx"
12 using namespace YACS::ENGINE;
15 #include "YacsTrace.hxx"
17 //=============================================================================
19 * Local C++ container class constructor
21 //=============================================================================
23 CppContainer::CppContainer() : _trueCont(0L)
25 DEBTRACE("CppContainer::CppContainer()");
29 //=============================================================================
31 * Local C++ container class destructor
33 //=============================================================================
35 CppContainer::~CppContainer()
37 DEBTRACE("CppContainer::~CppContainer()");
40 void CppContainer::lock()
45 void CppContainer::unLock()
50 bool CppContainer::isAlreadyStarted() const
52 return NULL != _trueCont;
55 void CppContainer::start() throw (YACS::Exception)
57 _trueCont = LocalContainer::get();
60 Container *CppContainer::clone() const
62 if(_isAttachedOnCloning)
65 return (Container*) (this);
68 return new CppContainer(*this);
71 bool CppContainer::loadComponentLibrary(const std::string & componentName) throw (YACS::Exception)
75 LocalLibrary L = _trueCont->loadComponentLibrary(componentName);
80 std::string mesg = "CppContainer not started";
81 throw YACS::Exception(mesg);
86 CppComponent * CppContainer::createComponentInstance(const std::string & componentName, int /* studyID */)
88 DEBTRACE("CppContainer::createComponentInstance");
90 return _trueCont->createComponentInstance(componentName.c_str());
93 std::string mesg = "CppContainer not started";
94 throw YACS::Exception(mesg);
98 void CppContainer::createInternalInstance(const std::string & name, void *&obj,
99 RunFunction &r, TerminateFunction &t)
101 DEBTRACE("CppContainer::createInternalInstance");
103 _trueCont->createInternalInstance(name.c_str(), obj, r, t);
106 std::string mesg = "CppContainer not started";
107 throw YACS::Exception(mesg);
111 void CppContainer::unregisterComponentInstance(CppComponent * C)
115 _trueCont->unregisterComponentInstance(C);
120 std::string CppContainer::getPlacementId() const
125 void CppContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw (Exception)
127 if(inst->getKind()!=CppComponent::KIND)
128 throw Exception("CppContainer::checkCapabilityToDealWith : CppContainer is not able to deal with this type of ComponentInstance.");
131 std::map<std::string, LocalLibrary> LocalContainer::_library_map; // libraries, loaded
132 std::multimap<std::string, CppComponent *> LocalContainer::_instance_map;
134 LocalContainer * LocalContainer::_singleton = NULL;
136 LocalContainer::LocalContainer()
140 LocalContainer::~LocalContainer()
145 LocalContainer * LocalContainer::get()
147 if (NULL == _singleton)
149 _singleton = new LocalContainer;
154 void LocalContainer::destroy()
156 if (NULL == _singleton)
159 // destroy all component instances
160 _instance_mapMutex.lock(); // lock
161 std::multimap<std::string, CppComponent *>::iterator iI, iJ;
162 for (iI=_instance_map.begin(); iI != _instance_map.end(); iI = iJ)
165 iI->second->setContainer(NULL);
168 _instance_map.clear();
169 _instance_mapMutex.unlock(); // unlock
171 // unload all dynamic libraries
172 _library_mapMutex.lock();
173 std::map<std::string, LocalLibrary>::iterator iL;
174 for (iL=_library_map.begin(); iL != _library_map.end(); iL++)
175 dlclose(iL->second.handle);
176 _library_map.clear();
177 _library_mapMutex.unlock();
184 //=============================================================================
185 //! Find or create a new C++ component instance
187 * Create a new component class (C++ implementation)
188 * \param name : component name
190 * Try to return a handle to an new instance of a C++ component
191 * If the associated library is not loaded, try to load it
193 * \return a handle to the component instance or throw an exception
194 * if it's not possible
196 //=============================================================================
197 CppComponent * LocalContainer::createComponentInstance(const char * name)
203 createInternalInstance(name, o, r, t);
206 C = new CppComponent(o, r, t, name);
207 _instance_mapMutex.lock(); // lock to be alone
208 _instance_map.insert(std::pair<std::string, CppComponent *>(name, C));
209 _instance_mapMutex.unlock(); // unlock
213 void LocalContainer::createInternalInstance(const char *name, void *&obj,
214 RunFunction &r, TerminateFunction &t)
218 std::map<std::string, LocalLibrary>::iterator foundL = _library_map.find(name);
219 if (foundL != _library_map.end())
222 L = loadComponentLibrary(name, NULL, false);
225 InitFunction i = L.initHandle;
226 t = L.terminateHandle;
228 PingFunction p = L.pingHandle;
235 void LocalContainer::unregisterComponentInstance(CppComponent * C)
237 _instance_mapMutex.lock(); // lock to be alone
238 _instance_map.erase(C->getName());
239 _instance_mapMutex.unlock(); // unlock
242 //=============================================================================
244 * load a new component class (C++ implementation)
245 * \param componentName like COMPONENT
246 * try to load libCOMPONENTLocal.so
247 * \return true if dlopen successfull or already done, false otherwise
249 //=============================================================================
251 inline void toupper (std::string & s)
253 transform (s.begin (), s.end (), s.begin (), (int(*)(int)) toupper);
256 LocalLibrary LocalContainer::loadComponentLibrary(const std::string & aCompName, const char * prefix, bool forcedLoad)
259 // if forcedLoad is true, unload library if it exists
260 // if forcedLoad is false, return the existing library or load it
263 unLoadComponentLibrary(aCompName);
266 std::map<std::string, LocalLibrary >::iterator itLib
267 = _library_map.find(aCompName);
268 if (itLib != _library_map.end()) return itLib->second;
271 // --- try dlopen C++ component
278 std::string s = aCompName + "_ROOT_DIR";
280 const char * t = getenv(s.c_str());
285 sprefix += "/lib/salome";
290 std::string impl_name = std::string ("lib") + aCompName + std::string("Local.so");
292 impl_name = sprefix + std::string("/") + impl_name;
294 std::string impl_name = aCompName + std::string("Local.dll");
295 impl_name = sprefix + std::string("\\") + impl_name;
297 DEBTRACE("impl_name = " << impl_name);
301 handle = dlopen( impl_name.c_str() , 0 ) ;
303 handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
309 if ((sError = dlerror()) || !handle)
311 std::stringstream msg;
312 msg << "Can't load shared library : " << impl_name
313 << " (dlopen error : " << sError << ") at "
314 << __FILE__ << ":" << __LINE__;
315 throw YACS::Exception(msg.str());
318 void *ihandle, *rhandle, *phandle = NULL, *thandle = NULL;
320 ihandle = dlsym(handle, "__init");
321 if (sError = dlerror())
324 std::stringstream msg;
325 msg << "Library " << impl_name
326 << " doesn't contains initialization function (" << sError << ") at "
327 << __FILE__ << ":" << __LINE__;
328 throw YACS::Exception(msg.str());
331 rhandle = dlsym(handle, "__run");
332 if (sError = dlerror())
335 std::stringstream msg;
336 msg << "Library " << impl_name
337 << " doesn't contains main switch function (" << sError << ") at "
338 << __FILE__ << ":" << __LINE__;
339 throw YACS::Exception(msg.str());
342 thandle = dlsym(handle, "__terminate");
343 if (sError = dlerror())
346 std::stringstream msg;
347 msg << "Library " << impl_name
348 << " doesn't contains terminate function (" << sError << ") at "
349 << __FILE__ << ":" << __LINE__;
350 throw YACS::Exception(msg.str());
352 phandle = dlsym(handle, "__ping");
354 _library_map[aCompName] = LocalLibrary(handle, (InitFunction) ihandle,
355 (RunFunction) rhandle,
356 (PingFunction) phandle,
357 (TerminateFunction) thandle);
358 return _library_map[aCompName];
361 void LocalContainer::unLoadComponentLibrary(const std::string & aCompName)
363 std::map<std::string, LocalLibrary >::iterator itLib
364 = _library_map.find(aCompName);
366 if (itLib == _library_map.end()) return;
368 dlclose(itLib->second.handle);
369 _library_map.erase(itLib);