1 // Copyright (C) 2006-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 #define dlopen LoadLibrary
25 #define dlclose FreeLibrary
26 #define dlsym GetProcAddress
31 #include "CppContainer.hxx"
32 #include "CppComponent.hxx"
33 #include "Exception.hxx"
38 using namespace YACS::ENGINE;
41 #include "YacsTrace.hxx"
43 //=============================================================================
45 * Local C++ container class constructor
47 //=============================================================================
49 CppContainer::CppContainer() : _trueCont(0L)
51 DEBTRACE("CppContainer::CppContainer()");
55 //=============================================================================
57 * Local C++ container class destructor
59 //=============================================================================
61 CppContainer::~CppContainer()
63 DEBTRACE("CppContainer::~CppContainer()");
66 void CppContainer::lock()
71 void CppContainer::unLock()
76 bool CppContainer::isAlreadyStarted(const Task *askingNode) const
78 return NULL != _trueCont;
81 void CppContainer::start(const Task *askingNode) throw (YACS::Exception)
83 _trueCont = LocalContainer::get();
86 void CppContainer::shutdown(int level)
91 Container *CppContainer::clone() const
93 if(_isAttachedOnCloning)
96 return (Container*) (this);
99 return new CppContainer(*this);
102 Container *CppContainer::cloneAlways() const
104 return new CppContainer(*this);
107 bool CppContainer::loadComponentLibrary(const std::string & componentName) throw (YACS::Exception)
111 LocalLibrary L = _trueCont->loadComponentLibrary(componentName);
116 std::string mesg = "CppContainer not started";
117 throw YACS::Exception(mesg);
122 CppComponent * CppContainer::createComponentInstance(const std::string & componentName, int /* studyID */)
124 DEBTRACE("CppContainer::createComponentInstance");
126 return _trueCont->createComponentInstance(componentName.c_str());
129 std::string mesg = "CppContainer not started";
130 throw YACS::Exception(mesg);
134 void CppContainer::createInternalInstance(const std::string & name, void *&obj,
135 RunFunction &r, TerminateFunction &t)
137 DEBTRACE("CppContainer::createInternalInstance");
139 _trueCont->createInternalInstance(name.c_str(), obj, r, t);
142 std::string mesg = "CppContainer not started";
143 throw YACS::Exception(mesg);
147 void CppContainer::unregisterComponentInstance(CppComponent *compo)
150 _trueCont->unregisterComponentInstance(compo);
154 std::string CppContainer::getPlacementId(const Task *askingNode) const
159 std::string CppContainer::getFullPlacementId(const Task *askingNode) const
164 void CppContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception)
166 if(inst->getKind()!=CppComponent::KIND)
167 throw Exception("CppContainer::checkCapabilityToDealWith : CppContainer is not able to deal with this type of ComponentInstance.");
170 std::map<std::string, LocalLibrary> LocalContainer::_library_map; // libraries, loaded
171 std::multimap<std::string, CppComponent *> LocalContainer::_instance_map;
173 LocalContainer * LocalContainer::_singleton = NULL;
175 LocalContainer::LocalContainer()
179 LocalContainer::~LocalContainer()
184 LocalContainer * LocalContainer::get()
186 if (NULL == _singleton)
188 _singleton = new LocalContainer;
193 void LocalContainer::destroy()
195 if (NULL == _singleton)
198 // destroy all component instances
199 _instance_mapMutex.lock(); // lock
200 std::multimap<std::string, CppComponent *>::iterator iI, iJ;
201 for (iI=_instance_map.begin(); iI != _instance_map.end(); iI = iJ)
204 iI->second->setContainer(NULL);
207 _instance_map.clear();
208 _instance_mapMutex.unLock(); // unlock
210 // unload all dynamic libraries
211 _library_mapMutex.lock();
212 std::map<std::string, LocalLibrary>::iterator iL;
213 for (iL=_library_map.begin(); iL != _library_map.end(); iL++)
214 dlclose(iL->second.handle);
215 _library_map.clear();
216 _library_mapMutex.unLock();
223 //=============================================================================
224 //! Find or create a new C++ component instance
226 * Create a new component class (C++ implementation)
227 * \param name : component name
229 * Try to return a handle to an new instance of a C++ component
230 * If the associated library is not loaded, try to load it
232 * \return a handle to the component instance or throw an exception
233 * if it's not possible
235 //=============================================================================
236 CppComponent * LocalContainer::createComponentInstance(const char * name)
242 createInternalInstance(name, o, r, t);
245 C = new CppComponent(o, r, t, name);
246 _instance_mapMutex.lock(); // lock to be alone
247 _instance_map.insert(std::pair<std::string, CppComponent *>(name, C));
248 _instance_mapMutex.unLock(); // unlock
252 void LocalContainer::createInternalInstance(const char *name, void *&obj,
253 RunFunction &r, TerminateFunction &t)
257 std::map<std::string, LocalLibrary>::iterator foundL = _library_map.find(name);
258 if (foundL != _library_map.end())
261 L = loadComponentLibrary(name, NULL, false);
264 InitFunction i = L.initHandle;
265 t = L.terminateHandle;
267 PingFunction p = L.pingHandle;
274 void LocalContainer::unregisterComponentInstance(CppComponent * C)
276 _instance_mapMutex.lock(); // lock to be alone
277 _instance_map.erase(C->getCompoName());
278 _instance_mapMutex.unLock(); // unlock
281 inline void toupper (std::string & s)
283 transform (s.begin (), s.end (), s.begin (), (int(*)(int)) toupper);
286 LocalLibrary LocalContainer::loadComponentLibrary(const std::string & aCompName, const char * prefix, bool forcedLoad)
289 // if forcedLoad is true, unload library if it exists
290 // if forcedLoad is false, return the existing library or load it
293 unLoadComponentLibrary(aCompName);
296 std::map<std::string, LocalLibrary >::iterator itLib
297 = _library_map.find(aCompName);
298 if (itLib != _library_map.end()) return itLib->second;
301 // --- try dlopen C++ component
308 std::string s = aCompName + "_ROOT_DIR";
310 const char * t = getenv(s.c_str());
315 sprefix += "/lib/salome";
320 std::string impl_name = std::string ("lib") + aCompName + std::string("Local.so");
322 impl_name = sprefix + std::string("/") + impl_name;
324 std::string impl_name = aCompName + std::string("Local.dll");
325 impl_name = sprefix + std::string("\\") + impl_name;
327 DEBTRACE("impl_name = " << impl_name);
331 handle = dlopen( impl_name.c_str() ) ;
334 handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
339 sError = "Not available here !";
346 if ((sError = dlerror()) || !handle)
349 std::stringstream msg;
350 msg << "Can't load shared library : " << impl_name
351 << " (dlopen error : " << sError << ") at "
352 << __FILE__ << ":" << __LINE__;
353 throw YACS::Exception(msg.str());
356 void *ihandle, *rhandle, *phandle = NULL, *thandle = NULL;
358 ihandle = dlsym(handle, "__init");
362 if (sError = dlerror())
366 std::stringstream msg;
367 msg << "Library " << impl_name
368 << " doesn't contains initialization function (" << sError << ") at "
369 << __FILE__ << ":" << __LINE__;
370 throw YACS::Exception(msg.str());
373 rhandle = dlsym(handle, "__run");
377 if (sError = dlerror())
381 std::stringstream msg;
382 msg << "Library " << impl_name
383 << " doesn't contains main switch function (" << sError << ") at "
384 << __FILE__ << ":" << __LINE__;
385 throw YACS::Exception(msg.str());
388 thandle = dlsym(handle, "__terminate");
392 if (sError = dlerror())
396 std::stringstream msg;
397 msg << "Library " << impl_name
398 << " doesn't contains terminate function (" << sError << ") at "
399 << __FILE__ << ":" << __LINE__;
400 throw YACS::Exception(msg.str());
402 phandle = dlsym(handle, "__ping");
404 _library_map[aCompName] = LocalLibrary(handle, (InitFunction) ihandle,
405 (RunFunction) rhandle,
406 (PingFunction) phandle,
407 (TerminateFunction) thandle);
408 return _library_map[aCompName];
411 void LocalContainer::unLoadComponentLibrary(const std::string & aCompName)
413 std::map<std::string, LocalLibrary >::iterator itLib
414 = _library_map.find(aCompName);
416 if (itLib == _library_map.end()) return;
418 dlclose(itLib->second.handle);
419 _library_map.erase(itLib);