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
InterfaceFunctions.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 INTERFACE_FUNCTIONS_CC
20 #define INTERFACE_FUNCTIONS_CC
21 
22 #include <cstddef>
23 #include <iostream>
24 #include <vector>
25 #include <algorithm>
26 #include <iterator>
27 #include <cstring>
28 
29 #include "InterfaceFunctions.h"
30 #include "Handle.h"
31 #include "RefCountedObject.h"
32 #include "Record.h"
33 #include "DeepCopy.h"
34 #include "RefCountMacros.h"
35 #include "TypeName.h"
36 #include "VTableMap.h"
37 #include "Holder.h"
38 
39 namespace pdb {
40 
41 template <class ObjType>
42 int16_t getTypeID() {
43  static int16_t typeID = -1;
44 
45  // if we've never been here before, return the value we got last time
46  if (typeID != -1)
47  return typeID;
48 
49  // if we have a type not derived from Object, return -1
50  else if (!std::is_base_of<Object, ObjType>::value) {
51  return -1;
52 
53  // we have some other type name
54  } else {
55  std::string name = getTypeName<ObjType>();
56  // std :: cout << "to get ID for name =" << name << std :: endl;
57  typeID = VTableMap::getIDByName(getTypeName<ObjType>(), false);
58  // std :: cout << "typeId for name=" << name << "is " << typeID << std :: endl;
59  return typeID;
60  }
61 }
62 
63 #define CHAR_PTR(c) ((char*)c)
64 
65 inline void makeObjectAllocatorBlock(size_t numBytesIn, bool throwExceptionOnFail) {
66 
67 // JiaNote: replace following line with malloc results check
68 // getAllocator ().setupBlock (malloc (numBytesIn), numBytesIn, throwExceptionOnFail);
69 #ifdef INITIALIZE_ALLOCATOR_BLOCK
70  void* space = calloc(1, numBytesIn);
71 #else
72  void* space = malloc(numBytesIn);
73 #endif
74  if (space == nullptr) {
75  std::cout << "Fatal Error in makeObjectAllocatorBlock(): out of memory" << std::endl;
76  exit(-1);
77  }
78  getAllocator().setupBlock(space, numBytesIn, throwExceptionOnFail);
79 }
80 
81 inline void makeObjectAllocatorBlock(void* spaceToUse,
82  size_t numBytesIn,
83  bool throwExceptionOnFail) {
84  getAllocator().setupUserSuppliedBlock(spaceToUse, numBytesIn, throwExceptionOnFail);
85 }
86 
89 }
90 
91 inline void emptyOutContainingBlock(void* forMe) {
92  getAllocator().emptyOutBlock(forMe);
93 }
94 
95 inline unsigned getNumObjectsInAllocatorBlock(void* forMe) {
97 }
98 
101 }
102 
103 template <class ObjType>
106 }
107 
108 template <class ObjType>
110 
111  // first we see if the object is located in the current allocation block
112  if (getAllocator().contains(&forMe)) {
113 
114  // it is, so we can just return the RefCountedObject directly
116 
117  // otherwise, we need to do a deep copy to the current allocation block
118  } else {
119 
120  // get the space... allocate and set up the reference count before it
121  PDBTemplateBase temp;
122  temp.template setup<ObjType>();
123 
124 #ifdef DEBUG_OBJECT_MODEL
125  void* space = getAllocator().getRAM(
127 #else
128  void* space = getAllocator().getRAM(temp.getSizeOfConstituentObject(&forMe) +
130 #endif
131  // see if there was not enough RAM
132  if (space == nullptr) {
133  throw myException;
134  }
135 
136  // allocate the new space
138 
139  // set the ref count to zero
140  returnVal->setRefCount(0);
141  try {
142  setUpAndCopyFromTemplate<ObjType>(returnVal->getObject(), &forMe, nullptr);
143  } catch (NotEnoughSpace& n) {
144 #ifdef DEBUG_OBJECT_MODEL
145  getAllocator().freeRAM(returnVal, temp.getTypeCode());
146 #else
147  getAllocator().freeRAM(returnVal);
148 #endif
149  throw n;
150  }
151  // and get outta here
152  return returnVal;
153  }
154 }
155 
156 template <class ObjType, class... Args>
158 #ifdef DEBUG_OBJECT_MODEL
159  PDBTemplateBase temp;
160  temp.template setup<ObjType>();
161  std::cout << "to get RAM from allocator with size ="
162  << sizeof(ObjType) + REF_COUNT_PREAMBLE_SIZE << std::endl;
163 #endif
164  // create a new object
166 #ifdef DEBUG_OBJECT_MODEL
167  (getAllocator().getRAM(sizeof(ObjType) + REF_COUNT_PREAMBLE_SIZE, temp.getTypeCode()));
168 #else
169  (getAllocator().getRAM(sizeof(ObjType) + REF_COUNT_PREAMBLE_SIZE));
170 #endif
171 
172  // if we got a nullptr, get outta there
173  if (returnVal == nullptr) {
174  // std :: cout << "makeObject: return nullptr" << std :: endl;
175  return nullptr;
176  }
177  // std :: cout << "to call the placement new" << std :: endl;
178  // call the placement new
179  try {
180  new ((void*)returnVal->getObject()) ObjType(args...);
181  } catch (NotEnoughSpace& n) {
182 // for reference counting correctness
183 // returnVal->setRefCount(0);
184 // Handle<ObjType> temp = returnVal;
185 // std :: cout << "to free RAM for exception" << std :: endl;
186 #ifdef DEBUG_OBJECT_MODEL
187  getAllocator().freeRAM(returnVal, temp.getTypeCode());
188 #else
189  getAllocator().freeRAM(returnVal);
190 #endif
191  throw n;
192  }
193  // std :: cout << "set reference count = 0" << std :: endl;
194  // set the reference count
195  returnVal->setRefCount(0);
196 
197  // and return it
198  return returnVal;
199 }
200 
201 template <class ObjType, class... Args>
203 #ifdef DEBUG_OBJECT_MODEL
204  PDBTemplateBase temp;
205  temp.template setup<ObjType>();
206  std::cout << "In makeObjectWithExtraStorage:" << std::endl;
207  std::cout << "extra=" << extra << std::endl;
208  std::cout << "sizeof(ObjType)=" << sizeof(ObjType) << std::endl;
209  std::cout << "REF_COUNT_PREAMBLE_SIZE=" << REF_COUNT_PREAMBLE_SIZE << std::endl;
210  std::cout << "to get RAM from allocator with size ="
211  << extra + sizeof(ObjType) + REF_COUNT_PREAMBLE_SIZE << std::endl;
212 #endif
213  // create a new object
215 #ifdef DEBUG_OBJECT_MODEL
216 
217  (getAllocator().getRAM(extra + sizeof(ObjType) + REF_COUNT_PREAMBLE_SIZE,
218  temp.getTypeCode()));
219 #else
220  (getAllocator().getRAM(extra + sizeof(ObjType) + REF_COUNT_PREAMBLE_SIZE));
221 #endif
222  // if we got a nullptr, get outta there
223  if (returnVal == nullptr)
224  return nullptr;
225 
226  // std :: cout << "to call the placement new" << std :: endl;
227  // call the placement new
228  try {
229  new ((void*)returnVal->getObject()) ObjType(args...);
230  } catch (NotEnoughSpace& n) {
231 // added by Jia based on Chris' proposal
232 // for reference counting correctness
233 // returnVal->setRefCount(0);
234 // Handle<ObjType> temp = returnVal;
235 #ifdef DEBUG_OBJECT_MODEL
236  getAllocator().freeRAM(returnVal, temp.getTypeCode());
237 #else
238  getAllocator().freeRAM(returnVal);
239 #endif
240  throw n;
241  }
242  // std :: cout << "to set reference count = 0" << std :: endl;
243  // set the reference count
244  returnVal->setRefCount(0);
245 
246  // and return it
247  return returnVal;
248 }
249 
250 template <class ObjType>
252 
253  // get a pointer to the allocation block for this guy
254  void* res = getAllocator().getAllocationBlock(forMe);
255  if(res == nullptr) {
256 
257  std::cout << "the handle to get record is not in current allocation block" << std::endl;
258 
259  }
260  // and return that
261  return (Record<ObjType>*)res;
262 }
263 
264 template <class OutObjType, class InObjType>
266 
267  Handle<OutObjType> result;
268  result.offset = castMe.offset + (CHAR_PTR(&castMe) - CHAR_PTR(&result));
269  result.typeInfo = castMe.typeInfo;
270  result.getTarget()->incRefCount();
271  return result;
272 }
273 
274 template <class ObjType>
275 Record<ObjType>* getRecord(Handle<ObjType>& forMe, void* putMeHere, size_t numBytesAvailable) {
276 
277  // temporarily use the memory given by the caller
278  AllocatorState tempAllocator =
279  getAllocator().temporarilyUseBlockForAllocations(putMeHere, numBytesAvailable);
280 
281  Handle<ObjType> temp;
282  try {
283  // copy this guy over
284  temp = forMe.copyTargetToCurrentAllocationBlock();
285 
286  // if we get an exception, then restore the allocation block and throw the exception
287  // ourselves
288  } catch (NotEnoughSpace& n) {
289 
290  getAllocator().restoreAllocationBlock(tempAllocator);
291  throw n;
292  }
293 
294  // get a pointer to the allocation block for this guy
295  void* res = getAllocator().getAllocationBlock(temp);
296 
297  // put the old allocation block back
298  getAllocator().restoreAllocationBlock(tempAllocator);
299 
300  // and return that pointer
301  return (Record<ObjType>*)res;
302 }
303 
304 // added by Jia based on Chris' proposal
305 template <class TargetType>
307  // std :: cout << "create a handle for the Holder object" << std :: endl;
308  Handle<Holder<TargetType>> temp = makeObject<Holder<TargetType>>();
309  // std :: cout << "to do a deep copy" << std :: endl;
310  temp->child = copyMe; // since temp->child is physically located in the current allocation
311  // block, forces a deep copy
312  // std :: cout << "deep copy done" << std :: endl;
313  return temp->child;
314 };
315 }
316 
317 #endif
#define REF_COUNT_PREAMBLE_SIZE
RefCountedObject< ObjType > * getHandle(ObjType &forMe)
size_t getSizeOfConstituentObject(void *forMe) const
size_t getBytesAvailableInCurrentAllocatorBlock()
AllocatorState temporarilyUseBlockForAllocations(void *putMeHere, size_t numBytesAvailable)
Definition: Allocator.cc:793
Handle< TargetType > deepCopyToCurrentAllocationBlock(Handle< TargetType > &copyMe)
Allocator & getAllocator()
Definition: Allocator.cc:943
void setupBlock(void *where, size_t numBytesIn, bool throwExceptionOnFail)
Definition: Allocator.cc:712
void restoreAllocationBlock(AllocatorState &restoreMe)
Definition: Allocator.cc:846
NotEnoughSpace myException
RefCountedObject< ObjType > * makeObjectWithExtraStorage(size_t extra, Args &&...args)
#define CHAR_PTR(c)
Record< ObjType > * getRecord(Handle< ObjType > &forMe)
void * getAllocationBlock(Handle< ObjType > &forMe)
Definition: Allocator.cc:760
size_t getBytesAvailableInCurrentAllocatorBlock()
Definition: Allocator.cc:661
unsigned getNumObjectsInHomeAllocatorBlock(Handle< ObjType > &forMe)
void * getRAM(size_t howMuch)
Definition: Allocator.cc:557
int16_t getTypeID()
unsigned getNumObjectsInCurrentAllocatorBlock()
Definition: Allocator.cc:676
int16_t getTypeCode() const
RefCountedObject< ObjType > * makeObject(Args &&...args)
unsigned getNumObjectsInAllocatorBlock(void *forMe)
void setupUserSuppliedBlock(void *where, size_t numBytesIn, bool throwExceptionOnFail)
Definition: Allocator.cc:653
static int16_t getIDByName(std::string objectName, bool withLock=true)
Definition: VTableMap.cc:90
Handle< OutObjType > unsafeCast(Handle< InObjType > &castMe)
unsigned getNumObjectsInCurrentAllocatorBlock()
ObjType * getObject() const
void setRefCount(unsigned toMe)
void emptyOutBlock(void *here)
Definition: Allocator.cc:596
void freeRAM(void *here)
Definition: Allocator.cc:632
void makeObjectAllocatorBlock(size_t numBytesIn, bool throwExceptionOnFail)
unsigned getNumObjectsInAllocatorBlock(void *forMe)
Definition: Allocator.cc:681
void emptyOutContainingBlock(void *forMe)
unsigned getNumObjectsInHomeAllocatorBlock(Handle< ObjType > &forMe)
Definition: Allocator.cc:704