A platform for high-performance distributed tool and library development written in C++. It can be deployed in two different cluster modes: standalone or distributed. API for v0.5.0, released on June 13, 2018.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Handle.cc
Go to the documentation of this file.
1 /*****************************************************************************
2  * *
3  * Copyright 2018 Rice University *
4  * *
5  * Licensed under the Apache License, Version 2.0 (the "License"); *
6  * you may not use this file except in compliance with the License. *
7  * You may obtain a copy of the License at *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14  * See the License for the specific language governing permissions and *
15  * limitations under the License. *
16  * *
17  *****************************************************************************/
18 
19 #ifndef HANDLE_CC
20 #define HANDLE_CC
21 
22 #include <cstddef>
23 #include <iostream>
24 #include <vector>
25 #include <algorithm>
26 #include <iterator>
27 #include <cstring>
28 
29 #include "PDBDebug.h"
30 #include "TypeName.h"
31 #include "Handle.h"
32 #include "RefCountedObject.h"
33 
34 namespace pdb {
35 
36 #define CHAR_PTR(c) ((char*)c)
37 
38 template <class ObjType>
39 Handle<ObjType>::Handle() {
40  typeInfo.setup<ObjType>();
41  offset = -1;
42 }
43 
44 template <class ObjType>
45 int16_t Handle<ObjType>::getTypeCode() {
46  return typeInfo.getTypeCode();
47 }
48 
49 template <class ObjType>
50 int32_t Handle<ObjType>::getExactTypeInfoValue() const {
51  return typeInfo.getExactTypeInfoValue();
52 }
53 
54 template <class ObjType>
55 void Handle<ObjType>::setExactTypeInfoValue(int32_t toMe) {
56  typeInfo.set(toMe);
57 }
58 
59 template <class ObjType>
60 Handle<ObjType>::~Handle() {
61 
62  // if we are not null, then dec the reference count
63  if (!isNullPtr() && getAllocator().isManaged(getTarget())) {
64  getTarget()->decRefCount(typeInfo);
65  }
66 }
67 
68 template <class ObjType>
69 unsigned Handle<ObjType>::getRefCount() {
70 
71  // if we are not null, then dec the reference count
72  if (!isNullPtr() && getAllocator().isManaged(getTarget())) {
73  return getTarget()->getRefCount();
74  }
75 
76  // returned if we have no reference count
77  return 9999999;
78 }
79 
80 template <class ObjType>
82 
83  if (!isNullPtr()) {
84 
85  // go ahead and free his block
86  getAllocator().emptyOutBlock(getTarget());
87 
88  // and set us so that we are a null pointer
89  offset = -1;
90  } else {
91  std::cout << "This seems bad. I don't think that you should be emptying the containing "
92  "block for a nullptr.\n";
93  }
94 }
95 
96 template <class ObjType>
97 Handle<ObjType>::Handle(GenericHandle rhs) {
98  typeInfo = rhs.getMyBase();
99  offset = -1;
100 }
101 
102 
103 template <class ObjType>
104 Handle<ObjType>::Handle(const std::nullptr_t rhs) {
105  typeInfo.setup<Nothing>();
106  offset = -1;
107 }
108 
109 template <class ObjType>
110 Handle<ObjType> Handle<ObjType>::copyTargetToCurrentAllocationBlock() {
111 
112  // if the current allocator contains us, then just return ourselves
113  if (getAllocator().contains(getTarget())) {
114  return *this;
115  }
116 
117  // otherwise, make a new handle and do the assignment via a deep copy
118  Handle<ObjType> returnVal;
119 
120 // get the space... allocate and set up the reference count before it
121 #ifdef DEBUG_OBJECT_MODEL
122  void* space =
123  getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjType), typeInfo.getTypeCode());
124 #else
125  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjType));
126 #endif
127  // see if there was not enough RAM
128  if (space == nullptr) {
129  PDB_COUT << "ERROR: Not enough memory when invoking copyTargetToCurrentAllocationBlock() "
130  "in Handle.cc"
131  << std::endl;
132  returnVal.offset = -1;
133  throw myException;
134  }
135 
136  // point the new handle at the space
137  returnVal.offset = CHAR_PTR(space) - CHAR_PTR(&returnVal);
138  returnVal.getTarget()->setRefCount(1);
139 
140  // copy over the object
141  returnVal.typeInfo = typeInfo;
142  try {
143  if (typeInfo.getTypeCode() == 0) {
144  PDB_COUT << "copyTargetToCurrentAllocationBlock: typeInfo = 0 before "
145  "setUpAndCopyFromConstituentObject"
146  << std::endl;
147  }
148  typeInfo.setUpAndCopyFromConstituentObject(returnVal.getTarget()->getObject(),
149  getTarget()->getObject());
150  } catch (NotEnoughSpace& n) {
151  PDB_COUT << "ERROR: Not enough memory when invoking copyTargetToCurrentAllocationBlock() "
152  "in Handle.cc"
153  << std::endl;
154  returnVal.getTarget()->decRefCount(typeInfo);
155  returnVal.offset = -1;
156  throw n;
157  }
158  // and reutrn him
159  return returnVal;
160 }
161 
162 #define GET_OLD_TARGET \
163  RefCountedObject<ObjType>* oldTarget = nullptr; \
164  if (!isNullPtr()) \
165  oldTarget = getTarget(); \
166  PDBTemplateBase oldTypeInfo = typeInfo;
167 #define DEC_OLD_REF_COUNT \
168  if (oldTarget != nullptr) \
169  oldTarget->decRefCount(oldTypeInfo)
170 
171 template <class ObjType>
172 Handle<ObjType>& Handle<ObjType>::operator=(const std::nullptr_t rhs) {
175  offset = -1;
176  return *this;
177 }
178 
179 template <class ObjType>
180 bool Handle<ObjType>::isNullPtr() const {
181  return (offset == -1);
182 }
183 
184 /***************************************************************************/
185 /* There are eight different cases for assign/copy construction on Handles */
186 /* */
187 /* 1. Copy construct from RefCountedObject of same Object type */
188 /* 2. Copy construct from RefCountedObject of diff Object type */
189 /* 3. Copy construct from Handle of same Object type */
190 /* 4. Copy construct from Handle of diff Object type */
191 /* 5. Assignment from RefCountedObject of same Object type */
192 /* 6. Assignment from RefCountedObject of diff Object type */
193 /* 7. Assignment from Handle of same Object type */
194 /* 8. Assignment from Handle of diff Object type */
195 /***************************************************************************/
196 
197 /***************************************/
198 /* Here are the four copy constructors */
199 /***************************************/
200 
201 /*************************************************************/
202 /* Here are the two copy constructors from RefCountedObjects */
203 /*************************************************************/
204 
205 template <class ObjType>
206 Handle<ObjType>::Handle(const RefCountedObject<ObjType>* fromMe) {
207 
208  // set up the type info for this guy
209  typeInfo.setup<ObjType>();
210 
211  if (fromMe == nullptr) {
212  offset = -1;
213  return;
214  }
215 
216  // if the RHS is not in the current allocator, but the handle is, then
217  // we need to copy it over using a deep copy
218  if (!getAllocator().contains((void*)fromMe) && getAllocator().contains(this)) {
219 #ifdef DEBUG_OBJECT_MODEL
220  // get the space... allocate and set up the reference count before it
221  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjType),
222  typeInfo.getTypeCode());
223 #else
224  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjType));
225 #endif
226  // see if there was not enough RAM
227  if (space == nullptr) {
228  std::cout << "ERROR: Not enough memory when invoking Handle (const RefCountedObject "
229  "<ObjType>) in Handle.cc"
230  << std::endl;
231  offset = -1;
232  throw myException;
233  }
234 
235  offset = CHAR_PTR(space) - CHAR_PTR(this);
236 
237  getTarget()->setRefCount(1);
238 
239  // copy over the object
240  try {
241  typeInfo.setUpAndCopyFromConstituentObject(getTarget()->getObject(),
242  fromMe->getObject());
243  } catch (NotEnoughSpace& n) {
244  PDB_COUT << "ERROR: Not enough memory when invoking Handle(const "
245  "RefCountedObject<ObjType>) in Handle.cc"
246  << std::endl;
247  getTarget()->decRefCount(typeInfo);
248  offset = -1;
249  throw n;
250  }
251 
252  // if the RHS is not in the current allocator or the LHS handle is not in the
253  // current allocator, then we just do a shallow copy
254  } else {
255 
256  // set the offset
257  offset = CHAR_PTR(fromMe) - CHAR_PTR(this);
258 
259  getTarget()->incRefCount();
260  }
261 }
262 
263 class String;
264 
265 template <class ObjType, class ObjTypeTwo>
266 auto convert(ObjType*, ObjTypeTwo*) -> std::enable_if_t<
267  std::is_base_of<ObjType, ObjTypeTwo>::value ||
268  (std::is_base_of<ObjType, Object>::value && std::is_base_of<String, ObjTypeTwo>::value) ||
269  (std::is_base_of<ObjType, Object>::value && std::is_base_of<HandleBase, ObjTypeTwo>::value),
270  int> {
271  return 7;
272 }
273 
274 template <class ObjType>
275 template <class ObjTypeTwo>
276 Handle<ObjType>::Handle(const RefCountedObject<ObjTypeTwo>* fromMe) {
277 
278  ObjType* one = nullptr;
279  ObjTypeTwo* two = nullptr;
280  convert(one, two); // this line will not compile with a bad assignment
281 
282  // set up the type info for this guy
283  typeInfo.setup<ObjTypeTwo>();
284 
285  if (fromMe == nullptr) {
286  offset = -1;
287  return;
288  }
289 
290  // if the RHS is not in the current allocator, but the handle is, then
291  // we need to copy it over using a deep copy
292  if (!getAllocator().contains((void*)fromMe) && getAllocator().contains(this)) {
293 
294 // get the space... allocate and set up the reference count before it
295 #ifdef DEBUG_OBJECT_MODEL
296  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjTypeTwo),
297  typeInfo.getTypeCode());
298 #else
299  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjTypeTwo));
300 #endif
301  // see if there was not enough RAM
302  if (space == nullptr) {
303  std::cout << "ERROR: Not enough memory when invoking Handle (const RefCountedObject "
304  "<ObjTypeTwo>) in Handle.cc"
305  << std::endl;
306  offset = -1;
307  throw myException;
308  }
309 
310  offset = CHAR_PTR(space) - CHAR_PTR(this);
311 
312  getTarget()->setRefCount(1);
313 
314  // copy over the object; use a virtual method so that we get everything set up and copied
315  // correctly
316  try {
317  typeInfo.setUpAndCopyFromConstituentObject(getTarget()->getObject(),
318  fromMe->getObject());
319  } catch (NotEnoughSpace& n) {
320  PDB_COUT << "ERROR: Not enough memory when invoking Handle(const "
321  "RefCountedObject<ObjTypeTwo>) in Handle.cc"
322  << std::endl;
323  getTarget()->decRefCount(typeInfo);
324  offset = -1;
325  throw n;
326  }
327 
328  // if the RHS is not in the current allocator or the LHS handle is not in the
329  // current allocator, then we just do a shallow copy
330  } else {
331 
332  // set the offset
333  offset = CHAR_PTR(fromMe) - CHAR_PTR(this);
334 
335  getTarget()->incRefCount();
336  }
337 }
338 
339 /***************************************************/
340 /* Here are the two copy constructors from Handles */
341 /***************************************************/
342 
343 template <class ObjType>
344 Handle<ObjType>::Handle(const Handle<ObjType>& fromMe) {
345 
346  // if we got a null pointer as the RHS, then we are the RHS
347  if (fromMe.isNullPtr()) {
348  offset = -1;
349  return;
350  }
351 
352  typeInfo = fromMe.typeInfo;
353 
354  // if the RHS is not in the current allocator, but the handle is, then
355  // we need to copy it over using a deep copy
356  if (!getAllocator().contains(fromMe.getTarget()) && getAllocator().contains(this)) {
357 
358 // get the space... allocate and set up the reference count before it
359 #ifdef DEBUG_OBJECT_MODEL
360  void* space = getAllocator().getRAM(
362  typeInfo.getSizeOfConstituentObject(fromMe.getTarget()->getObject()),
363  typeInfo.getTypeCode());
364 #else
365  void* space = getAllocator().getRAM(
367  typeInfo.getSizeOfConstituentObject(fromMe.getTarget()->getObject()));
368 #endif
369  // see if there was not enough RAM
370  if (space == nullptr) {
371  std::cout << "ERROR: Not enough memory when invoking Handle(const Handle<ObjType>) in "
372  "Handle.cc"
373  << std::endl;
374  offset = -1;
375  throw myException;
376  }
377 
378  offset = CHAR_PTR(space) - CHAR_PTR(this);
379 
380  // set the reference count to one then decrement the old ref count
381  getTarget()->setRefCount(1);
382 
383  // copy over the object; use a virtual method so that we get everything set up and copied
384  // correctly
385  try {
386  typeInfo.setUpAndCopyFromConstituentObject(getTarget()->getObject(),
387  fromMe.getTarget()->getObject());
388  } catch (NotEnoughSpace& n) {
389  PDB_COUT << "ERROR: Not enough memory when invoking Handle(const Handle<ObjType>) in "
390  "Handle.cc"
391  << std::endl;
392  getTarget()->decRefCount(typeInfo);
393  offset = -1;
394  throw n;
395  }
396  // if the RHS is not in the current allocator or the LHS handle is not in the
397  // current allocator, then we just do a shallow copy
398  } else {
399 
400  // set the offset
401  offset = CHAR_PTR(fromMe.getTarget()) - CHAR_PTR(this);
402 
403  getTarget()->incRefCount();
404  }
405 }
406 
407 template <class ObjType>
408 template <class ObjTypeTwo>
409 Handle<ObjType>::Handle(const Handle<ObjTypeTwo>& fromMe) {
410 
411  ObjType* one = nullptr;
412  ObjTypeTwo* two = nullptr;
413  convert(one, two); // this line will not compile with a bad assignment
414 
415  // if we got a null pointer as the RHS, then we are the RHS
416  if (fromMe.isNullPtr()) {
417  offset = -1;
418  return;
419  }
420 
421  typeInfo = fromMe.typeInfo;
422 
423  // if the RHS is not in the current allocator, but the handle is, then
424  // we need to copy it over using a deep copy
425  if (!getAllocator().contains(fromMe.getTarget()) && getAllocator().contains(this)) {
426 
427 // get the space... allocate and set up the reference count before it
428 #ifdef DEBUG_OBJECT_MODEL
429  void* space = getAllocator().getRAM(
431  typeInfo.getSizeOfConstituentObject(fromMe.getTarget()->getObject()),
432  typeInfo.getTypeCode());
433 #else
434  void* space = getAllocator().getRAM(
436  typeInfo.getSizeOfConstituentObject(fromMe.getTarget()->getObject()));
437 #endif
438  // see if there was not enough RAM
439  if (space == nullptr) {
440  std::cout << "ERROR: Not enough memory when invoking Handle(const Handle<ObjTypeTwo>) "
441  "in Handle.cc"
442  << std::endl;
443  offset = -1;
444  throw myException;
445  }
446 
447  offset = CHAR_PTR(space) - CHAR_PTR(this);
448 
449  getTarget()->setRefCount(1);
450 
451  // copy over the object; use a virtual method so that we get everything set up and copied
452  // correctly
453  try {
454  typeInfo.setUpAndCopyFromConstituentObject(getTarget()->getObject(),
455  fromMe.getTarget()->getObject());
456  } catch (NotEnoughSpace& n) {
457  PDB_COUT << "ERROR: Not enough memory when invoking Handle(const Handle<ObjTypeTwo>) "
458  "in Handle.cc"
459  << std::endl;
460  getTarget()->decRefCount(typeInfo);
461  offset = -1;
462  throw n;
463  }
464  // if the RHS is not in the current allocator or the LHS handle is not in the
465  // current allocator, then we just do a shallow copy
466  } else {
467 
468  // set the offset
469  offset = CHAR_PTR(fromMe.getTarget()) - CHAR_PTR(this);
470 
471  getTarget()->incRefCount();
472  }
473 }
474 
475 /******************************************/
476 /* Here are the four assignment operators */
477 /******************************************/
478 
479 /****************************************************************/
480 /* Here are the two assignment operators from RefCountedObjects */
481 /****************************************************************/
482 
483 template <class ObjType>
484 Handle<ObjType>& Handle<ObjType>::operator=(const RefCountedObject<ObjType>* fromMe) {
485  // get the thing that we used to point to
487 
488  // set up the type info for this guy
489  typeInfo.setup<ObjType>();
490 
491  if (fromMe == nullptr) {
492  std::cout << "ERROR: fromMe is nullptr when invoking operator = (const RefCountedObject "
493  "<ObjType>*) in Handle.cc"
494  << std::endl;
496  offset = -1;
497  return *this;
498  }
499 
500  // if the RHS is not in the current allocator, but the handle is, then
501  // we need to copy it over using a deep copy
502  if (!getAllocator().contains((void*)fromMe) && getAllocator().contains(this)) {
503 
504 // get the space... allocate and set up the reference count before it
505 #ifdef DEBUG_OBJECT_MODEL
506  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjType),
507  typeInfo.getTypeCode());
508 #else
509  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjType));
510 #endif
511  // see if there was not enough RAM
512  if (space == nullptr) {
513  std::cout << "ERROR: not enough memory when invoking operator = (const "
514  "RefCountedObject <ObjType>*) in Handle.cc"
515  << std::endl;
517  offset = -1;
518  throw myException;
519  }
520 
521  offset = CHAR_PTR(space) - CHAR_PTR(this);
522 
523  // set the reference count to one then decrement the old ref count
524  getTarget()->setRefCount(1);
525 
526  // copy over the object; use a virtual method so that we get everything set up and copied
527  // correctly
528  try {
529  if (typeInfo.getTypeCode() == 0) {
530  PDB_COUT << "operator=: typeInfo = 0 before setUpAndCopyFromConstituentObject"
531  << std::endl;
532  }
533 #ifdef DEBUG_DEEP_COPY
534  if (typeInfo.getTypeCode() > 126) {
535  PDB_COUT << "typeInfo=" << typeInfo.getTypeCode() << std::endl;
536  }
537 #endif
538  typeInfo.setUpAndCopyFromConstituentObject(getTarget()->getObject(),
539  fromMe->getObject());
540  } catch (NotEnoughSpace& n) {
541  PDB_COUT << "ERROR: Not enough memory when invoking operator = (const "
542  "RefCountedObject<ObjType>*) in Handle.cc"
543  << std::endl;
545  getTarget()->decRefCount(typeInfo);
546  offset = -1;
547  throw n;
548  }
550 
551  // if the RHS is not in the current allocator or the LHS handle is not in the
552  // current allocator, then we just do a shallow copy
553  } else {
554 #ifdef DEBUG_OBJECT_MODEL
555  if (!getAllocator().contains((void*)fromMe) && !getAllocator().contains(this)) {
556  std::cout << "#################################################" << std::endl;
557  std::cout << "Both LHS and RHS are not in current block" << std::endl;
558  std::cout << "RHS typeinfo =" << typeInfo.getTypeCode() << std::endl;
559  std::cout << "#################################################" << std::endl;
560  }
561 #endif
562 
563 
564  // set the offset
565  offset = CHAR_PTR(fromMe) - CHAR_PTR(this);
566  // std :: cout << "offset=" << offset << std :: endl;
567  // increment the reference count then decrement the old ref count...
568  // it is important to do it in this order to correctly handle self-
569  // assignments without accidentally setting the count to zero
570  getTarget()->incRefCount();
571  // std :: cout << "to dec old ref count" << std :: endl;
573  // std :: cout << "to return" << std :: endl;
574  }
575 
576  return *this;
577 }
578 
579 template <class ObjType>
580 template <class ObjTypeTwo>
581 Handle<ObjType>& Handle<ObjType>::operator=(const RefCountedObject<ObjTypeTwo>* fromMe) {
582 
583  ObjType* one = nullptr;
584  ObjTypeTwo* two = nullptr;
585  convert(one, two); // this line will not compile with a bad assignment
586 
587  // get the thing that we used to point to
589 
590  // set up the type info for this guy
591  typeInfo.setup<ObjTypeTwo>();
592 
593  if (fromMe == nullptr) {
595  offset = -1;
596  return *this;
597  }
598 
599  // if the RHS is not in the current allocator, but the handle is, then
600  // we need to copy it over using a deep copy
601  if (!getAllocator().contains((void*)fromMe) && getAllocator().contains(this)) {
602 
603 // get the space... allocate and set up the reference count before it
604 #ifdef DEBUG_OBJECT_MODEL
605  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjTypeTwo),
606  typeInfo.getTypeCode());
607 #else
608  void* space = getAllocator().getRAM(REF_COUNT_PREAMBLE_SIZE + sizeof(ObjTypeTwo));
609 #endif
610  // see if there was not enough RAM
611  if (space == nullptr) {
612  std::cout << "ERROR: Not enough memory when invoking operator = (const "
613  "RefCountedObject<ObjTypeTwo>*) in Handle.cc"
614  << std::endl;
616  offset = -1;
617  throw myException;
618  }
619 
620  offset = CHAR_PTR(space) - CHAR_PTR(this);
621 
622  // set the reference count to one then decrement the old ref count
623  getTarget()->setRefCount(1);
624 
625  // copy over the object; use a virtual method so that we get everything set up and copied
626  // correctly
627  try {
628  typeInfo.setUpAndCopyFromConstituentObject(getTarget()->getObject(),
629  fromMe->getObject());
630  } catch (NotEnoughSpace& n) {
631  PDB_COUT << "ERROR: Not enough memory when invoking operator = (const "
632  "RefCountedObject<ObjTypeTwo>*) in Handle.cc"
633  << std::endl;
634  getTarget()->decRefCount(typeInfo);
636  offset = -1;
637  throw n;
638  }
640 
641  // if the RHS is not in the current allocator or the LHS handle is not in the
642  // current allocator, then we just do a shallow copy
643  } else {
644 #ifdef DEBUG_OBJECT_MODEL
645  if (!getAllocator().contains((void*)fromMe) && !getAllocator().contains(this)) {
646  std::cout << "#################################################" << std::endl;
647  std::cout << "Both LHS and RHS are not in current block" << std::endl;
648  std::cout << "RHS typeinfo =" << typeInfo.getTypeCode() << std::endl;
649  std::cout << "#################################################" << std::endl;
650  }
651 #endif
652 
653  // set the offset
654  offset = CHAR_PTR(fromMe) - CHAR_PTR(this);
655 
656  // increment the reference count then decrement the old ref count...
657  // it is important to do it in this order to correctly handle self-
658  // assignments without accidentally setting the count to zero
659  getTarget()->incRefCount();
661  }
662 
663  return *this;
664 }
665 
666 /******************************************************/
667 /* Here are the two assignment operators from Handles */
668 /******************************************************/
669 
670 template <class ObjType>
671 Handle<ObjType>& Handle<ObjType>::operator=(const Handle<ObjType>& fromMe) {
672 
673  // get the thing that we used to point to
675 
676  // if we got a null pointer as the RHS, then we are the RHS
677  if (fromMe == nullptr) {
679  offset = -1;
680  return *this;
681  }
682 
683  typeInfo = fromMe.typeInfo;
684 
685  // if the RHS is not in the current allocator, but the handle is, then
686  // we need to copy it over using a deep copy
687  if (!getAllocator().contains(fromMe.getTarget()) && getAllocator().contains(this)) {
688 
689  // get the space... allocate and set up the reference count before it
690  RefCountedObject<ObjType>* refCountedObject = fromMe.getTarget();
691  ObjType* object = refCountedObject->getObject();
692 #ifdef DEBUG_OBJECT_MODEL
693  void* space =
695  typeInfo.getSizeOfConstituentObject(
696  /*fromMe.getTarget ()->getObject ()*/ (void*)object),
697  typeInfo.getTypeCode());
698 #else
699  void* space =
701  typeInfo.getSizeOfConstituentObject(
702  /*fromMe.getTarget ()->getObject ()*/ (void*)object));
703 #endif
704  // see if there was not enough RAM
705  if (space == nullptr) {
706  std::cout << "Not enough memory when doing a deep copy with TypeId="
707  << typeInfo.getTypeCode() << std::endl;
709  offset = -1;
710  throw myException;
711  }
712 
713  offset = CHAR_PTR(space) - CHAR_PTR(this);
714 
715  // set the reference count to one then decrement the old ref count
716  getTarget()->setRefCount(1);
717 
718  // copy over the object; use a virtual method so that we get everything set up and copied
719  // correctly
720  try {
721 #ifdef DEBUG_DEEP_COPY
722  int typeId = typeInfo.getTypeCode();
723  if ((typeId == 0) || (typeId > 126)) {
724  PDB_COUT << "Handle operator=: typeInfo=" << typeId
725  << " before setUpAndCopyFromConstituentObject" << std::endl;
726  }
727 #endif
728  typeInfo.setUpAndCopyFromConstituentObject(getTarget()->getObject(),
729  fromMe.getTarget()->getObject());
730  } catch (NotEnoughSpace& n) {
731  PDB_COUT << "Not enough memory when doing a deep copy with TypeId="
732  << typeInfo.getTypeCode() << std::endl;
733  getTarget()->decRefCount(typeInfo);
735  offset = -1;
736  throw n;
737  }
738 
740 
741  // finally, do the assignment
742  return *this;
743 
744  // if the RHS is not in the current allocator or the LHS handle is not in the
745  // current allocator, then we just do a shallow copy
746  } else {
747 #ifdef DEBUG_OBJECT_MODEL
748  if (!getAllocator().contains(fromMe.getTarget()) && !getAllocator().contains(this)) {
749  std::cout << "#################################################" << std::endl;
750  std::cout << "Both LHS and RHS are not in current block" << std::endl;
751  std::cout << "RHS typeinfo =" << typeInfo.getTypeCode() << std::endl;
752  std::cout << "#################################################" << std::endl;
753  }
754 #endif
755  // set the offset
756  offset = CHAR_PTR(fromMe.getTarget()) - CHAR_PTR(this);
757 
758  // increment the reference count then decrement the old ref count...
759  // it is important to do it in this order to correctly handle self-
760  // assignments without accidentally setting the count to zero
761  getTarget()->incRefCount();
763 
764  return *this;
765  }
766 }
767 
768 template <class ObjType>
769 template <class ObjTypeTwo>
770 Handle<ObjType>& Handle<ObjType>::operator=(const Handle<ObjTypeTwo>& fromMe) {
771 
772  ObjType* one = nullptr;
773  ObjTypeTwo* two = nullptr;
774  convert(one, two); // this line will not compile with a bad assignment
775 
776  // get the thing that we used to point to
778 
779  // if we got a null pointer as the RHS, then we are the RHS
780  if (fromMe == nullptr) {
782  offset = -1;
783  return *this;
784  }
785 
786  typeInfo = fromMe.typeInfo;
787  if (typeInfo.getTypeCode() == 0) {
788  PDB_COUT << "Handle operator = ObjTypeTwo: typeInfo = 0 before getSizeConstituentObject"
789  << std::endl;
790  }
791  // if the RHS is not in the current allocator, but the handle is, then
792  // we need to copy it over using a deep copy
793  if (!getAllocator().contains(fromMe.getTarget()) && getAllocator().contains(this)) {
794 
795 // get the space... allocate and set up the reference count before it
796 #ifdef DEBUG_OBJECT_MODEL
797  void* space = getAllocator().getRAM(
799  typeInfo.getSizeOfConstituentObject(fromMe.getTarget()->getObject()),
800  typeInfo.getTypeCode());
801 #else
802  void* space = getAllocator().getRAM(
804  typeInfo.getSizeOfConstituentObject(fromMe.getTarget()->getObject()));
805 #endif
806  // see if there was not enough RAM
807  if (space == nullptr) {
808  std::cout << "Not enough memory when doing a deep copy with TypeId="
809  << typeInfo.getTypeCode() << std::endl;
811  offset = -1;
812  throw myException;
813  }
814 
815  offset = CHAR_PTR(space) - CHAR_PTR(this);
816 
817  // set the reference count to one then decrement the old ref count
818  getTarget()->setRefCount(1);
819 
820  // copy over the object; use a virtual method so that we get everything set up and copied
821  // correctly
822  try {
823  typeInfo.setUpAndCopyFromConstituentObject(getTarget()->getObject(),
824  fromMe.getTarget()->getObject());
825  } catch (NotEnoughSpace& n) {
826  PDB_COUT << "Not enough memory when doing a deep copy with TypeId="
827  << typeInfo.getTypeCode() << std::endl;
828  getTarget()->decRefCount(typeInfo);
830  offset = -1;
831  throw n;
832  }
833 
835 
836  // finally, do the assignment
837  return *this;
838 
839  // if the RHS is not in the current allocator or the LHS handle is not in the
840  // current allocator, then we just do a shallow copy
841  } else {
842 #ifdef DEBUG_OBJECT_MODEL
843  if (!getAllocator().contains(fromMe.getTarget()) && !getAllocator().contains(this)) {
844  std::cout << "#################################################" << std::endl;
845  std::cout << "Both LHS and RHS are not in current block" << std::endl;
846  std::cout << "RHS typeinfo =" << typeInfo.getTypeCode() << std::endl;
847  std::cout << "#################################################" << std::endl;
848  }
849 #endif
850  // set the offset
851  offset = CHAR_PTR(fromMe.getTarget()) - CHAR_PTR(this);
852 
853  // increment the reference count then decrement the old ref count...
854  // it is important to do it in this order to correctly handle self-
855  // assignments without accidentally setting the count to zero
856  getTarget()->incRefCount();
858 
859  return *this;
860  }
861 }
862 
863 // de-reference operators
864 template <class ObjType>
865 ObjType* Handle<ObjType>::operator->() const {
866 
867  // fix the vTable pointer and return a reference
868  // std :: cout << "to setVTablePtr in handle -> operator" << std :: endl;
869  typeInfo.setVTablePtr(getTarget()->getObject());
870  // std :: cout << "setVTablePtr done" << std :: endl;
871  return getTarget()->getObject();
872 }
873 
874 template <class ObjType>
875 void Handle<ObjType>::setOffset(int64_t toMe) {
876  offset = toMe;
877 }
878 
879 template <class ObjType>
880 int64_t Handle<ObjType>::getOffset() const {
881  return offset;
882 }
883 
884 template <class ObjType>
885 ObjType& Handle<ObjType>::operator*() const {
886 
887  // fix the vTable pointer and return a reference
888  typeInfo.setVTablePtr(getTarget()->getObject());
889  return *(getTarget()->getObject());
890 }
891 
892 
893 // gets a pointer to the target object
894 template <class ObjType>
895 RefCountedObject<ObjType>* Handle<ObjType>::getTarget() const {
896  return (RefCountedObject<ObjType>*)(CHAR_PTR(this) + offset);
897 }
898 
899 
900 // JiaNote: to shallow copy a handle to current allocation block
901 // This is to improve the performance of current pipeline bundling
902 template <class ObjType>
903 Handle<ObjType>& Handle<ObjType>::shallowCopyToCurrentAllocationBlock(
904  const Handle<ObjType>& copyMe) {
905 
906  // get the thing that we used to point to
908 
909  // if we got a null pointer as the RHS, then we are the RHS
910  if (copyMe == nullptr) {
912  offset = -1;
913  return *this;
914  }
915 
916  typeInfo = copyMe.typeInfo;
917 
918  // set the offset
919  offset = CHAR_PTR(copyMe.getTarget()) - CHAR_PTR(this);
920 
921  // increment the reference count then decrement the old ref count...
922  // it is important to do it in this order to correctly handle self-
923  // assignments without accidentally setting the count to zero
924  getTarget()->incRefCount();
926 
927  return *this;
928 }
929 }
930 
931 #endif
#define REF_COUNT_PREAMBLE_SIZE
auto convert(ObjType *, ObjTypeTwo *) -> std::enable_if_t< std::is_base_of< ObjType, ObjTypeTwo >::value||(std::is_base_of< ObjType, Object >::value &&std::is_base_of< String, ObjTypeTwo >::value)||(std::is_base_of< ObjType, Object >::value &&std::is_base_of< HandleBase, ObjTypeTwo >::value), int >
Definition: Handle.cc:266
Allocator & getAllocator()
Definition: Allocator.cc:943
#define DEC_OLD_REF_COUNT
Definition: Handle.cc:167
NotEnoughSpace myException
bool contains(void *whereIn)
Definition: Allocator.cc:543
void * getRAM(size_t howMuch)
Definition: Allocator.cc:557
#define PDB_COUT
Definition: PDBDebug.h:31
void emptyOutBlock(void *here)
Definition: Allocator.cc:596
#define GET_OLD_TARGET
Definition: Handle.cc:162
void emptyOutContainingBlock(void *forMe)
#define CHAR_PTR(c)
Definition: Handle.cc:36