Salome HOME
Addition of MPIComponent
[tools/yacsgen.git] / module_generator / mpi_tmpl.py
1 # Copyright (C) 2009-2015  EDF R&D
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 try:
21   from string import Template
22 except:
23   from compat import Template,set
24
25 # cxx file of a MPI component.
26 # template parameters:
27 #   component : component name
28 #   servicesdef : extra "#include"
29 #   servicesimpl : services implementations
30 cxxCompo="""
31 #include "${component}.hxx"
32 #include <string>
33 #include <unistd.h>
34 #include <signal.h>
35 #include <SALOME_NamingService.hxx>
36 #include <Utils_SALOME_Exception.hxx>
37 #include "Utils_CorbaException.hxx"
38 #include <pthread.h>
39 #include <execinfo.h>
40
41 typedef struct
42 {
43   bool exception;
44   std::string msg;
45 } exception_st;
46
47 //DEFS
48 ${servicesdef}
49 //ENDDEF
50
51
52 using namespace std;
53
54 //! Constructor for component "${component}" instance
55 /*!
56  *
57  */
58 ${component}_i::${component}_i(CORBA::ORB_ptr orb,
59                      PortableServer::POA_ptr poa,
60                      PortableServer::ObjectId * contId,
61                      const char *instanceName,
62                      const char *interfaceName,
63                      bool regist)
64           : Engines_Component_i(orb, poa, contId, instanceName, interfaceName,
65                                 false, regist)
66 {
67   _thisObj = this ;
68   _id = _poa->activate_object(_thisObj);
69 }
70
71 ${component}_i::${component}_i(CORBA::ORB_ptr orb,
72                      PortableServer::POA_ptr poa,
73                      Engines::Container_ptr container,
74                      const char *instanceName,
75                      const char *interfaceName,
76                      bool regist)
77           : Engines_Component_i(orb, poa, container, instanceName, interfaceName,
78                                 false, regist)
79 {
80   _thisObj = this ;
81   _id = _poa->activate_object(_thisObj);
82 }
83
84 //! Destructor for component "${component}" instance
85 ${component}_i::~${component}_i()
86 {
87 }
88
89 ${servicesimpl}
90
91 extern "C"
92 {
93   PortableServer::ObjectId * ${component}Engine_factory( CORBA::ORB_ptr orb,
94                                                     PortableServer::POA_ptr poa,
95                                                     PortableServer::ObjectId * contId,
96                                                     const char *instanceName,
97                                                     const char *interfaceName)
98   {
99     MESSAGE("PortableServer::ObjectId * ${component}Engine_factory()");
100     int is_mpi_container;
101     bool regist;
102     int numproc;
103     
104     MPI_Initialized(&is_mpi_container);
105     if (!is_mpi_container)
106     {
107       int argc = 0;
108       char ** argv = NULL;
109       MPI_Init(&argc, &argv);
110     }
111     
112     MPI_Comm_rank( MPI_COMM_WORLD, &numproc );
113     if( numproc == 0 )
114       regist = true;
115     else
116       regist = false;
117     ${component}_i * myEngine = new ${component}_i(orb, poa, contId, instanceName, interfaceName, regist);
118     return myEngine->getId() ;
119   }
120 }
121 """
122 cxxCompo=Template(cxxCompo)
123
124 # Header file of a MPI component
125 # template parameters:
126 #   component : component name
127 #   module : module name
128 #   compodefs : additional "#include" and other specific declarations
129 #   servicesdef : declaration of component services
130 hxxCompo="""
131 #ifndef _${component}_HXX_
132 #define _${component}_HXX_
133
134 #include <SALOME_Component.hh>
135 #include "Superv_Component_i.hxx"
136 #include "${module}.hh"
137 #include "MPIObject_i.hxx"
138
139 //COMPODEFS
140 ${compodefs}
141 //ENDDEF
142
143 class ${component}_i: public virtual POA_${module}_ORB::${component},
144                       ${inheritedclass}
145                       public virtual MPIObject_i,
146                       public virtual Engines_Component_i
147 {
148   public:
149     ${component}_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa,
150               PortableServer::ObjectId * contId,
151               const char *instanceName, const char *interfaceName,
152               bool regist = true);
153     ${component}_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa,
154               Engines::Container_ptr container,
155               const char *instanceName, const char *interfaceName,
156               bool regist = true);
157     virtual ~${component}_i();
158 ${servicesdef}
159 };
160
161 extern "C"
162 {
163     PortableServer::ObjectId * ${component}Engine_factory( CORBA::ORB_ptr orb,
164                                                       PortableServer::POA_ptr poa,
165                                                       PortableServer::ObjectId * contId,
166                                                       const char *instanceName,
167                                                       const char *interfaceName);
168 }
169 #endif
170
171 """
172 hxxCompo=Template(hxxCompo)
173
174 # Declaration of the thread function to run a MPI service.
175 # template parameters:
176 #   service : name of the service.
177 #   input_vals : declarations of input ports of the service.
178 hxxThreadService="""
179 void * th_${service}(void * s);
180 typedef struct {
181   int ip; // mpi process id
182   Engines::IORTab* tior;
183   ${input_vals}
184 } thread_${service}_struct;
185
186 """
187 hxxThreadService=Template(hxxThreadService)
188
189 # Body of a service.
190 # template parameters:
191 #   module : module name
192 #   component : component name
193 #   service : service name
194 #   out_vals : declaration of output ports ("type1 name1;\ntype2 name2;")
195 #   service_call : 
196 #   in_vals : copy of input ports to thread structure
197 #   parameters : list of parameters ("type1 name1, type2 name2")
198 #   body : user body
199 cxxService="""
200 void * th_${service}(void * s)
201 {
202   std::ostringstream msg;
203   exception_st *est = new exception_st;
204   est->exception = false;
205   
206   thread_${service}_struct *st = (thread_${service}_struct *)s;
207   
208   try
209   {
210     ${out_vals}
211     ${module}_ORB::${component}_var compo = ${module}_ORB::${component}::_narrow((*(st->tior))[st->ip]);
212     compo->${service_call};
213   }
214   catch(const SALOME::SALOME_Exception &ex)
215   {
216     est->exception = true;
217     est->msg = ex.details.text;
218   }
219   catch(const CORBA::Exception &ex)
220   {
221     est->exception = true;
222     msg << "CORBA::Exception: " << ex;
223     est->msg = msg.str();
224   }
225   
226   delete st;
227   return ((void*)est);
228 }
229
230 void ${component}_i::${service}(${parameters})
231 {
232   beginService("${component}_i::${service}");
233   void *ret_th;
234   pthread_t *th;
235   exception_st *est;
236
237   try
238     {
239       // Run the service in every MPI process
240       if(_numproc == 0)
241       {
242         th = new pthread_t[_nbproc];
243         for(int ip=1;ip<_nbproc;ip++)
244         {
245             thread_${service}_struct *st = new thread_${service}_struct;
246             st->ip = ip;
247             st->tior = _tior;
248             ${in_vals}
249             pthread_create(&(th[ip]),NULL,th_${service},(void*)st);
250         }
251       }
252       
253 //BODY
254 ${body}
255 //ENDBODY
256       if(_numproc == 0)
257       {
258         for(int ip=1;ip<_nbproc;ip++)
259         {
260           pthread_join(th[ip],&ret_th);
261           est = (exception_st*)ret_th;
262           if(est->exception)
263           {
264               std::ostringstream msg;
265               msg << "[" << ip << "] " << est->msg;
266               delete est;
267               delete[] th;
268               THROW_SALOME_CORBA_EXCEPTION(msg.str().c_str(),SALOME::INTERNAL_ERROR);
269           }
270           delete est;
271         }
272         delete[] th;
273       }
274     }
275   catch ( const SALOME_Exception & ex)
276     {
277       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
278 /*      SALOME::ExceptionStruct es;
279       es.text=CORBA::string_dup(ex.what());
280       es.type=SALOME::INTERNAL_ERROR;
281       throw SALOME::SALOME_Exception(es);*/
282     }
283   catch ( const SALOME::SALOME_Exception & ex)
284     {
285       throw;
286     }
287   catch ( const std::exception& ex)
288     {
289       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
290 /*      //std::cerr << typeid(ex).name() << std::endl;
291       SALOME::ExceptionStruct es;
292       es.text=CORBA::string_dup(ex.what());
293       es.type=SALOME::INTERNAL_ERROR;
294       throw SALOME::SALOME_Exception(es);*/
295     }
296   catch (...)
297     {
298       THROW_SALOME_CORBA_EXCEPTION("unknown exception", SALOME::INTERNAL_ERROR);
299 /*      std::cerr << "unknown exception" << std::endl;
300       SALOME::ExceptionStruct es;
301       es.text=CORBA::string_dup(" unknown exception");
302       es.type=SALOME::INTERNAL_ERROR;
303       throw SALOME::SALOME_Exception(es);*/
304     }
305   endService("${component}_i::${service}");
306 }
307
308 """
309 cxxService=Template(cxxService)
310
311 interface="""
312   interface ${component}:${inheritedinterface} Engines::MPIObject, Engines::EngineComponent
313   {
314 ${services}
315   };
316 """
317 interface=Template(interface)