Version: 9.16.0
CppContainer.cxx
Go to the documentation of this file.
1// Copyright (C) 2006-2026 CEA, EDF
2//
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.
7//
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.
12//
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
16//
17// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18//
19
20#include <iostream>
21#include <sstream>
22#ifdef WIN32
23#include <windows.h>
24#define dlopen LoadLibrary
25#define dlclose FreeLibrary
26#define dlsym GetProcAddress
27#else
28#include <dlfcn.h>
29#endif
30
31#include "CppContainer.hxx"
32#include "CppComponent.hxx"
33#include "Exception.hxx"
34#include <algorithm>
35#include <iostream>
36
37
38using namespace YACS::ENGINE;
39
40char CppContainer::KIND[]="Cpp";
41
42//#define _DEVDEBUG_
43#include "YacsTrace.hxx"
44
45//=============================================================================
49//=============================================================================
50
51CppContainer::CppContainer() : _trueCont(0L)
52{
53 DEBTRACE("CppContainer::CppContainer()");
54}
55
56
57//=============================================================================
61//=============================================================================
62
64{
65 DEBTRACE("CppContainer::~CppContainer()");
66}
67
69{
70 _mutex.lock();
71}
72
74{
75 _mutex.unLock();
76}
77
78std::string CppContainer::getKind() const
79{
80 return KIND;
81}
82
83bool CppContainer::isAlreadyStarted(const Task *askingNode) const
84{
85 return NULL != _trueCont;
86}
87
88void CppContainer::start(const Task *askingNode)
89{
91}
92
94{
95
96}
97
99{
101 {
102 incrRef();
103 return (Container*) (this);
104 }
105 else
106 return new CppContainer(*this);
107}
108
110{
111 return new CppContainer(*this);
112}
113
114bool CppContainer::loadComponentLibrary(const std::string & componentName)
115 {
116 if (_trueCont)
117 {
118 LocalLibrary L = _trueCont->loadComponentLibrary(componentName);
119 return L.good();
120 }
121 else
122 {
123 std::string mesg = "CppContainer not started";
124 throw YACS::Exception(mesg);
125 }
126 return false;
127 }
128
129CppComponent * CppContainer::createComponentInstance(const std::string & componentName)
130{
131 DEBTRACE("CppContainer::createComponentInstance");
132 if (_trueCont)
133 return _trueCont->createComponentInstance(componentName.c_str());
134 else
135 {
136 std::string mesg = "CppContainer not started";
137 throw YACS::Exception(mesg);
138 }
139}
140
141void CppContainer::createInternalInstance(const std::string & name, void *&obj,
143{
144 DEBTRACE("CppContainer::createInternalInstance");
145 if (_trueCont)
146 _trueCont->createInternalInstance(name.c_str(), obj, r, t);
147 else
148 {
149 std::string mesg = "CppContainer not started";
150 throw YACS::Exception(mesg);
151 }
152}
153
155{
156 if (_trueCont)
158}
159
160
161std::string CppContainer::getPlacementId(const Task *askingNode) const
162{
163 return "/";
164}
165
166std::string CppContainer::getFullPlacementId(const Task *askingNode) const
167{
168 return "/";
169}
170
172{
173 if(inst->getKind()!=CppComponent::KIND)
174 throw Exception("CppContainer::checkCapabilityToDealWith : CppContainer is not able to deal with this type of ComponentInstance.");
175}
176
177std::map<std::string, LocalLibrary> LocalContainer::_library_map; // libraries, loaded
178std::multimap<std::string, CppComponent *> LocalContainer::_instance_map;
179
181
183{
184}
185
187{
188 destroy();
189}
190
192{
193 if (NULL == _singleton)
194 {
196 }
197 return _singleton;
198}
199
201{
202 if (NULL == _singleton)
203 return;
204
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)
209 {
210 iJ = iI++;
211 iI->second->setContainer(NULL);
212 delete iI->second;
213 }
214 _instance_map.clear();
215 _instance_mapMutex.unLock(); // unlock
216
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();
224
225 delete _singleton;
226 _singleton = NULL;
227}
228
229
230//=============================================================================
232
242//=============================================================================
244{
245 void *o;
248
249 createInternalInstance(name, o, r, t);
250
251 CppComponent * C;
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
256 return C;
257}
258
259void LocalContainer::createInternalInstance(const char *name, void *&obj,
261{
262 LocalLibrary L;
263
264 std::map<std::string, LocalLibrary>::iterator foundL = _library_map.find(name);
265 if (foundL != _library_map.end())
266 L = foundL->second;
267 else
268 L = loadComponentLibrary(name, NULL, false);
269
270 r = L.runHandle;
272 t = L.terminateHandle;
273
275 if (p) p();
276
277 obj = i();
278
279}
280
282{
283 _instance_mapMutex.lock(); // lock to be alone
284 _instance_map.erase(C->getCompoName());
285 _instance_mapMutex.unLock(); // unlock
286}
287
288inline void toupper (std::string & s)
289{
290 transform (s.begin (), s.end (), s.begin (), (int(*)(int)) toupper);
291}
292
293LocalLibrary LocalContainer::loadComponentLibrary(const std::string & aCompName, const char * prefix, bool forcedLoad)
294{
295
296 // if forcedLoad is true, unload library if it exists
297 // if forcedLoad is false, return the existing library or load it
298
299 if (forcedLoad)
300 unLoadComponentLibrary(aCompName);
301 else
302 {
303 std::map<std::string, LocalLibrary >::iterator itLib
304 = _library_map.find(aCompName);
305 if (itLib != _library_map.end()) return itLib->second;
306 }
307
308 // --- try dlopen C++ component
309
310 std::string sprefix;
311 if (prefix)
312 sprefix = prefix;
313 else
314 {
315 std::string s = aCompName + "_ROOT_DIR";
316 toupper(s);
317 const char * t = getenv(s.c_str());
318 sprefix="";
319 if (t)
320 {
321 sprefix = t;
322 sprefix += "/lib/salome";
323 }
324 }
325
326#ifndef WIN32
327#ifdef __APPLE__
328 std::string impl_name = std::string ("lib") + aCompName + std::string("Local.dylib");
329#else
330 std::string impl_name = std::string ("lib") + aCompName + std::string("Local.so");
331#endif
332 if(sprefix != "")
333 impl_name = sprefix + std::string("/") + impl_name;
334#else
335 std::string impl_name = aCompName + std::string("Local.dll");
336 impl_name = sprefix + std::string("\\") + impl_name;
337#endif
338 DEBTRACE("impl_name = " << impl_name);
339
340#if defined( WIN32 )
341 HMODULE handle;
342#if defined(UNICODE)
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);
347#else
348 const char* aPath = fullLibName.c_str();
349#endif
350 handle = dlopen( aPath ) ;
351#else
352 void* handle;
353 handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
354#endif
355
356 const char * sError;
357#if defined( WIN32 )
358 sError = "Not available here !";
359#endif
360
361#if defined( WIN32 )
362 if (!handle)
363#else
364 sError = dlerror();
365 if ((sError = dlerror()) || !handle)
366#endif
367 {
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());
373 }
374
375 void *ihandle, *rhandle, *phandle = NULL, *thandle = NULL;
376
377 ihandle = dlsym(handle, "__init");
378#if defined( WIN32 )
379 if (!ihandle)
380#else
381 if (sError = dlerror())
382#endif
383 {
384 dlclose(handle);
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());
390 }
391
392 rhandle = dlsym(handle, "__run");
393#if defined( WIN32 )
394 if (!rhandle)
395#else
396 if (sError = dlerror())
397#endif
398 {
399 dlclose(handle);
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());
405 }
406
407 thandle = dlsym(handle, "__terminate");
408#if defined( WIN32 )
409 if (!thandle)
410#else
411 if (sError = dlerror())
412#endif
413 {
414 dlclose(handle);
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());
420 }
421 phandle = dlsym(handle, "__ping");
422
423 _library_map[aCompName] = LocalLibrary(handle, (InitFunction) ihandle,
424 (RunFunction) rhandle,
425 (PingFunction) phandle,
426 (TerminateFunction) thandle);
427 return _library_map[aCompName];
428}
429
430void LocalContainer::unLoadComponentLibrary(const std::string & aCompName)
431{
432 std::map<std::string, LocalLibrary >::iterator itLib
433 = _library_map.find(aCompName);
434
435 if (itLib == _library_map.end()) return;
436
437 dlclose(itLib->second.handle);
438 _library_map.erase(itLib);
439
440}
void toupper(std::string &s)
#define DEBTRACE(msg)
Definition: YacsTrace.hxx:31
Base class for all component instances.
const std::string & getCompoName() const
virtual std::string getKind() const
Return the component kind.
static const char KIND[]
void createInternalInstance(const std::string &componentName, void *&obj, RunFunction &r, TerminateFunction &t)
YACS::ENGINE::Container * clone() const
WARNING ! clone behaviour MUST be in coherence with what is returned by isAttachedOnCloning() method
Container * cloneAlways() const
std::string getFullPlacementId(const Task *askingNode) const
void unregisterComponentInstance(CppComponent *C)
bool loadComponentLibrary(const std::string &componentName)
void checkCapabilityToDealWith(const ComponentInstance *inst) const
std::string getPlacementId(const Task *askingNode) const
std::string getKind() const
CppComponent * createComponentInstance(const std::string &componentName)
void start(const Task *askingNode)
LocalContainer * _trueCont
YACS::BASES::Mutex _mutex
bool isAlreadyStarted(const Task *askingNode) const
static YACS::ENGINE::LocalContainer * get()
void unLoadComponentLibrary(const std::string &aCompName)
LocalLibrary loadComponentLibrary(const std::string &, const char *prefix=NULL, bool forcedLoad=false)
static std::map< std::string, LocalLibrary > _library_map
YACS::BASES::Mutex _instance_mapMutex
void unregisterComponentInstance(CppComponent *C)
static LocalContainer * _singleton
static std::multimap< std::string, CppComponent * > _instance_map
YACS::BASES::Mutex _library_mapMutex
void createInternalInstance(const char *componentName, void *&obj, RunFunction &r, TerminateFunction &t)
CppComponent * createComponentInstance(const char *componentName)
Find or create a new C++ component instance.
Proc * p
Definition: driver.cxx:216
void(* RunFunction)(void *, const char *, int, int, Any **, Any **, returnInfo *)
void(* PingFunction)()
void *(* InitFunction)()
void(* TerminateFunction)(void **)
TerminateFunction terminateHandle