1 // Copyright (C) 2006-2020 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;
40 char CppContainer::KIND[]="Cpp";
43 #include "YacsTrace.hxx"
45 //=============================================================================
47 * Local C++ container class constructor
49 //=============================================================================
51 CppContainer::CppContainer() : _trueCont(0L)
53 DEBTRACE("CppContainer::CppContainer()");
57 //=============================================================================
59 * Local C++ container class destructor
61 //=============================================================================
63 CppContainer::~CppContainer()
65 DEBTRACE("CppContainer::~CppContainer()");
68 void CppContainer::lock()
73 void CppContainer::unLock()
78 std::string CppContainer::getKind() const
83 bool CppContainer::isAlreadyStarted(const Task *askingNode) const
85 return NULL != _trueCont;
88 void CppContainer::start(const Task *askingNode)
90 _trueCont = LocalContainer::get();
93 void CppContainer::shutdown(int level)
98 Container *CppContainer::clone() const
100 if(_isAttachedOnCloning)
103 return (Container*) (this);
106 return new CppContainer(*this);
109 Container *CppContainer::cloneAlways() const
111 return new CppContainer(*this);
114 bool CppContainer::loadComponentLibrary(const std::string & componentName)
118 LocalLibrary L = _trueCont->loadComponentLibrary(componentName);
123 std::string mesg = "CppContainer not started";
124 throw YACS::Exception(mesg);
129 CppComponent * CppContainer::createComponentInstance(const std::string & componentName)
131 DEBTRACE("CppContainer::createComponentInstance");
133 return _trueCont->createComponentInstance(componentName.c_str());
136 std::string mesg = "CppContainer not started";
137 throw YACS::Exception(mesg);
141 void CppContainer::createInternalInstance(const std::string & name, void *&obj,
142 RunFunction &r, TerminateFunction &t)
144 DEBTRACE("CppContainer::createInternalInstance");
146 _trueCont->createInternalInstance(name.c_str(), obj, r, t);
149 std::string mesg = "CppContainer not started";
150 throw YACS::Exception(mesg);
154 void CppContainer::unregisterComponentInstance(CppComponent *compo)
157 _trueCont->unregisterComponentInstance(compo);
161 std::string CppContainer::getPlacementId(const Task *askingNode) const
166 std::string CppContainer::getFullPlacementId(const Task *askingNode) const
171 void CppContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const
173 if(inst->getKind()!=CppComponent::KIND)
174 throw Exception("CppContainer::checkCapabilityToDealWith : CppContainer is not able to deal with this type of ComponentInstance.");
177 std::map<std::string, LocalLibrary> LocalContainer::_library_map; // libraries, loaded
178 std::multimap<std::string, CppComponent *> LocalContainer::_instance_map;
180 LocalContainer * LocalContainer::_singleton = NULL;
182 LocalContainer::LocalContainer()
186 LocalContainer::~LocalContainer()
191 LocalContainer * LocalContainer::get()
193 if (NULL == _singleton)
195 _singleton = new LocalContainer;
200 void LocalContainer::destroy()
202 if (NULL == _singleton)
205 // destroy all component instances
206 _instance_mapMutex.lock(); // lock
207 std::multimap<std::string, CppComponent *>::iterator iI, iJ;
208 for (iI=_instance_map.begin(); iI != _instance_map.end(); iI = iJ)
211 iI->second->setContainer(NULL);
214 _instance_map.clear();
215 _instance_mapMutex.unLock(); // unlock
217 // unload all dynamic libraries
218 _library_mapMutex.lock();
219 std::map<std::string, LocalLibrary>::iterator iL;
220 for (iL=_library_map.begin(); iL != _library_map.end(); iL++)
221 dlclose(iL->second.handle);
222 _library_map.clear();
223 _library_mapMutex.unLock();
230 //=============================================================================
231 //! Find or create a new C++ component instance
233 * Create a new component class (C++ implementation)
234 * \param name : component name
236 * Try to return a handle to an new instance of a C++ component
237 * If the associated library is not loaded, try to load it
239 * \return a handle to the component instance or throw an exception
240 * if it's not possible
242 //=============================================================================
243 CppComponent * LocalContainer::createComponentInstance(const char * name)
249 createInternalInstance(name, o, r, t);
252 C = new CppComponent(o, r, t, name);
253 _instance_mapMutex.lock(); // lock to be alone
254 _instance_map.insert(std::pair<std::string, CppComponent *>(name, C));
255 _instance_mapMutex.unLock(); // unlock
259 void LocalContainer::createInternalInstance(const char *name, void *&obj,
260 RunFunction &r, TerminateFunction &t)
264 std::map<std::string, LocalLibrary>::iterator foundL = _library_map.find(name);
265 if (foundL != _library_map.end())
268 L = loadComponentLibrary(name, NULL, false);
271 InitFunction i = L.initHandle;
272 t = L.terminateHandle;
274 PingFunction p = L.pingHandle;
281 void LocalContainer::unregisterComponentInstance(CppComponent * C)
283 _instance_mapMutex.lock(); // lock to be alone
284 _instance_map.erase(C->getCompoName());
285 _instance_mapMutex.unLock(); // unlock
288 inline void toupper (std::string & s)
290 transform (s.begin (), s.end (), s.begin (), (int(*)(int)) toupper);
293 LocalLibrary LocalContainer::loadComponentLibrary(const std::string & aCompName, const char * prefix, bool forcedLoad)
296 // if forcedLoad is true, unload library if it exists
297 // if forcedLoad is false, return the existing library or load it
300 unLoadComponentLibrary(aCompName);
303 std::map<std::string, LocalLibrary >::iterator itLib
304 = _library_map.find(aCompName);
305 if (itLib != _library_map.end()) return itLib->second;
308 // --- try dlopen C++ component
315 std::string s = aCompName + "_ROOT_DIR";
317 const char * t = getenv(s.c_str());
322 sprefix += "/lib/salome";
328 std::string impl_name = std::string ("lib") + aCompName + std::string("Local.dylib");
330 std::string impl_name = std::string ("lib") + aCompName + std::string("Local.so");
333 impl_name = sprefix + std::string("/") + impl_name;
335 std::string impl_name = aCompName + std::string("Local.dll");
336 impl_name = sprefix + std::string("\\") + impl_name;
338 DEBTRACE("impl_name = " << impl_name);
343 size_t length = strlen(impl_name.c_str()) + sizeof(char);
344 wchar_t* aPath = new wchar_t[length + 1];
345 memset(aPath, '\0', length);
346 mbstowcs(aPath, impl_name.c_str(), length);
348 const char* aPath = fullLibName.c_str();
350 handle = dlopen( aPath ) ;
353 handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
358 sError = "Not available here !";
365 if ((sError = dlerror()) || !handle)
368 std::stringstream msg;
369 msg << "Can't load shared library : " << impl_name
370 << " (dlopen error : " << sError << ") at "
371 << __FILE__ << ":" << __LINE__;
372 throw YACS::Exception(msg.str());
375 void *ihandle, *rhandle, *phandle = NULL, *thandle = NULL;
377 ihandle = dlsym(handle, "__init");
381 if (sError = dlerror())
385 std::stringstream msg;
386 msg << "Library " << impl_name
387 << " doesn't contains initialization function (" << sError << ") at "
388 << __FILE__ << ":" << __LINE__;
389 throw YACS::Exception(msg.str());
392 rhandle = dlsym(handle, "__run");
396 if (sError = dlerror())
400 std::stringstream msg;
401 msg << "Library " << impl_name
402 << " doesn't contains main switch function (" << sError << ") at "
403 << __FILE__ << ":" << __LINE__;
404 throw YACS::Exception(msg.str());
407 thandle = dlsym(handle, "__terminate");
411 if (sError = dlerror())
415 std::stringstream msg;
416 msg << "Library " << impl_name
417 << " doesn't contains terminate function (" << sError << ") at "
418 << __FILE__ << ":" << __LINE__;
419 throw YACS::Exception(msg.str());
421 phandle = dlsym(handle, "__ping");
423 _library_map[aCompName] = LocalLibrary(handle, (InitFunction) ihandle,
424 (RunFunction) rhandle,
425 (PingFunction) phandle,
426 (TerminateFunction) thandle);
427 return _library_map[aCompName];
430 void LocalContainer::unLoadComponentLibrary(const std::string & aCompName)
432 std::map<std::string, LocalLibrary >::iterator itLib
433 = _library_map.find(aCompName);
435 if (itLib == _library_map.end()) return;
437 dlclose(itLib->second.handle);
438 _library_map.erase(itLib);