1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 /****************************************************************************/
4 /*                                                                          */
5 /* File:      objmgr.c                                                      */
6 /*                                                                          */
7 /* Purpose:   creation and deletion of objects                              */
8 /*                                                                          */
9 /* Author:    Klaus Birken                                                  */
10 /*            Rechenzentrum Uni Stuttgart                                   */
11 /*            Universitaet Stuttgart                                        */
12 /*            Allmandring 30                                                */
13 /*            70550 Stuttgart                                               */
14 /*            internet: birken@rus.uni-stuttgart.de                         */
15 /*                                                                          */
16 /* History:   94/02/21 kb  begin                                            */
17 /*            95/11/03 kb  complete redesign of objmgr-interface, C++ style */
18 /*            95/11/15 kb  arbitrary offset for DDD_HEADER                  */
19 /*                                                                          */
20 /* Remarks:                                                                 */
21 /*                                                                          */
22 /****************************************************************************/
23 
24 /****************************************************************************/
25 /*                                                                          */
26 /* include files                                                            */
27 /*            system include files                                          */
28 /*            application include files                                     */
29 /*                                                                          */
30 /****************************************************************************/
31 
32 /* standard C library */
33 #include <config.h>
34 #include <cstdlib>
35 #include <cstdio>
36 #include <cstring>
37 #include <cassert>
38 
39 #include <algorithm>
40 
41 #include <dune/common/exceptions.hh>
42 #include <dune/common/stdstreams.hh>
43 
44 #include <dune/uggrid/parallel/ddd/dddi.h>
45 
46 USING_UG_NAMESPACES
47 
48 /* PPIF namespace: */
49 using namespace PPIF;
50 
51 START_UGDIM_NAMESPACE
52 
53 /*
54    #define DebugCreation
55    #define DebugDeletion
56  */
57 
58 
59 /****************************************************************************/
60 /*                                                                          */
61 /* defines in the following order                                           */
62 /*                                                                          */
63 /*        compile time constants defining static data size (i.e. arrays)    */
64 /*        other constants                                                   */
65 /*        macros                                                            */
66 /*                                                                          */
67 /****************************************************************************/
68 
69 
70 #define MakeUnique(context, n)  (((n)<<MAX_PROCBITS_IN_GID)+(context).me())
71 #define ProcFromId(n)  ((n)& ((1<<MAX_PROCBITS_IN_GID)-1))
72 #define CountFromId(n) (((n)-((n)& ((1<<MAX_PROCBITS_IN_GID)-1)))>>MAX_PROCBITS_IN_GID)
73 
74 
75 
76 
77 /****************************************************************************/
78 /*                                                                          */
79 /* routines                                                                 */
80 /*                                                                          */
81 /****************************************************************************/
82 
83 
84 
sort_ObjListGID(const DDD_HDR & a,const DDD_HDR & b)85 static bool sort_ObjListGID (const DDD_HDR& a, const DDD_HDR& b)
86 {
87   return OBJ_GID(a) < OBJ_GID(b);
88 }
89 
90 
LocalObjectsList(const DDD::DDDContext & context)91 std::vector<DDD_HDR> LocalObjectsList(const DDD::DDDContext& context)
92 {
93   const int nObjs = context.nObjs();
94   std::vector<DDD_HDR> locObjs(nObjs);
95 
96   const auto& objTable = context.objTable();
97   std::copy(objTable.begin(), objTable.begin() + nObjs, locObjs.begin());
98   std::sort(locObjs.begin(), locObjs.end(), sort_ObjListGID);
99 
100   return locObjs;
101 }
102 
103 
LocalCoupledObjectsList(const DDD::DDDContext & context)104 std::vector<DDD_HDR> LocalCoupledObjectsList(const DDD::DDDContext& context)
105 {
106   const auto& nCpls = context.couplingContext().nCpls;
107   std::vector<DDD_HDR> locObjs(nCpls);
108 
109   const auto& objTable = context.objTable();
110   std::copy(objTable.begin(), objTable.begin() + nCpls, locObjs.begin());
111   std::sort(locObjs.begin(), locObjs.end(), sort_ObjListGID);
112 
113   return locObjs;
114 }
115 
116 
117 /****************************************************************************/
118 
119 
ddd_EnsureObjTabSize(DDD::DDDContext & context,int n)120 void ddd_EnsureObjTabSize(DDD::DDDContext& context, int n)
121 {
122   auto& objTable = context.objTable();
123 
124   /* if size is large enough, we are already finished. */
125   if (objTable.size() >= n)
126     return;
127 
128   objTable.resize(n);
129 
130   /* issue a warning in order to inform user */
131   Dune::dwarn << "increased object table, now " << n << " entries\n";
132 }
133 
134 
135 /****************************************************************************/
136 
137 /*
138         Description of ObjMgr Interfaces
139 
140         Raw-Memory-Interface:    DDD_ObjNew, DDD_ObjDelete
141         Constructor-Interface:   DDD_HdrConstructor, DDD_HdrDestructor
142         Application-Interface:   DDD_Get, DDD_UnGet
143  */
144 
145 
146 /****************************************************************************/
147 /*                                                                          */
148 /* Function:  DDD_ObjNew                                                    */
149 /*                                                                          */
150 /****************************************************************************/
151 
152 /* Purpose:   get raw memory for new DDD-object.                            */
153 /*                                                                          */
154 /* Input:     size:  memory size of object                                  */
155 /*            typ:   DDD_TYPE of object                                     */
156 /*            prio:  DDD_PRIO of object                                     */
157 /*            attr:  attribute of distributed object                        */
158 /*                                                                          */
159 /* Output:    pointer to raw memory                                         */
160 /*                                                                          */
161 /****************************************************************************/
162 
163 /**
164         Allocate raw memory for new \ddd{object}.
165         This function dynamically creates raw memory for a new \ddd{object}.
166         Therefore, the user-supplied memory manager function \memmgrfunk{AllocOMEM}
167         is called to allocate the necessary memory. Although the caller must
168         supply the object's priority and attribute, its header will not be
169         initialized by \funk{ObjNew}; the parameters are used for smart
170         memory allocation, only.
171 
172         The function \funk{ObjNew} and \funk{ObjDelete}, its corresponding
173         deletion function, form the ObjManager's {\em raw memory interface}.
174 
175         DDD users who use the #C_FRONTEND# may prefer the more
176         elaborate {\em application interface}, consisting of the functions
177         \funk{ObjGet} and \funk{ObjUnGet}. DDD users who use the language
178         C++ (object-oriented style) with #CPP_FRONTEND# will use the
179         {\em raw memory interface} together with the
180         {\em constructor/destructor interface} (\funk{HdrConstructor},
181         \funk{HdrDestructor}, \funk{HdrConstructorMove})
182         in order to integrate DDD into C++ style object management easily.
183 
184         For variable-sized \ddd{objects}, the parameter {\em aSize}
185         may differ from the size specified during the corresponding
186         \funk{TypeDefine}-call.
187 
188    @return pointer to free memory block for the \ddd{object}
189    @param  aSize   memory size of the new object
190    @param  aType   \ddd{type} of the new object
191    @param  aPrio   \ddd{priority} of the new object
192    @param  aAttr   \ddd{attribute} of the new object
193  */
194 
195 
DDD_ObjNew(size_t aSize,DDD_TYPE aType,DDD_PRIO aPrio,DDD_ATTR aAttr)196 DDD_OBJ DDD_ObjNew (size_t aSize, DDD_TYPE aType,
197                     DDD_PRIO aPrio, DDD_ATTR aAttr)
198 {
199   DDD_OBJ obj;
200 
201   /* check input parameters */
202   if (aPrio>=MAX_PRIO)
203     DUNE_THROW(Dune::Exception, "priority must be less than " << MAX_PRIO);
204   if (aType>=MAX_TYPEDESC)
205     DUNE_THROW(Dune::Exception, "DDD-type must be less than " << MAX_TYPEDESC);
206 
207   /* get object memory */
208   obj = (DDD_OBJ) AllocObj(aSize, aType, aPrio, aAttr);
209   if (obj==NULL)
210     throw std::bad_alloc();
211 
212 #       ifdef DebugCreation
213   Dune::dinfo
214     << "DDD_ObjNew(aSize=" << aSize << ", type=" << aType << ", prio=" << aPrio
215     << ", attr=" << aAttr << ") ADR=" << obj << "\n";
216 #       endif
217 
218   return(obj);
219 }
220 
221 
222 
223 /****************************************************************************/
224 /*                                                                          */
225 /* Function:  DDD_ObjDelete                                                 */
226 /*                                                                          */
227 /* Purpose:   free raw memory from DDD-object                               */
228 /*                                                                          */
229 /* Input:     obj:   object header address                                  */
230 /*            size:  memory size of object                                  */
231 /*            typ:   DDD_TYPE of object                                     */
232 /*                                                                          */
233 /* Output:    -                                                             */
234 /*                                                                          */
235 /****************************************************************************/
236 
237 
DDD_ObjDelete(DDD_OBJ obj,size_t size,DDD_TYPE typ)238 void DDD_ObjDelete (DDD_OBJ obj, size_t size, DDD_TYPE typ)
239 {
240   FreeObj((void *)obj, size, typ);
241 }
242 
243 
244 /****************************************************************************/
245 /*                                                                          */
246 /* Function:  DDD_HdrConstructor                                            */
247 /*                                                                          */
248 /****************************************************************************/
249 
250 /**
251         Initiate object's \ddd{header}.
252         This function registers a \ddd{object} via constructing
253         its DDD-header. Each \ddd{object} is given a unique {\em global ID},
254         which is stored in the DDD-header together with the object's
255         properties (type\_id, prio, attr) and additional data used by DDD.
256 
257         The function \funk{HdrConstructor} and its corresponding deletion
258         function \funk{HdrDestructor} form the ObjManager's
259         {\em constructor/destructor interface}. This interface will be
260         useful for C++ users, together with the {\em raw memory interface}
261         functions \funk{ObjNew} and \funk{ObjDelete}.
262         DDD users who use the language C may prefer the more
263         elaborate {\em application interface}, consisting of the functions
264         \funk{ObjGet} and \funk{ObjUnGet}.
265 
266         Due to the construction of global IDs, an overflow error may occur
267         after many calls to \funk{HdrConstructor}
268         (\MaxUniqueGids\ times in \Version).
269 
270    @param aHdr   pointer to the \ddd{header} which should be constructed
271    @param aType  \ddd{type} of \ddd{object}
272    @param aPrio  \ddd{priority} of \ddd{object}
273    @param aAttr  \ddd{attribute} of \ddd{object}
274  */
275 
DDD_HdrConstructor(DDD::DDDContext & context,DDD_HDR aHdr,DDD_TYPE aType,DDD_PRIO aPrio,DDD_ATTR aAttr)276 void DDD_HdrConstructor (DDD::DDDContext& context,
277                          DDD_HDR aHdr, DDD_TYPE aType,
278                          DDD_PRIO aPrio, DDD_ATTR aAttr)
279 {
280   auto& ctx = context.objmgrContext();
281 
282   /* check input parameters */
283   if (aPrio>=MAX_PRIO)
284     DUNE_THROW(Dune::Exception, "priority must be less than " << MAX_PRIO);
285 
286         #ifdef WithFullObjectTable
287 /* in case of FullObjectTable, we register each header in the
288    global ddd_ObjTable. */
289   auto& objTable = context.objTable();
290 
291 /* check whether there are available objects */
292 if (context.nObjs() == objTable.size())
293 {
294   /* TODO update docu */
295   /* this is a fatal case. we cant register more objects here */
296   /* TODO one could try to expand the global tables here. */
297   DUNE_THROW(Dune::Exception, "no more objects in DDD_HdrConstructor");
298 }
299 
300 /* insert into theObj array */
301 objTable[context.nObjs()] = aHdr;
302 OBJ_INDEX(aHdr) = context.nObjs();
303 context.nObjs(context.nObjs() + 1);
304         #else
305 /* if we dont have WithFullObjectTable, pure local objects without
306    copies on other processors aren't registered by DDD. Therefore,
307    they don't have a valid OBJ_INDEX field. */
308 MarkHdrLocal(aHdr);
309         #endif
310 
311 
312 /* init object header with defaults */
313 OBJ_TYPE(aHdr)  = aType;
314 OBJ_PRIO(aHdr)  = aPrio;
315 OBJ_ATTR(aHdr)  = aAttr;
316 OBJ_FLAGS(aHdr) = 0;
317 
318 /* create unique GID */
319 OBJ_GID(aHdr)   = MakeUnique(context, ctx.theIdCount++);
320 
321 /* check overflow of global id numbering */
322 if (MakeUnique(context, ctx.theIdCount) <= MakeUnique(context, ctx.theIdCount-1))
323 {
324   /* TODO update docu */
325   /* TODO one could try to renumber all objects here. */
326   DUNE_THROW(Dune::Exception, "global ID overflow DDD_HdrConstructor");
327 }
328 
329 #       ifdef DebugCreation
330   Dune::dinfo
331     << "DDD_HdrConstructor(adr=" << aHdr << ", type=" << aType
332     << ", prio=" << aPrio << ", attr=" << aAttr << "), GID=" << OBJ_GID(aHdr)
333     << "  INDEX=" << OBJ_INDEX(aHdr) << "\n";
334 #       endif
335 }
336 
337 
338 
339 /****************************************************************************/
340 /*                                                                          */
341 /* Function:  DDD_HdrDestructor                                             */
342 /*                                                                          */
343 /****************************************************************************/
344 
345 /**
346         Remove object's header from DDD management.
347         This function removes an object from DDD-management
348         via destructing its \ddd{header}.
349         {\em Note:} The \ddd{object} will be destroyed, but its copies
350         on remote processors will not be informed by \funk{HdrDestructor}.
351         There are two consistent possibilities to delete \ddd{objects} which
352         have copies on remote processors:
353 
354         \begin{itemize}
355         \item In order to delete only this local object copy, use
356         \funk{XferDelete} during a DDD Transfer-operation. This will
357         inform the remote copies of the deletion.
358         \item In order to delete a distributed object (\ie, all its
359         object copies), use function \funk{ObjUnGet} (when using the
360         {\em application interface})
361         or a combination of functions
362         \funk{HdrDestructor} / \funk{ObjDelete} (when not using
363         the {\em application interface}) for all copies.
364         \end{itemize}
365 
366         The function \funk{HdrDestructor} and its corresponding creation
367         function \funk{HdrConstructor} form the ObjManager's
368         {\em constructor/destructor interface}. This interface will be
369         useful for C++ users, together with the {\em raw memory interface}
370         functions \funk{ObjNew} and \funk{ObjDelete}.
371         DDD users who use the language C may prefer the more
372         elaborate {\em application interface}, consisting of the functions
373         \funk{ObjGet} and \funk{ObjUnGet}.
374 
375    @param hdr  the object's DDD Header
376  */
377 
DDD_HdrDestructor(DDD::DDDContext & context,DDD_HDR hdr)378 void DDD_HdrDestructor(DDD::DDDContext& context, DDD_HDR hdr)
379 {
380   auto& objTable = context.objTable();
381   auto& nCpls = context.couplingContext().nCpls;
382 COUPLING   *cpl;
383 int objIndex, xfer_active = ddd_XferActive(context);
384 
385 #       ifdef DebugDeletion
386   Dune::dinfo
387     << "DDD_HdrDestructor(adr=" << hdr << ", typ=" << OBJ_TYPE(hdr)
388     << ", prio=" << OBJ_PRIO(hdr) << ", attr=" << OBJ_ATTR(hdr)
389     << "), GID=" << OBJ_GID(hdr) << "  INDEX=" << OBJ_INDEX(hdr) << "\n";
390 #       endif
391 
392 
393 if (IsHdrInvalid(hdr))
394 {
395   /* DDD_HDR is invalid, so destructor is useless */
396   return;
397 }
398 
399 /* formally, the object's GID should be returned here */
400 
401 
402 /* if currently in xfer, register deletion for other processors */
403 if (xfer_active)
404   ddd_XferRegisterDelete(context, hdr);
405 
406 
407 objIndex = OBJ_INDEX(hdr);
408 
409 if (objIndex < nCpls)
410 {
411   /* this is an object with couplings */
412   cpl = IdxCplList(context, objIndex);
413 
414   /* if not during xfer, deletion may be inconsistent */
415   if (!xfer_active)
416   {
417     /* deletion is dangerous, distributed object might get
418        inconsistent. */
419     if (DDD_GetOption(context, OPT_WARNING_DESTRUCT_HDR)==OPT_ON)
420       Dune::dwarn << "DDD_HdrDestructor: inconsistency by deleting gid="
421                   << OBJ_GID(hdr) << "\n";
422   }
423 
424   nCpls -= 1;
425   context.nObjs(context.nObjs() - 1);
426 
427   /* fill slot of deleted obj with last cpl-obj */
428   objTable[objIndex] = objTable[nCpls];
429   IdxCplList(context, objIndex) = IdxCplList(context, nCpls);
430   IdxNCpl(context, objIndex) = IdxNCpl(context, nCpls);
431   OBJ_INDEX(objTable[objIndex]) = objIndex;
432 
433                 #ifdef WithFullObjectTable
434   /* fill slot of last cpl-obj with last obj */
435   if (nCpls < context.nObjs())
436   {
437     objTable[nCpls] = objTable[context.nObjs()];
438     OBJ_INDEX(objTable[nCpls]) = nCpls;
439   }
440                 #else
441   assert(nCpls == context.nObjs());
442                 #endif
443 
444   /* dispose all couplings */
445   DisposeCouplingList(context, cpl);
446 }
447 else
448 {
449                 #ifdef WithFullObjectTable
450   /* this is an object without couplings */
451   /* deletion is not dangerous (no consistency problem) */
452   context.nObjs(context.nObjs() - 1);
453 
454   /* fill slot of deleted obj with last obj */
455   objTable[objIndex] = objTable[context.nObjs()];
456   OBJ_INDEX(objTable[objIndex]) = objIndex;
457                 #endif
458 }
459 
460 /* invalidate this DDD_HDR */
461 MarkHdrInvalid(hdr);
462 }
463 
464 
465 
466 /****************************************************************************/
467 /*                                                                          */
468 /* Function:  DDD_ObjGet                                                    */
469 /*                                                                          */
470 /* Purpose:   get new DDD object for a given DDD_TYPE                       */
471 /*                                                                          */
472 /*            DDD_ObjGet allows different size for each object instance,    */
473 /*            differing from the size computed during DDD_TypeDefine        */
474 /*                                                                          */
475 /* Input:     typ: DDD_TYPE of object                                       */
476 /*                                                                          */
477 /* Output:    pointer to memory, which is raw except from the               */
478 /*              constructed DDD_HDR.                                        */
479 /*                                                                          */
480 /****************************************************************************/
481 
DDD_ObjGet(DDD::DDDContext & context,size_t size,DDD_TYPE typ,DDD_PRIO prio,DDD_ATTR attr)482 DDD_OBJ DDD_ObjGet (DDD::DDDContext& context, size_t size, DDD_TYPE typ, DDD_PRIO prio, DDD_ATTR attr)
483 {
484   DDD_OBJ obj;
485   const TYPE_DESC& desc = context.typeDefs()[typ];
486 
487   /* check input parameters */
488   if (prio<0 || prio>=MAX_PRIO)
489     DUNE_THROW(Dune::Exception, "priority must be less than " << MAX_PRIO);
490 
491   /* get raw memory */
492   obj = (DDD_OBJ) DDD_ObjNew(size, typ, prio, attr);
493   if (obj==NULL)
494     throw std::bad_alloc();
495 
496   if ((desc.size != size) && (DDD_GetOption(context, OPT_WARNING_VARSIZE_OBJ)==OPT_ON))
497   {
498     DDD_PrintError('W', 2200,
499                    "object size differs from declared size in DDD_ObjGet");
500   }
501 
502   if ((desc.size > size) && (DDD_GetOption(context, OPT_WARNING_SMALLSIZE)==OPT_ON))
503   {
504     DDD_PrintError('W', 2201,
505                    "object size smaller than declared size in DDD_ObjGet");
506   }
507 
508 
509   /* call DDD_HdrConstructor */
510   DDD_HdrConstructor(context, OBJ2HDR(obj, &desc), typ, prio, attr);
511 
512   return(obj);
513 }
514 
515 
516 
517 /****************************************************************************/
518 /*                                                                          */
519 /* Function:  DDD_ObjUnGet                                                  */
520 /*                                                                          */
521 /* Purpose:   remove object from DDD management and free its memory         */
522 /*                                                                          */
523 /* Input:     obj: object header address                                    */
524 /*                                                                          */
525 /* Output:    -                                                             */
526 /*                                                                          */
527 /****************************************************************************/
528 
DDD_ObjUnGet(DDD::DDDContext & context,DDD_HDR hdr,size_t size)529 void DDD_ObjUnGet (DDD::DDDContext& context, DDD_HDR hdr, size_t size)
530 
531 {
532   DDD_TYPE typ = OBJ_TYPE(hdr);
533   const TYPE_DESC& desc = context.typeDefs()[typ];
534   DDD_OBJ obj = HDR2OBJ(hdr, &desc);
535 
536   if ((desc.size != size) && (DDD_GetOption(context, OPT_WARNING_VARSIZE_OBJ)==OPT_ON))
537   {
538     DDD_PrintError('W', 2299,
539                    "object size differs from declared size in DDD_ObjUnGet");
540   }
541 
542   /* call DDD_HDR-destructor */
543   DDD_HdrDestructor(context, hdr);
544 
545   /* free raw memory */
546   DDD_ObjDelete(obj, size, typ);
547 }
548 
549 
550 
551 /****************************************************************************/
552 /*                                                                          */
553 /* Function:  DDD_HdrConstructorCopy                                        */
554 /*                                                                          */
555 /* Purpose:   create DDD_HDR copy from message original                     */
556 /*                                                                          */
557 /* Input:     newhdr: new DDD_HDR                                           */
558 /*            prio:   DDD_PRIO of new copy                                  */
559 /*                                                                          */
560 /* Output:    -                                                             */
561 /*                                                                          */
562 /****************************************************************************/
563 
DDD_HdrConstructorCopy(DDD::DDDContext & context,DDD_HDR newhdr,DDD_PRIO prio)564 void DDD_HdrConstructorCopy (DDD::DDDContext& context, DDD_HDR newhdr, DDD_PRIO prio)
565 {
566   /* check input parameters */
567   if (prio>=MAX_PRIO)
568     DUNE_THROW(Dune::Exception, "priority must be less than " << MAX_PRIO);
569 
570         #ifdef WithFullObjectTable
571   auto& objTable = context.objTable();
572 
573   /* check whether there are available objects */
574   if (context.nObjs() == context.objTable().size())
575   {
576     /* TODO update docu */
577     /* this is a fatal case. we cant register more objects here */
578     DDD_PrintError('F', 2220, "no more objects in DDD_HdrConstructorCopy");
579     /* TODO one could try to expand the global tables here. */
580   }
581 
582   /* insert into theObj array */
583   objTable[context.nObjs()] = newhdr;
584   OBJ_INDEX(newhdr) = context.nObjs();
585   context.nObjs(context.nObjs() + 1);
586         #else
587   MarkHdrLocal(newhdr);
588   assert(context.nObjs() == context.couplingContext().nCpls);
589         #endif
590 
591   /* init LDATA components. GDATA components will be copied elsewhere */
592   OBJ_PRIO(newhdr)  = prio;
593 
594 
595 #       ifdef DebugCreation
596   Dune::dinfo
597     << "DDD_HdrConstructorCopy(adr=" << newhdr << ", prio=" << prio
598     << "), GID= " << OBJ_GID(newhdr) << "  INDEX=" << OBJ_INDEX(newhdr)
599     << "  ATTR=" << OBJ_ATTR(newhdr) << "\n";
600 #       endif
601 }
602 
603 
604 
605 /****************************************************************************/
606 /*                                                                          */
607 /* Function:  DDD_HdrConstructorMove                                        */
608 /*                                                                          */
609 /* Purpose:   create DDD_HDR copy inside local memory,                      */
610 /*            simultaneously destruct original DDD_HDR                      */
611 /*                                                                          */
612 /* Input:     newhdr: new DDD_HDR                                           */
613 /*            oldhdr: old DDD_HDR                                           */
614 /*                                                                          */
615 /* Output:    -                                                             */
616 /*                                                                          */
617 /****************************************************************************/
618 
DDD_HdrConstructorMove(DDD::DDDContext & context,DDD_HDR newhdr,DDD_HDR oldhdr)619 void DDD_HdrConstructorMove (DDD::DDDContext& context, DDD_HDR newhdr, DDD_HDR oldhdr)
620 {
621   int objIndex = OBJ_INDEX(oldhdr);
622   const auto& nCpls = context.couplingContext().nCpls;
623 
624 
625   /* copy all components */
626   OBJ_INDEX(newhdr) = OBJ_INDEX(oldhdr);
627   OBJ_TYPE(newhdr)  = OBJ_TYPE(oldhdr);
628   OBJ_PRIO(newhdr)  = OBJ_PRIO(oldhdr);
629   OBJ_ATTR(newhdr)  = OBJ_ATTR(oldhdr);
630   OBJ_FLAGS(newhdr) = OBJ_FLAGS(oldhdr);
631   OBJ_GID(newhdr)   = OBJ_GID(oldhdr);
632 
633 
634   /* change all references from DDD to oldhdr */
635 
636   /* change entry of theObj array */
637   auto& objTable = context.objTable();
638         #ifdef WithFullObjectTable
639   objTable[objIndex] = newhdr;
640         #else
641   if (objIndex < nCpls)
642     objTable[objIndex] = newhdr;
643         #endif
644 
645   /* change pointers from couplings to object */
646   if (objIndex < nCpls)
647   {
648     COUPLING *cpl = IdxCplList(context, objIndex);
649 
650     for(; cpl!=NULL; cpl=CPL_NEXT(cpl)) {
651       cpl->obj = newhdr;
652     }
653 
654     /* invalidate update obj-shortcut tables from IF module */
655     IFInvalidateShortcuts(context, OBJ_TYPE(newhdr));
656   }
657 
658   /* invalidate old DDD_HDR */
659   MarkHdrInvalid(oldhdr);
660 }
661 
662 
663 
664 /****************************************************************************/
665 /*                                                                          */
666 /* Function:  ObjCopyGlobalData                                             */
667 /*                                                                          */
668 /* Purpose:   copy DDD-object from message to memory. elements marked       */
669 /*            EL_LDATA (local data) will not be copied. this is done        */
670 /*            in an efficient way by using the DDD_TYPEs copy-mask (which   */
671 /*            has been set up during StructRegister()).                     */
672 /*                                                                          */
673 /*            CopyByMask() is a support function doing the actual work.     */
674 /*            This function could be more efficient by copying more than    */
675 /*            one byte at a time.                                           */
676 /*                                                                          */
677 /* Input:     target: DDD_OBJ address of target memory                      */
678 /*            source: DDD_OBJ address of source object                      */
679 /*            size:   size of object in bytes (might be != desc->size)      */
680 /*                                                                          */
681 /* Output:    -                                                             */
682 /*                                                                          */
683 /****************************************************************************/
684 
685 
CopyByMask(TYPE_DESC * desc,DDD_OBJ target,DDD_OBJ source)686 static void CopyByMask (TYPE_DESC *desc, DDD_OBJ target, DDD_OBJ source)
687 {
688   unsigned char *s=(unsigned char *)source, *t=(unsigned char *)target;
689   int i;
690 
691 #       ifdef DebugCreation
692   Dune::dinfo << "CopyByMask(" << desc->name << ", size=" << desc->size
693               << ", to=" << target << ", from=" << source << ")\n";
694 #       endif
695 
696   unsigned char* maskp = desc->cmask.get();
697 
698   /* copy all bits set in cmask from source to target */
699   for(i=0; i<desc->size; i++)
700   {
701     unsigned char negmask = *maskp^0xff;
702     *t = (*s & *maskp) | (*t & negmask);
703 
704     t++; s++; maskp++;              /* Paragon didn't manage postfix increment */
705   }
706 }
707 
708 
ObjCopyGlobalData(TYPE_DESC * desc,DDD_OBJ target,DDD_OBJ source,size_t size)709 void ObjCopyGlobalData (TYPE_DESC *desc,
710                         DDD_OBJ target, DDD_OBJ source, size_t size)
711 {
712   /*
713           normally size will be equal to desc->size (for fixed-sized objects).
714           for variable-sized objects size depends on what the sender put into
715           the message
716    */
717 
718   CopyByMask(desc, target, source);
719 
720   /* copy remainder as EL_GDATA */
721   if (size > desc->size)
722   {
723     memcpy(((char *)target)+desc->size,
724            ((char *)source)+desc->size, size-desc->size);
725   }
726 
727 #       ifdef DebugCreation
728   const auto& hdr = OBJ2HDR(target, desc);
729   Dune::dinfo
730     << "ObjCopyGlobalData(" << hdr << " <- " << source << ", size=" << size
731     << "), TYP=" << OBJ_TYPE(hdr) << "  GID=" << OBJ_GID(hdr)
732     << "  INDEX=" << OBJ_INDEX(hdr) << "\n";
733 #       endif
734 }
735 
736 
737 
738 /****************************************************************************/
739 
DDD_SearchHdr(DDD::DDDContext & context,DDD_GID gid)740 DDD_HDR DDD_SearchHdr(DDD::DDDContext& context, DDD_GID gid)
741 {
742   auto& objTable = context.objTable();
743   const int nObjs = context.nObjs();
744 int i;
745 
746 i=0;
747 while (i < nObjs && OBJ_GID(objTable[i])!=gid)
748   i++;
749 
750 if (i < nObjs)
751 {
752   return(objTable[i]);
753 }
754 else
755   return(NULL);
756 }
757 
758 
759 /****************************************************************************/
760 
761 
ddd_ObjMgrInit(DDD::DDDContext & context)762 void ddd_ObjMgrInit(DDD::DDDContext& context)
763 {
764   auto& ctx = context.objmgrContext();
765 
766   /* sanity check: does the DDD_PROC type have enough bits? */
767   if (sizeof(DDD_PROC)*8 < MAX_PROCBITS_IN_GID)
768     DDD_PrintError('F', 666, "DDD_PROC isn't large enough for MAX_PROCBITS_IN_GID bits");
769 
770   ctx.theIdCount = 1;        /* start with 1, for debugging reasons */
771 
772   /* allocate first (smallest) object table */
773   context.objTable().resize(MAX_OBJ_START);
774 }
775 
776 
ddd_ObjMgrExit(DDD::DDDContext & context)777 void ddd_ObjMgrExit(DDD::DDDContext& context)
778 {
779   context.objTable().clear();
780 }
781 
782 
783 /****************************************************************************/
784 
785 END_UGDIM_NAMESPACE
786