Version: 9.15.0
CppContainer.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2025 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 
38 using namespace YACS::ENGINE;
39 
40 char CppContainer::KIND[]="Cpp";
41 
42 //#define _DEVDEBUG_
43 #include "YacsTrace.hxx"
44 
45 //=============================================================================
49 //=============================================================================
50 
51 CppContainer::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 
78 std::string CppContainer::getKind() const
79 {
80  return KIND;
81 }
82 
83 bool CppContainer::isAlreadyStarted(const Task *askingNode) const
84 {
85  return NULL != _trueCont;
86 }
87 
88 void CppContainer::start(const Task *askingNode)
89 {
91 }
92 
93 void CppContainer::shutdown(int level)
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 
114 bool 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 
129 CppComponent * 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 
141 void 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 
161 std::string CppContainer::getPlacementId(const Task *askingNode) const
162 {
163  return "/";
164 }
165 
166 std::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 
177 std::map<std::string, LocalLibrary> LocalContainer::_library_map; // libraries, loaded
178 std::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;
246  RunFunction r;
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 
259 void 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 
288 inline void toupper (std::string & s)
289 {
290  transform (s.begin (), s.end (), s.begin (), (int(*)(int)) toupper);
291 }
292 
293 LocalLibrary 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 
430 void 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 *(* InitFunction)()
void(* PingFunction)()
void(* TerminateFunction)(void **)
TerminateFunction terminateHandle