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 ComponentInstance *inst) const
78 return NULL != _trueCont;
81 void CppContainer::start(const ComponentInstance *inst) throw (YACS::Exception)
83 _trueCont = LocalContainer::get();
86 Container *CppContainer::clone() const
88 if(_isAttachedOnCloning)
91 return (Container*) (this);
94 return new CppContainer(*this);
97 bool CppContainer::loadComponentLibrary(const std::string & componentName) throw (YACS::Exception)
101 LocalLibrary L = _trueCont->loadComponentLibrary(componentName);
106 std::string mesg = "CppContainer not started";
107 throw YACS::Exception(mesg);
112 CppComponent * CppContainer::createComponentInstance(const std::string & componentName, int /* studyID */)
114 DEBTRACE("CppContainer::createComponentInstance");
116 return _trueCont->createComponentInstance(componentName.c_str());
119 std::string mesg = "CppContainer not started";
120 throw YACS::Exception(mesg);
124 void CppContainer::createInternalInstance(const std::string & name, void *&obj,
125 RunFunction &r, TerminateFunction &t)
127 DEBTRACE("CppContainer::createInternalInstance");
129 _trueCont->createInternalInstance(name.c_str(), obj, r, t);
132 std::string mesg = "CppContainer not started";
133 throw YACS::Exception(mesg);
137 void CppContainer::unregisterComponentInstance(CppComponent * C)
141 _trueCont->unregisterComponentInstance(C);
146 std::string CppContainer::getPlacementId(const ComponentInstance *inst) const
151 std::string CppContainer::getFullPlacementId(const ComponentInstance *inst) const
156 void CppContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception)
158 if(inst->getKind()!=CppComponent::KIND)
159 throw Exception("CppContainer::checkCapabilityToDealWith : CppContainer is not able to deal with this type of ComponentInstance.");
162 std::map<std::string, LocalLibrary> LocalContainer::_library_map; // libraries, loaded
163 std::multimap<std::string, CppComponent *> LocalContainer::_instance_map;
165 LocalContainer * LocalContainer::_singleton = NULL;
167 LocalContainer::LocalContainer()
171 LocalContainer::~LocalContainer()
176 LocalContainer * LocalContainer::get()
178 if (NULL == _singleton)
180 _singleton = new LocalContainer;
185 void LocalContainer::destroy()
187 if (NULL == _singleton)
190 // destroy all component instances
191 _instance_mapMutex.lock(); // lock
192 std::multimap<std::string, CppComponent *>::iterator iI, iJ;
193 for (iI=_instance_map.begin(); iI != _instance_map.end(); iI = iJ)
196 iI->second->setContainer(NULL);
199 _instance_map.clear();
200 _instance_mapMutex.unlock(); // unlock
202 // unload all dynamic libraries
203 _library_mapMutex.lock();
204 std::map<std::string, LocalLibrary>::iterator iL;
205 for (iL=_library_map.begin(); iL != _library_map.end(); iL++)
206 dlclose(iL->second.handle);
207 _library_map.clear();
208 _library_mapMutex.unlock();
215 //=============================================================================
216 //! Find or create a new C++ component instance
218 * Create a new component class (C++ implementation)
219 * \param name : component name
221 * Try to return a handle to an new instance of a C++ component
222 * If the associated library is not loaded, try to load it
224 * \return a handle to the component instance or throw an exception
225 * if it's not possible
227 //=============================================================================
228 CppComponent * LocalContainer::createComponentInstance(const char * name)
234 createInternalInstance(name, o, r, t);
237 C = new CppComponent(o, r, t, name);
238 _instance_mapMutex.lock(); // lock to be alone
239 _instance_map.insert(std::pair<std::string, CppComponent *>(name, C));
240 _instance_mapMutex.unlock(); // unlock
244 void LocalContainer::createInternalInstance(const char *name, void *&obj,
245 RunFunction &r, TerminateFunction &t)
249 std::map<std::string, LocalLibrary>::iterator foundL = _library_map.find(name);
250 if (foundL != _library_map.end())
253 L = loadComponentLibrary(name, NULL, false);
256 InitFunction i = L.initHandle;
257 t = L.terminateHandle;
259 PingFunction p = L.pingHandle;
266 void LocalContainer::unregisterComponentInstance(CppComponent * C)
268 _instance_mapMutex.lock(); // lock to be alone
269 _instance_map.erase(C->getCompoName());
270 _instance_mapMutex.unlock(); // unlock
273 inline void toupper (std::string & s)
275 transform (s.begin (), s.end (), s.begin (), (int(*)(int)) toupper);
278 LocalLibrary LocalContainer::loadComponentLibrary(const std::string & aCompName, const char * prefix, bool forcedLoad)
281 // if forcedLoad is true, unload library if it exists
282 // if forcedLoad is false, return the existing library or load it
285 unLoadComponentLibrary(aCompName);
288 std::map<std::string, LocalLibrary >::iterator itLib
289 = _library_map.find(aCompName);
290 if (itLib != _library_map.end()) return itLib->second;
293 // --- try dlopen C++ component
300 std::string s = aCompName + "_ROOT_DIR";
302 const char * t = getenv(s.c_str());
307 sprefix += "/lib/salome";
312 std::string impl_name = std::string ("lib") + aCompName + std::string("Local.so");
314 impl_name = sprefix + std::string("/") + impl_name;
316 std::string impl_name = aCompName + std::string("Local.dll");
317 impl_name = sprefix + std::string("\\") + impl_name;
319 DEBTRACE("impl_name = " << impl_name);
323 handle = dlopen( impl_name.c_str() ) ;
326 handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
331 sError = "Not available here !";
338 if ((sError = dlerror()) || !handle)
341 std::stringstream msg;
342 msg << "Can't load shared library : " << impl_name
343 << " (dlopen error : " << sError << ") at "
344 << __FILE__ << ":" << __LINE__;
345 throw YACS::Exception(msg.str());
348 void *ihandle, *rhandle, *phandle = NULL, *thandle = NULL;
350 ihandle = dlsym(handle, "__init");
354 if (sError = dlerror())
358 std::stringstream msg;
359 msg << "Library " << impl_name
360 << " doesn't contains initialization function (" << sError << ") at "
361 << __FILE__ << ":" << __LINE__;
362 throw YACS::Exception(msg.str());
365 rhandle = dlsym(handle, "__run");
369 if (sError = dlerror())
373 std::stringstream msg;
374 msg << "Library " << impl_name
375 << " doesn't contains main switch function (" << sError << ") at "
376 << __FILE__ << ":" << __LINE__;
377 throw YACS::Exception(msg.str());
380 thandle = dlsym(handle, "__terminate");
384 if (sError = dlerror())
388 std::stringstream msg;
389 msg << "Library " << impl_name
390 << " doesn't contains terminate function (" << sError << ") at "
391 << __FILE__ << ":" << __LINE__;
392 throw YACS::Exception(msg.str());
394 phandle = dlsym(handle, "__ping");
396 _library_map[aCompName] = LocalLibrary(handle, (InitFunction) ihandle,
397 (RunFunction) rhandle,
398 (PingFunction) phandle,
399 (TerminateFunction) thandle);
400 return _library_map[aCompName];
403 void LocalContainer::unLoadComponentLibrary(const std::string & aCompName)
405 std::map<std::string, LocalLibrary >::iterator itLib
406 = _library_map.find(aCompName);
408 if (itLib == _library_map.end()) return;
410 dlclose(itLib->second.handle);
411 _library_map.erase(itLib);