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