source: XIOS/dev/dev_olga/src/object_template_impl.hpp @ 1027

Last change on this file since 1027 was 1025, checked in by mhnguyen, 8 years ago

Merging working version of coupler

+) Add some changes of domain and axis: Retransfer the atttributes in a generic ways for each level of client (or server)
+) Remove some spoiled files from the previous commits

Test
+) No test

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
File size: 19.8 KB
RevLine 
[591]1#ifndef __XIOS_CObjectTemplate_impl__
2#define __XIOS_CObjectTemplate_impl__
[219]3
[591]4#include "xios_spl.hpp"
[327]5#include "context_client.hpp"
[300]6#include "object_factory.hpp"
7#include "context.hpp"
8#include "buffer_in.hpp"
9#include "attribute.hpp"
10#include "event_client.hpp"
[327]11#include "object_template.hpp"
[300]12#include "context_client.hpp"
[327]13#include "indent.hpp"
14#include "type_util.hpp"
15#include "message.hpp"
16#include "type.hpp"
[352]17#include "type_util.hpp"
18#include "group_template.hpp"
[300]19
[335]20namespace xios
[219]21{
22   /// ////////////////////// Définitions ////////////////////// ///
23   template <class T>
24      xios_map<StdString,
25      xios_map<StdString,
26      boost::shared_ptr<T> > > CObjectTemplate<T>::AllMapObj;
27
28   template <class T>
29      xios_map<StdString,
30      std::vector<boost::shared_ptr<T> > > CObjectTemplate<T>::AllVectObj;
31
32   template <class T>
[286]33      xios_map<StdString,long int> CObjectTemplate<T>::GenId;
34
35   template <class T>
[219]36      CObjectTemplate<T>::CObjectTemplate(void)
[345]37         : CAttributeMap()
[219]38         , CObject()
39   { /* Ne rien faire de plus */ }
40
41   template <class T>
42      CObjectTemplate<T>::CObjectTemplate(const StdString & id)
[345]43         : CAttributeMap()
[769]44         , CObject(id, CObjectFactory::IsGenUId<T>(id))
[219]45   { /* Ne rien faire de plus */ }
46
47   template <class T>
48      CObjectTemplate<T>::CObjectTemplate
49         (const CObjectTemplate<T> & object, bool withAttrList, bool withId)
[345]50         : CAttributeMap()
[219]51         , CObject()
52   {
53      if (object.hasId() && withId)
[769]54         this->setId(object.getId(), object.hasAutoGeneratedId());
[219]55      ERROR("CObjectTemplate<T> construtor 3", << "Not completly implemented yet !");
56   }
[509]57
[219]58   template <class T>
59      CObjectTemplate<T>::~CObjectTemplate(void)
60   { /* Ne rien faire de plus */ }
61
62   ///--------------------------------------------------------------
63
64   template <class T>
65      std::vector<boost::shared_ptr<T> > &
66         CObjectTemplate<T>::GetAllVectobject(const StdString & contextId)
[509]67   {
68      return (CObjectTemplate<T>::AllVectObj[contextId]);
[219]69   }
[509]70
[219]71   //---------------------------------------------------------------
[509]72
[219]73   template <class T>
74      StdString CObjectTemplate<T>::toString(void) const
75   {
76      StdOStringStream oss;
77      oss << "<" << T::GetName();
78      if (this->hasId())
79         oss << " id=\"" << this->getId() << "\"";
80      oss << " " << SuperClassMap::toString() << "/>";
81      return (oss.str());
82   }
83
84   template <class T>
85      void CObjectTemplate<T>::fromString(const StdString & str)
[509]86   {
[219]87      ERROR("CObjectTemplate<T>::fromString(str)",
[509]88            << "[ str = " << str << "] Not implemented yet !");
[219]89   }
[509]90
[219]91   //---------------------------------------------------------------
[369]92
[509]93/*
[219]94   template <class T>
95      void CObjectTemplate<T>::toBinary(StdOStream & os) const
96   {
[509]97      SuperClassMap::toBinary(os);
[219]98   }
[509]99
[219]100   template <class T>
101      void CObjectTemplate<T>::fromBinary(StdIStream & is)
102   {
[509]103      SuperClassMap::fromBinary(is);
[219]104   }
[369]105*/
106
[219]107   //---------------------------------------------------------------
108
109   template <class T>
110      void CObjectTemplate<T>::parse(xml::CXMLNode & node)
111   {
112      xml::THashAttributes attributes = node.getAttributes();
113      CAttributeMap::setAttributes(attributes);
114   }
115
116   //---------------------------------------------------------------
117
118   template <class T>
[345]119      ENodeType CObjectTemplate<T>::getType(void) const
[219]120   {
121      return (T::GetType());
122   }
[509]123
[313]124   template <class T>
125   string CObjectTemplate<T>::getName(void) const
126   {
127      return (T::GetName());
128   }
[509]129
[219]130   //---------------------------------------------------------------
131
132   template <class T>
133      bool CObjectTemplate<T>::hasChild(void) const
[509]134   {
135      return (false);
[219]136   }
137
138   //---------------------------------------------------------------
139
140   template <class T>
[445]141      void CObjectTemplate<T>::solveDescInheritance(bool apply, const CAttributeMap * const parent)
[509]142   {
[549]143      if (parent != NULL)
144         SuperClassMap::setAttributes(parent, apply);
[219]145   }
146
147   //---------------------------------------------------------------
148
149   template <class T>
150      void CObjectTemplate<T>::ClearAllAttributes(void)
151   {
[549]152      vector<T*> avect = CObjectTemplate<T>::getAll();
[347]153      typename vector<T*>::iterator
[219]154            it = avect.begin(), end = avect.end();
155
156      for (;it != end; it++)
157      {
158         CAttributeMap & amap = **it;
159         amap.clearAllAttributes();
160      }
161   }
162
[509]163   template<typename T>
[731]164   std::map<int, size_t> CObjectTemplate<T>::getMinimumBufferSizeForAttributes()
165   {
[1021]166     // Use correct context client to send message
[987]167     CContext* context = CContext::getCurrent();
[1009]168     int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
169     for (int i = 0; i < nbSrvPools; ++i)
170     {
171       CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[i] : context->client;
[987]172
[1009]173       std::map<int, size_t> minimumSizes;
[731]174
[1009]175       if (contextClientTmp->isServerLeader())
[731]176       {
[1009]177         size_t minimumSize = 0;
178         CAttributeMap& attrMap = *this;
179         CAttributeMap::const_iterator it = attrMap.begin(), itE = attrMap.end();
180         for (; it != itE; ++it)
[731]181         {
[1009]182           if (!it->second->isEmpty())
183           {
184             size_t size = it->second->getName().size() + sizeof(size_t) + it->second->size();
185             if (size > minimumSize)
186               minimumSize = size;
187           }
[731]188         }
189
[1009]190         if (minimumSize)
191         {
192           // Account for extra header info
193           minimumSize += CEventClient::headerSize + getIdServer().size() + sizeof(size_t);
[731]194
[1009]195           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
196           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
197             minimumSizes.insert(std::make_pair(*itRank, minimumSize));
198         }
[731]199       }
200
[987]201     // if (client->isServerLeader())
202     // {
203     //   size_t minimumSize = 0;
204     //   CAttributeMap& attrMap = *this;
205     //   CAttributeMap::const_iterator it = attrMap.begin(), itE = attrMap.end();
206     //   for (; it != itE; ++it)
207     //   {
208     //     if (!it->second->isEmpty())
209     //     {
210     //       size_t size = it->second->getName().size() + sizeof(size_t) + it->second->size();
211     //       if (size > minimumSize)
212     //         minimumSize = size;
213     //     }
214     //   }
215
216     //   if (minimumSize)
217     //   {
218     //     // Account for extra header info
219     //     minimumSize += CEventClient::headerSize + getIdServer().size() + sizeof(size_t);
220
221     //     const std::list<int>& ranks = client->getRanksServerLeader();
222     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
223     //       minimumSizes.insert(std::make_pair(*itRank, minimumSize));
224     //   }
225     // }
226
[1009]227       return minimumSizes;
228     }
[731]229   }
230
231   template<typename T>
[509]232   void CObjectTemplate<T>::sendAllAttributesToServer()
233   {
234     CAttributeMap& attrMap = *this;
235     CAttributeMap::const_iterator it = attrMap.begin(), itE = attrMap.end();
236     for (; it != itE; ++it)
237     {
238       if (!(it->second)->isEmpty()) sendAttributToServer(*(it->second));
239     }
240   }
241
[1009]242   template<typename T>
[1021]243   void CObjectTemplate<T>::sendAllAttributesToServer(CContextClient* client)
[1009]244   {
245     CAttributeMap& attrMap = *this;
246     CAttributeMap::const_iterator it = attrMap.begin(), itE = attrMap.end();
247     for (; it != itE; ++it)
248     {
[1021]249       if (!(it->second)->isEmpty()) sendAttributToServer(*(it->second), client);
[1009]250     }
251   }
252
[300]253   template <class T>
254   void CObjectTemplate<T>::sendAttributToServer(const string& id)
255   {
256      CAttributeMap & attrMap = *this;
[549]257      CAttribute* attr=attrMap[id];
[1025]258      if (attr->doSend()) 
259        sendAttributToServer(*attr);
[300]260   }
[219]261
[1009]262   template <class T>
[1021]263   void CObjectTemplate<T>::sendAttributToServer(const string& id, CContextClient* client)
[1009]264   {
265      CAttributeMap & attrMap = *this;
266      CAttribute* attr=attrMap[id];
[1021]267      sendAttributToServer(*attr, client);
[1009]268   }
269
[347]270  template <class T>
271  void CObjectTemplate<T>::sendAttributToServer(CAttribute& attr)
272  {
[1021]273     // Use correct context client to send message
[549]274    CContext* context=CContext::getCurrent();
[987]275    if (context->hasClient)
[300]276    {
[1009]277      int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
278      for (int i = 0; i < nbSrvPools; ++i)
279      {
280        CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[i] : context->client;
281        CEventClient event(getType(),EVENT_ID_SEND_ATTRIBUTE);
282        if (contextClientTmp->isServerLeader())
283        {
284          CMessage msg;
[1021]285          msg<<this->getIdServer();
[1009]286          msg << attr.getName();
287          msg << attr;
288          const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
289          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
290            event.push(*itRank,1,msg);
291          contextClientTmp->sendEvent(event);
292        }
293        else contextClientTmp->sendEvent(event);
294      }
[300]295    }
[987]296//     // if (!context->hasServer)
297//     if (context->hasClient)
298//     {
299//        CContextClient* client=context->client;
300
301//        CEventClient event(getType(),EVENT_ID_SEND_ATTRIBUTE);
302//        if (client->isServerLeader())
303//        {
304//          CMessage msg;
305// //       msg << this->getId();
306//          msg << this->getIdServer();
307//          msg << attr.getName();
308//          msg << attr;
309//          const std::list<int>& ranks = client->getRanksServerLeader();
310//          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
311//            event.push(*itRank,1,msg);
312//          client->sendEvent(event);
313//        }
314//        else client->sendEvent(event);
315//     }
316
[347]317  }
[509]318
[1009]319  template <class T>
[1021]320  void CObjectTemplate<T>::sendAttributToServer(CAttribute& attr, CContextClient* client)
[1009]321  {
322    CEventClient event(getType(),EVENT_ID_SEND_ATTRIBUTE);
[1021]323    if (client->isServerLeader())
[1009]324    {
325      CMessage msg;
326      msg<<this->getIdServer();
327      msg << attr.getName();
328      msg << attr;
[1021]329      const std::list<int>& ranks = client->getRanksServerLeader();
[1009]330      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
331        event.push(*itRank,1,msg);
[1021]332      client->sendEvent(event);
[1009]333    }
[1021]334    else client->sendEvent(event);
[1009]335  }
336
[987]337  /*!
338    This generic funtion only provides instance for sending, for receving, each
339    child class must define itself.
340    \param [in] id Id of added item
341    \param [in] itemType type of added item
342  */
343  template<class T>
344  void CObjectTemplate<T>::sendAddItem(const StdString& id, int itemType)
345  {
346    CContext* context = CContext::getCurrent();
347    typedef typename T::EEventId ItemType;
348    if (context->hasClient)
349    {
[1021]350      // Use correct context client to send message
[1009]351      int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
352      for (int i = 0; i < nbSrvPools; ++i)
353      {
354         CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[i] : context->client;
355         CEventClient event(this->getType(),ItemType(itemType));
356         if (contextClientTmp->isServerLeader())
357         {
358           CMessage msg;
359           msg << this->getId();
360           msg << id;
361           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
362           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
363             event.push(*itRank,1,msg);
364           contextClientTmp->sendEvent(event);
365         }
366         else contextClientTmp->sendEvent(event);
367      }
[987]368    }
369  }
370
[1009]371  template<class T>
[1021]372  void CObjectTemplate<T>::sendAddItem(const StdString& id, int itemType, CContextClient* client)
[1009]373  {
374    typedef typename T::EEventId ItemType;
375     CEventClient event(this->getType(),ItemType(itemType));
[1021]376     if (client->isServerLeader())
[1009]377     {
378       CMessage msg;
379       msg << this->getId();
380       msg << id;
[1021]381       const std::list<int>& ranks = client->getRanksServerLeader();
[1009]382       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
383         event.push(*itRank,1,msg);
[1021]384       client->sendEvent(event);
[1009]385     }
[1021]386     else client->sendEvent(event);
[1009]387  }
388
[1021]389
[347]390  template <class T>
391  void CObjectTemplate<T>::recvAttributFromClient(CEventServer& event)
392  {
[509]393
[347]394    CBufferIn* buffer=event.subEvents.begin()->buffer;
395    string id,attrId;
[549]396    *buffer>>id;
[347]397    CAttributeMap & attrMap = *get(id);
[549]398    *buffer>>attrId;
399    CAttribute* attr=attrMap[attrId];
[581]400    info(50) << "attribut recu " << attrId << "  ";
401    if (attr->isEmpty()) info(50) << "--> empty" << endl;
402    else info(50) /*<attr->getValue()*/ << endl;
[549]403    *buffer>>*attr;
[581]404     info(50) << "attribut recu " << attrId << "  ";
405    if (attr->isEmpty()) info(50) << "--> empty" << endl;
406    else info(50) /*attr->getValue()*/ << endl;
[300]407  }
408
409   template <class T>
410   bool CObjectTemplate<T>::dispatchEvent(CEventServer& event)
411   {
412      switch(event.type)
413      {
414         case EVENT_ID_SEND_ATTRIBUTE :
[549]415           recvAttributFromClient(event);
416           return true;
417           break;
[509]418
[300]419         default :
[549]420         return false;
[581]421//           ERROR("void CObjectTemplate<T>::recvEvent(CEventServer& event)", << "Unknown Event");
[300]422      }
423   }
[509]424
[300]425   template <typename T>
426   bool CObjectTemplate<T>::has(const string & id)
427   {
[549]428     return CObjectFactory::HasObject<T>(id);
[300]429   }
430
431   template <typename T>
[346]432   bool CObjectTemplate<T>::has(const string& contextId, const string & id)
433   {
[549]434     return CObjectFactory::HasObject<T>(contextId,id);
[346]435   }
436
437   template <typename T>
[347]438   T* CObjectTemplate<T>::get(const string & id)
[300]439   {
[549]440     return CObjectFactory::GetObject<T>(id).get();
[300]441   }
442
443   template <typename T>
[347]444   T* CObjectTemplate<T>::get(const T* ptr)
[346]445   {
[549]446     return CObjectFactory::GetObject<T>(ptr).get();
[347]447   }
[509]448
[347]449   template <typename T>
450   shared_ptr<T> CObjectTemplate<T>::getShared(const T* ptr)
451   {
[549]452     return CObjectFactory::GetObject<T>(ptr);
[346]453   }
[347]454
455   template <typename T>
456   shared_ptr<T> CObjectTemplate<T>::getShared(void)
457   {
[549]458     return CObjectFactory::GetObject<T>((T*)this);
[347]459   }
[509]460
[346]461   template <typename T>
[347]462   const vector<T*> CObjectTemplate<T>::getAll()
[346]463   {
[347]464     const vector< shared_ptr<T> >& shared_vect= CObjectFactory::GetObjectVector<T>();
[549]465     vector<T*> vect;
[509]466
[347]467     typename vector<shared_ptr<T> >::const_iterator it;
[549]468     for(it=shared_vect.begin();it!=shared_vect.end();++it) vect.push_back(it->get());
469     return vect;
[346]470   }
471
472   template <typename T>
[347]473   const vector<T*> CObjectTemplate<T>::getAll(const string & id)
[346]474   {
[347]475     const vector< shared_ptr<T> >& shared_vect= CObjectFactory::GetObjectVector<T>(id);
[549]476     vector<T*> vect;
[509]477
[347]478     typename vector<shared_ptr<T> >::const_iterator it;
[549]479     for(it=shared_vect.begin();it!=shared_vect.end();++it) vect.push_back(it->get());
480     return vect;
[346]481   }
482
483   template <typename T>
[347]484   T* CObjectTemplate<T>::get(const string& contextId, const string & id)
[346]485   {
[549]486     return CObjectFactory::GetObject<T>(contextId,id).get();
[346]487   }
488
489   template <typename T>
[347]490   T* CObjectTemplate<T>::create(const string & id)
[300]491   {
[549]492     return CObjectFactory::CreateObject<T>(id).get();
[300]493   }   ///--------------------------------------------------------------
494
495  template <typename T>
[347]496  T* CObjectTemplate<T>::get(void)
[300]497  {
[549]498    return CObjectFactory::GetObject<T>((T*)this).get();
[300]499  }
[509]500
[313]501   template <typename T>
502   void CObjectTemplate<T>::generateCInterface(ostream& oss)
503   {
[549]504     string className=getName();
505     int found=className.rfind("_group");
506     if (found!=string::npos) className.replace(found,1,0,'x');
[509]507
[581]508     oss << "/* ************************************************************************** *" << iendl;
509     oss << " *               Interface auto generated - do not modify                     *" << iendl;
510     oss << " * ************************************************************************** */" << iendl;
511     oss << iendl;
512     oss << "#include <boost/multi_array.hpp>" << iendl;
513     oss << "#include <boost/shared_ptr.hpp>" << iendl;
[591]514     oss << "#include \"xios.hpp\"" << iendl;
[581]515     oss << "#include \"attribute_template.hpp\"" << iendl;
516     oss << "#include \"object_template.hpp\"" << iendl;
517     oss << "#include \"group_template.hpp\"" << iendl;
518     oss << "#include \"icutil.hpp\"" << iendl;
519     oss << "#include \"icdate.hpp\"" << iendl;
520     oss << "#include \"timer.hpp\"" << iendl;
521     oss << "#include \"node_type.hpp\"" << iendl;
522     oss << iendl;
523     oss << "extern \"C\"" << iendl;
524     oss << "{" << iendl++;
525     oss << "typedef xios::" << getStrType<T>() << "* " << className << "_Ptr;";
[549]526     SuperClassMap::generateCInterface(oss,className);
[581]527     oss << "}" << iendl--;
[313]528   }
[300]529
[313]530   template <typename T>
531   void CObjectTemplate<T>::generateFortran2003Interface(ostream& oss)
532   {
[549]533     string className=getName();
534     int found=className.rfind("_group");
535     if (found!=string::npos) className.replace(found,1,0,'x');
[509]536
[581]537     oss << "! * ************************************************************************** *" << iendl;
538     oss << "! *               Interface auto generated - do not modify                     *" << iendl;
539     oss << "! * ************************************************************************** *" << iendl;
540     oss << "#include \"../fortran/xios_fortran_prefix.hpp\"" << iendl;
541     oss << iendl;
542     oss << "MODULE " << className << "_interface_attr" << iendl++;
543     oss << "USE, INTRINSIC :: ISO_C_BINDING" << std::endl;
544     oss << iendl;
545     oss << "INTERFACE" << iendl++;
546     oss << "! Do not call directly / interface FORTRAN 2003 <-> C99";
[549]547     SuperClassMap::generateFortran2003Interface(oss,className);
[581]548     oss << iendl--;
549     oss << "END INTERFACE" << iendl--;
550     oss << iendl;
551     oss << "END MODULE " << className << "_interface_attr" << iendl;
[313]552   }
[509]553
[313]554   template <typename T>
555   void CObjectTemplate<T>::generateFortranInterface(ostream& oss)
556   {
[549]557     string className=getName();
558     int found=className.rfind("_group");
559     if (found!=string::npos) className.erase(found,1);
[313]560     string superClassName=getName();
[549]561     found=superClassName.find("_group");
562     if (found!=string::npos) superClassName.erase(found,6);
[509]563
[581]564     oss << "! * ************************************************************************** *" << iendl;
565     oss << "! *               Interface auto generated - do not modify                     *" << iendl;
566     oss << "! * ************************************************************************** *" << iendl;
567     oss << "#include \"xios_fortran_prefix.hpp\"" << iendl;
568     oss << iendl;
569     oss << "MODULE i" << className << "_attr" << iendl++;
570     oss << "USE, INTRINSIC :: ISO_C_BINDING" << iendl;
571     oss << "USE i" << superClassName << iendl;
572     oss << "USE " << className << "_interface_attr" << iendl--;
573//   oss << "TYPE txios(" << className << ")" << iendl;
574//   oss << "  INTEGER(kind = C_INTPTR_T) :: daddr" << iendl;
575//   oss << "END TYPE txios(" << className << ")" << iendl;
576     oss << iendl;
577     oss << "CONTAINS" << iendl;
578     oss << iendl++;
[549]579     SuperClassMap::generateFortranInterface_id(oss,className);
[581]580     oss << iendl;
[549]581     SuperClassMap::generateFortranInterface_hdl(oss,className);
[581]582     oss << iendl;
[549]583     SuperClassMap::generateFortranInterface_hdl_(oss,className);
[581]584     oss << iendl;
[549]585     SuperClassMap::generateFortranInterfaceGet_id(oss,className);
[581]586     oss << iendl;
[549]587     SuperClassMap::generateFortranInterfaceGet_hdl(oss,className);
[581]588     oss << iendl;
[549]589     SuperClassMap::generateFortranInterfaceGet_hdl_(oss,className);
[581]590     oss << iendl;
[549]591     SuperClassMap::generateFortranInterfaceIsDefined_id(oss,className);
[581]592     oss << iendl;
[549]593     SuperClassMap::generateFortranInterfaceIsDefined_hdl(oss,className);
[581]594     oss << iendl;
[549]595     SuperClassMap::generateFortranInterfaceIsDefined_hdl_(oss,className);
[581]596     oss << iendl--;
597     oss << "END MODULE i" << className << "_attr" << iendl;
[313]598   }
[335]599} // namespace xios
[219]600
[591]601#endif // __XIOS_CObjectTemplate_impl__
Note: See TracBrowser for help on using the repository browser.