1 // Copyright (C) 2006-2008 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.
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
23 #include "CppContainer.hxx"
24 #include "CppComponent.hxx"
25 #include "Exception.hxx"
30 using namespace YACS::ENGINE;
33 #include "YacsTrace.hxx"
35 //=============================================================================
37 * Local C++ container class constructor
39 //=============================================================================
41 CppContainer::CppContainer() : _trueCont(0L)
43 DEBTRACE("CppContainer::CppContainer()");
47 //=============================================================================
49 * Local C++ container class destructor
51 //=============================================================================
53 CppContainer::~CppContainer()
55 DEBTRACE("CppContainer::~CppContainer()");
58 void CppContainer::lock()
63 void CppContainer::unLock()
68 bool CppContainer::isAlreadyStarted() const
70 return NULL != _trueCont;
73 void CppContainer::start() throw (YACS::Exception)
75 _trueCont = LocalContainer::get();
78 Container *CppContainer::clone() const
80 if(_isAttachedOnCloning)
83 return (Container*) (this);
86 return new CppContainer(*this);
89 bool CppContainer::loadComponentLibrary(const std::string & componentName) throw (YACS::Exception)
93 LocalLibrary L = _trueCont->loadComponentLibrary(componentName);
98 std::string mesg = "CppContainer not started";
99 throw YACS::Exception(mesg);
104 CppComponent * CppContainer::createComponentInstance(const std::string & componentName, int /* studyID */)
106 DEBTRACE("CppContainer::createComponentInstance");
108 return _trueCont->createComponentInstance(componentName.c_str());
111 std::string mesg = "CppContainer not started";
112 throw YACS::Exception(mesg);
116 void CppContainer::createInternalInstance(const std::string & name, void *&obj,
117 RunFunction &r, TerminateFunction &t)
119 DEBTRACE("CppContainer::createInternalInstance");
121 _trueCont->createInternalInstance(name.c_str(), obj, r, t);
124 std::string mesg = "CppContainer not started";
125 throw YACS::Exception(mesg);
129 void CppContainer::unregisterComponentInstance(CppComponent * C)
133 _trueCont->unregisterComponentInstance(C);
138 std::string CppContainer::getPlacementId() const
143 void CppContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw (Exception)
145 if(inst->getKind()!=CppComponent::KIND)
146 throw Exception("CppContainer::checkCapabilityToDealWith : CppContainer is not able to deal with this type of ComponentInstance.");
149 std::map<std::string, LocalLibrary> LocalContainer::_library_map; // libraries, loaded
150 std::multimap<std::string, CppComponent *> LocalContainer::_instance_map;
152 LocalContainer * LocalContainer::_singleton = NULL;
154 LocalContainer::LocalContainer()
158 LocalContainer::~LocalContainer()
163 LocalContainer * LocalContainer::get()
165 if (NULL == _singleton)
167 _singleton = new LocalContainer;
172 void LocalContainer::destroy()
174 if (NULL == _singleton)
177 // destroy all component instances
178 _instance_mapMutex.lock(); // lock
179 std::multimap<std::string, CppComponent *>::iterator iI, iJ;
180 for (iI=_instance_map.begin(); iI != _instance_map.end(); iI = iJ)
183 iI->second->setContainer(NULL);
186 _instance_map.clear();
187 _instance_mapMutex.unlock(); // unlock
189 // unload all dynamic libraries
190 _library_mapMutex.lock();
191 std::map<std::string, LocalLibrary>::iterator iL;
192 for (iL=_library_map.begin(); iL != _library_map.end(); iL++)
193 dlclose(iL->second.handle);
194 _library_map.clear();
195 _library_mapMutex.unlock();
202 //=============================================================================
203 //! Find or create a new C++ component instance
205 * Create a new component class (C++ implementation)
206 * \param name : component name
208 * Try to return a handle to an new instance of a C++ component
209 * If the associated library is not loaded, try to load it
211 * \return a handle to the component instance or throw an exception
212 * if it's not possible
214 //=============================================================================
215 CppComponent * LocalContainer::createComponentInstance(const char * name)
221 createInternalInstance(name, o, r, t);
224 C = new CppComponent(o, r, t, name);
225 _instance_mapMutex.lock(); // lock to be alone
226 _instance_map.insert(std::pair<std::string, CppComponent *>(name, C));
227 _instance_mapMutex.unlock(); // unlock
231 void LocalContainer::createInternalInstance(const char *name, void *&obj,
232 RunFunction &r, TerminateFunction &t)
236 std::map<std::string, LocalLibrary>::iterator foundL = _library_map.find(name);
237 if (foundL != _library_map.end())
240 L = loadComponentLibrary(name, NULL, false);
243 InitFunction i = L.initHandle;
244 t = L.terminateHandle;
246 PingFunction p = L.pingHandle;
253 void LocalContainer::unregisterComponentInstance(CppComponent * C)
255 _instance_mapMutex.lock(); // lock to be alone
256 _instance_map.erase(C->getCompoName());
257 _instance_mapMutex.unlock(); // unlock
260 inline void toupper (std::string & s)
262 transform (s.begin (), s.end (), s.begin (), (int(*)(int)) toupper);
265 LocalLibrary LocalContainer::loadComponentLibrary(const std::string & aCompName, const char * prefix, bool forcedLoad)
268 // if forcedLoad is true, unload library if it exists
269 // if forcedLoad is false, return the existing library or load it
272 unLoadComponentLibrary(aCompName);
275 std::map<std::string, LocalLibrary >::iterator itLib
276 = _library_map.find(aCompName);
277 if (itLib != _library_map.end()) return itLib->second;
280 // --- try dlopen C++ component
287 std::string s = aCompName + "_ROOT_DIR";
289 const char * t = getenv(s.c_str());
294 sprefix += "/lib/salome";
299 std::string impl_name = std::string ("lib") + aCompName + std::string("Local.so");
301 impl_name = sprefix + std::string("/") + impl_name;
303 std::string impl_name = aCompName + std::string("Local.dll");
304 impl_name = sprefix + std::string("\\") + impl_name;
306 DEBTRACE("impl_name = " << impl_name);
310 handle = dlopen( impl_name.c_str() , 0 ) ;
312 handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
318 if ((sError = dlerror()) || !handle)
320 std::stringstream msg;
321 msg << "Can't load shared library : " << impl_name
322 << " (dlopen error : " << sError << ") at "
323 << __FILE__ << ":" << __LINE__;
324 throw YACS::Exception(msg.str());
327 void *ihandle, *rhandle, *phandle = NULL, *thandle = NULL;
329 ihandle = dlsym(handle, "__init");
330 if (sError = dlerror())
333 std::stringstream msg;
334 msg << "Library " << impl_name
335 << " doesn't contains initialization function (" << sError << ") at "
336 << __FILE__ << ":" << __LINE__;
337 throw YACS::Exception(msg.str());
340 rhandle = dlsym(handle, "__run");
341 if (sError = dlerror())
344 std::stringstream msg;
345 msg << "Library " << impl_name
346 << " doesn't contains main switch function (" << sError << ") at "
347 << __FILE__ << ":" << __LINE__;
348 throw YACS::Exception(msg.str());
351 thandle = dlsym(handle, "__terminate");
352 if (sError = dlerror())
355 std::stringstream msg;
356 msg << "Library " << impl_name
357 << " doesn't contains terminate function (" << sError << ") at "
358 << __FILE__ << ":" << __LINE__;
359 throw YACS::Exception(msg.str());
361 phandle = dlsym(handle, "__ping");
363 _library_map[aCompName] = LocalLibrary(handle, (InitFunction) ihandle,
364 (RunFunction) rhandle,
365 (PingFunction) phandle,
366 (TerminateFunction) thandle);
367 return _library_map[aCompName];
370 void LocalContainer::unLoadComponentLibrary(const std::string & aCompName)
372 std::map<std::string, LocalLibrary >::iterator itLib
373 = _library_map.find(aCompName);
375 if (itLib == _library_map.end()) return;
377 dlclose(itLib->second.handle);
378 _library_map.erase(itLib);