Salome HOME
Copyright update 2022
[tools/yacsgen.git] / module_generator / mpi_tmpl.py
1 # Copyright (C) 2009-2022  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 module_generator.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     regist = ( numproc == 0 );
114     ${component}_i * myEngine = new ${component}_i(orb, poa, contId, instanceName, interfaceName, regist);
115     return myEngine->getId() ;
116   }
117 }
118 """
119 cxxCompo=Template(cxxCompo)
120
121 # Header file of a MPI component
122 # template parameters:
123 #   component : component name
124 #   module : module name
125 #   compodefs : additional "#include" and other specific declarations
126 #   servicesdef : declaration of component services
127 hxxCompo="""
128 #ifndef _${component}_HXX_
129 #define _${component}_HXX_
130
131 #include <SALOME_Component.hh>
132 #include "Superv_Component_i.hxx"
133 #include "${module}.hh"
134 #include "MPIObject_i.hxx"
135
136 //COMPODEFS
137 ${compodefs}
138 //ENDDEF
139
140 class ${component}_i: public virtual POA_${module}_ORB::${component},
141                       ${inheritedclass}
142                       public virtual MPIObject_i,
143                       public virtual Engines_Component_i
144 {
145   public:
146     ${component}_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa,
147               PortableServer::ObjectId * contId,
148               const char *instanceName, const char *interfaceName,
149               bool regist = true);
150     ${component}_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa,
151               Engines::Container_ptr container,
152               const char *instanceName, const char *interfaceName,
153               bool regist = true);
154     virtual ~${component}_i();
155 ${servicesdef}
156 };
157
158 extern "C"
159 {
160     PortableServer::ObjectId * ${component}Engine_factory( CORBA::ORB_ptr orb,
161                                                       PortableServer::POA_ptr poa,
162                                                       PortableServer::ObjectId * contId,
163                                                       const char *instanceName,
164                                                       const char *interfaceName);
165 }
166 #endif
167
168 """
169 hxxCompo=Template(hxxCompo)
170
171 # Declaration of the thread function to run a MPI service.
172 # template parameters:
173 #   service : name of the service.
174 #   input_vals : declarations of input ports of the service.
175 hxxThreadService="""
176 void * th_${service}(void * s);
177 typedef struct {
178   int ip; // mpi process id
179   Engines::IORTab* tior;
180   ${input_vals}
181 } thread_${service}_struct;
182
183 """
184 hxxThreadService=Template(hxxThreadService)
185
186 # Body of a service.
187 # template parameters:
188 #   module : module name
189 #   component : component name
190 #   service : service name
191 #   out_vals : declaration of output ports ("type1 name1;\ntype2 name2;")
192 #   service_call : 
193 #   in_vals : copy of input ports to thread structure
194 #   parameters : list of parameters ("type1 name1, type2 name2")
195 #   body : user body
196 cxxService="""
197 void * th_${service}(void * s)
198 {
199   std::ostringstream msg;
200   exception_st *est = new exception_st;
201   est->exception = false;
202   
203   thread_${service}_struct *st = (thread_${service}_struct *)s;
204   
205   try
206   {
207     ${out_vals}
208     ${module}_ORB::${component}_var compo = ${module}_ORB::${component}::_narrow((*(st->tior))[st->ip]);
209     compo->${service_call};
210   }
211   catch(const SALOME::SALOME_Exception &ex)
212   {
213     est->exception = true;
214     est->msg = ex.details.text;
215   }
216   catch(const CORBA::Exception &ex)
217   {
218     est->exception = true;
219     msg << "CORBA::Exception: " << ex;
220     est->msg = msg.str();
221   }
222   
223   delete st;
224   return ((void*)est);
225 }
226
227 void ${component}_i::${service}(${parameters})
228 {
229   beginService("${component}_i::${service}");
230   void *ret_th;
231   pthread_t *th;
232   exception_st *est;
233
234   try
235     {
236       // Run the service in every MPI process
237       if(_numproc == 0)
238       {
239         th = new pthread_t[_nbproc];
240         for(int ip=1;ip<_nbproc;ip++)
241         {
242             thread_${service}_struct *st = new thread_${service}_struct;
243             st->ip = ip;
244             st->tior = _tior;
245             ${in_vals}
246             pthread_create(&(th[ip]),NULL,th_${service},(void*)st);
247         }
248       }
249       
250 //BODY
251 ${body}
252 //ENDBODY
253       if(_numproc == 0)
254       {
255         for(int ip=1;ip<_nbproc;ip++)
256         {
257           pthread_join(th[ip],&ret_th);
258           est = (exception_st*)ret_th;
259           if(est->exception)
260           {
261               std::ostringstream msg;
262               msg << "[" << ip << "] " << est->msg;
263               delete est;
264               delete[] th;
265               THROW_SALOME_CORBA_EXCEPTION(msg.str().c_str(),SALOME::INTERNAL_ERROR);
266           }
267           delete est;
268         }
269         delete[] th;
270       }
271     }
272   catch ( const SALOME_Exception & ex)
273     {
274       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
275     }
276   catch ( const SALOME::SALOME_Exception & ex)
277     {
278       throw;
279     }
280   catch ( const std::exception& ex)
281     {
282       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
283     }
284   catch (...)
285     {
286       THROW_SALOME_CORBA_EXCEPTION("unknown exception", SALOME::INTERNAL_ERROR);
287     }
288   endService("${component}_i::${service}");
289 }
290
291 """
292 cxxService=Template(cxxService)
293
294 interface="""
295   interface ${component}:${inheritedinterface} Engines::MPIObject, Engines::EngineComponent
296   {
297 ${services}
298   };
299 """
300 interface=Template(interface)