NeoPZ
tpzautopointer.h
Go to the documentation of this file.
1 
6 #ifndef TPZAUTOPOINTER_H
7 #define TPZAUTOPOINTER_H
8 
9 #include "pz_pthread.h"
10 
19 #define AP_MUTEX_ARRAY_SZ 512
20 
21 /* Define PROFILE_AP_MUTEXES if you want to profile the autopointer mutexes use. */
22 //#define PROFILE_AP_MUTEXES
23 
24 #ifdef PROFILE_AP_MUTEXES
25 extern uint64_t ap_mutex_accesses[];
26 #endif
27 
28 #define AP_MUTEX_HASH_1 \
29 addr = (addr >> 32) ^ addr; \
30 addr = (addr >> 16) ^ addr; \
31 addr = (addr >> 8) ^ addr; \
32 addr = (addr >> 4) ^ addr; \
33 i = (unsigned) (addr % AP_MUTEX_ARRAY_SZ)
34 
35 #define AP_MUTEX_HASH_2 \
36 addr = (addr >> 8) ^ addr; \
37 addr = (addr >> 4) ^ addr; \
38 i = (unsigned) (addr % AP_MUTEX_ARRAY_SZ)
39 
40 extern pthread_mutex_t gAutoPointerMutexArray[];
41 inline pthread_mutex_t* get_ap_mutex(void* obj)
42 {
43  unsigned i;
44  uint64_t addr = (uint64_t) obj;
45  // AP_MUTEX_HASH_1;
47 #ifdef PROFILE_AP_MUTEXES
48  ap_mutex_accesses[i]++;
49 #endif
50  return &(gAutoPointerMutexArray[i]);
51 }
52 
53 #include <stdlib.h>
54 
55 
56 
61 template<class T>
62 class TPZAutoPointer {
63 
65  template<class T2>
66  struct TPZReference
67  {
69  T2 *fPointer;
70  int *fCounter;
71 
73  {
74  fPointer = nullptr;
75  fCounter = new int;
76  (*fCounter) = 1;
77  }
78 
79  TPZReference(T2 *pointer)
80  {
81  fPointer = pointer;
82  fCounter = new int;
83  (*fCounter) = 1;
84  }
85 
87  {
88  if(fPointer) {
89  delete fPointer;
90  }
91  fPointer = nullptr;
92  if(fCounter) {
93  delete fCounter;
94  }
95  fCounter = nullptr;
96  }
97 
98  void ReallocForNuma(int node_id)
99  {
100  // -2: Do not realloc
101  // -1: Realloc to the node that is currently running this thread.
102  // node_id>=0 : Realloc to node_id
103 
104  if (node_id == -2) return;
105 
106  //TODO: Currently relying on first-touch policy to implement case -1
107 
108  T2* old = fPointer;
109  fPointer = (T2*) fPointer->Clone();
110  delete old;
111  }
112 
113 
115  bool Increment()
116  {
117  if(PZ_PTHREAD_MUTEX_LOCK(get_ap_mutex((void*) this), __PRETTY_FUNCTION__))
118  return false;
119  (*fCounter)++;
120  PZ_PTHREAD_MUTEX_UNLOCK(get_ap_mutex((void*) this), __PRETTY_FUNCTION__);
121  return true;
122  }
124  bool Decrease()
125  {
126  bool should_delete = false;
127  if(PZ_PTHREAD_MUTEX_LOCK(get_ap_mutex((void*) this), __PRETTY_FUNCTION__))
128  return false;
129  (*fCounter)--;
130 
131  if((*fCounter) <= 0) should_delete = true;
132 
133  PZ_PTHREAD_MUTEX_UNLOCK(get_ap_mutex((void*) this), __PRETTY_FUNCTION__);
134  if(should_delete)
135  {
136  delete this;
137  }
138  return true;
139  }
140 
141  };
142 
144  TPZReference<T> *fRef;
145 
146 public:
149  {
150  fRef = new TPZReference<T>();
151  }
152 
155  {
156  if (fRef){
157  fRef->Decrease();
158  }
159  }
160 
163  {
164  fRef = new TPZReference<T>(obj);
165  }
166 
169  {
170  fRef = copy.fRef;
171  fRef->Increment();
172  }
173 
176  if (fRef) {
177  fRef->Decrease();
178  }
179  fRef = copy.fRef;
180  copy.fRef = nullptr;
181  return *this;
182  }
183 
186  {
187  if(copy.fRef == fRef) return *this;
188  copy.fRef->Increment();
189  fRef->Decrease();
190  fRef = copy.fRef;
191  return *this;
192  }
193 
195  operator T&()
196  {
197  return *(fRef->fPointer);
198  }
199 
201  T& operator *() const
202  {
203  return *(fRef->fPointer);
204  }
205 
208  {
209  return *(fRef->fPointer);
210  }
211 
213  T *operator->() const
214  {
215  return fRef->fPointer;
216  }
218  {
219  return fRef->fPointer;
220  }
221 
222  void ReallocForNuma(int node)
223  {
224  fRef->ReallocForNuma(node);
225  }
226 
228  operator bool() const{
229  return (this->fRef->fPointer != nullptr);
230  }
231  operator bool() {
232  return fRef->fPointer != nullptr;
233  }
234 
236  int Count() const
237  {
238  return *(fRef->fCounter);
239  }
240  int Count()
241  {
242  return *(fRef->fCounter);
243  }
244  template<typename R, typename T2>
246 };
247 
248 template<typename R, typename T>
251  R* p;
252  if ( (p = dynamic_cast<R*> (in.operator->())) ) {
253  rv.fRef->fPointer = dynamic_cast<R*> (in.fRef->fPointer);
254  delete rv.fRef->fCounter;
255  rv.fRef->fCounter = in.fRef->fCounter;
256  rv.fRef->Increment();
257  }
258  return rv;
259 }
260 
263 #endif
#define PZ_PTHREAD_MUTEX_UNLOCK(mutex, fn)
Definition: pz_pthread.h:79
T2 * fPointer
Pointer to T2 object.
#define AP_MUTEX_HASH_2
bool Increment()
Increment the counter.
friend TPZAutoPointer< R > TPZAutoPointerDynamicCast(TPZAutoPointer< T2 > in)
bool Decrease()
Decrease the counter. If the counter is zero, delete myself.
int Count() const
Returns the counter value.
TPZAutoPointer(const TPZAutoPointer< T > &copy)
Share the pointer of the copy.
#define PZ_PTHREAD_MUTEX_LOCK(mutex, fn)
Definition: pz_pthread.h:76
pthread_mutex_t gAutoPointerMutexArray[]
~TPZAutoPointer()
The destructor will delete the administered pointer if its reference count is zero.
void ReallocForNuma(int node_id)
pthread_mutex_t * get_ap_mutex(void *obj)
TPZReference< T > * fRef
The object which contains the pointer and the reference count.
TPZAutoPointer(T *obj)
This method will create an object which will administer the area pointed to by obj.
TPZAutoPointer & operator=(TPZAutoPointer< T > &&copy)
Move assignment operator.
T * operator->() const
Returns the pointer for referenced object.
T & operator*() const
Returns the referenced object.
TPZAutoPointer()
Creates an reference counted null pointer.
TPZAutoPointer & operator=(const TPZAutoPointer< T > &copy)
Assignment operator.
void ReallocForNuma(int node)
obj
Definition: test.py:225
This class implements a reference counter mechanism to administer a dynamically allocated object...