OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
RefBlock.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  *
7  * Visit http://people.web.psi.ch/adelmann/ for more details
8  *
9  ***************************************************************************/
10 
11 /***********************************************************************
12 
13 This little gadget lets you allocate an array of elements of type T
14 and reference count the whole block. As long as you refer to the block
15 using objects of the type RefBlockP it will keep the block around. As
16 soon as the last RefBlockP that refers to the block is deleted, it
17 deletes the block.
18 
19 You create a block like: RefBlockP<T> p(size)
20 Then you use p like a pointer. Pointer operations are as efficient as
21 with a bare pointer as long as bounds checking is off.
22 
23 It has a second template argument for whether to do bounds checking.
24 It defaults to the value of the preprocessor symbol
25 REFBLOCK_BOUNDS_CHECK_DEFAULT. If you don't define that symbol it
26 is set to false, for no bounds checking.
27 
28 To turn bounds checking on for your whole code define
29 REFBLOCK_BOUNDS_CHECK_DEFAULT as true.
30 
31 To turn bounds checking on for a particular RefBlockP you
32 declare it like:
33 
34 RefBlockP<T,true> p;
35 
36 To turn it off you declare it as:
37 
38 RefBlockP<T,false> p;
39 
40 ***********************************************************************/
41 
42 #ifndef REF_BLOCK_H
43 #define REF_BLOCK_H
44 
45 // include files
46 #include "Utility/RefCounted.h"
47 
48 #include <cassert>
49 #include <cstddef>
50 
51 //----------------------------------------------------------------------
52 #ifndef REFBLOCK_BOUNDS_CHECK_DEFAULT
53 # ifndef BOUNDS_CHECK_DEFAULT
54 # define REFBLOCK_BOUNDS_CHECK_DEFAULT false
55 # else
56 # define REFBLOCK_BOUNDS_CHECK_DEFAULT BOUNDS_CHECK_DEFAULT
57 # endif
58 #endif
59 
60 template<class T, bool BoundsCheck=REFBLOCK_BOUNDS_CHECK_DEFAULT>
61 class RefBlockP
62 {
63  //
64  // Allow the other bounds checking polarity to look in here.
65  //
66 // friend class RefBlockP<T,!BoundsCheck>;
67 
68 private:
69  //
70  // A simple class that has the pointer to the beginning of the block.
71  // Because it is refcounted, when the last reference to the
72  // block goes away, this dies and takes the block with it.
73  //
75  {
76  public:
77  T* P;
78  T* Pend;
79  bool Dealloc;
80  RefBlockController(T *p, size_t size)
81  : P(p),Pend(p+size),Dealloc(false)
82  {
83  }
84  RefBlockController(size_t size)
85  : P(new T[size]),Pend(P+size),Dealloc(true)
86  {
87  }
89  {
90  if (Dealloc)
91  delete P;
92  }
94  {
95  return P;
96  }
97  bool checkDeref(T* p)
98  {
99  return (P<=p) && (p<Pend) ;
100  }
101  };
102 
103  //
104  // We have two data items in each RefBlockP:
105  // A bare pointer that points somewhere in the block.
106  // A refcounted pointer to the block controller.
107  //
108  T* P;
110 
111 public:
112 
113  //
114  // Null ctor for arrays. Initialize w/ null ptr.
115  //
116  RefBlockP() : P(0) {}
117 
118  //
119  // Initialize a block of a given size.
120  //
121  RefBlockP(size_t size)
122  : Controller(new RefBlockController(size))
123  {
124  P = Controller->getBlock();
125  }
126 
127  //
128  // Initialize with a user allocated pointer.
129  // This turns off the deallocation but not the bounds checking.
130  //
131  RefBlockP(T* p, size_t size)
132  : P(p), Controller( new RefBlockController(p,size) )
133  {
134  }
135 
136  // Copy ctor and assignment
138  : P(b.P), Controller(b.Controller)
139  {
140  }
142  {
143  P = rhs.P;
144  Controller = rhs.Controller;
145  return *this;
146  }
147 
148  // Copy ctor and assignment from a RefBlockP opposite bounds checking.
149 // RefBlockP(const RefBlockP<T,!BoundsCheck>& b)
150 // : P(b.P), Controller(b.Controller)
151 // {
152 // }
153 // RefBlockP<T,BoundsCheck>& operator=(const RefBlockP<T,!BoundsCheck>& rhs)
154 // {
155 // P = rhs.P;
156 // Controller = rhs.Controller;
157 // return *this;
158 // }
159 
160  //
161  // Provide all the usual pointer manipulation functions.
162  // Each one makes sure it is legal to do the operation if
163  // it is marked for bounds checking.
164  // Because BoundsCheck is a compile time parameter, if you don't use it
165  // the asserts will be optimized away.
166  //
168  {
169  ++P;
170  return *this;
171  }
173  {
174  RefBlockP<T> save(*this);
175  ++P;
176  return save;
177  }
179  {
180  --P;
181  return *this;
182  }
184  {
185  RefBlockP<T,BoundsCheck> save(*this);
186  --P;
187  return save;
188  }
189 
190  T& operator*() const
191  {
192  if ( BoundsCheck )
193  assert( Controller->checkDeref(P) );
194  return *P;
195  }
196  T& operator[](int i) const
197  {
198  T* p = P+i;
199  if ( BoundsCheck )
200  assert( Controller->checkDeref(p) );
201  return *p;
202  }
203  T* operator->() const
204  {
205  if ( BoundsCheck )
206  assert( P==0 || Controller->checkDeref(P) );
207  return P;
208  }
209 
210  void operator+=(int i)
211  {
212  P += i;
213  }
214  void operator-=(int i)
215  {
216  P -= i;
217  }
218 
220  {
221  RefBlockP<T,BoundsCheck> ret(*this);
222  ret += i;
223  return ret;
224  }
226  {
227  RefBlockP<T,BoundsCheck> ret(*this);
228  ret -= i;
229  return ret;
230  }
231 
232  bool operator==(const RefBlockP<T,BoundsCheck>& a) const
233  {
234  return P == a.P;
235  }
236 // bool operator==(const RefBlockP<T,!BoundsCheck>& a) const
237 // {
238 // return P == a.P;
239 // }
240 
241  void invalidate()
242  {
243  Controller.invalidate();
244  P = 0;
245  }
246  bool valid()
247  {
248  return P!=0;
249  }
250 
251  //
252  // If something needs a T*, convert it.
253  //
254  operator T*() const
255  {
256  return P;
257  }
258 };
259 
261 
262 #endif // REF_BLOCK_H
263 
264 /***************************************************************************
265  * $RCSfile: RefBlock.h,v $ $Author: adelmann $
266  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $
267  * IPPL_VERSION_ID: $Id: RefBlock.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $
268  ***************************************************************************/
RefCountedP< RefBlockController > Controller
Definition: RefBlock.h:109
RefBlockP< T, BoundsCheck > & operator=(const RefBlockP< T, BoundsCheck > &rhs)
Definition: RefBlock.h:141
Definition: rbendmap.h:8
RefBlockP< T, BoundsCheck > & operator--()
Definition: RefBlock.h:178
RefBlockP()
Definition: RefBlock.h:116
T & operator*() const
Definition: RefBlock.h:190
RefBlockController(size_t size)
Definition: RefBlock.h:84
bool valid()
Definition: RefBlock.h:246
RefBlockP< T, BoundsCheck > operator-(int i)
Definition: RefBlock.h:225
T * operator->() const
Definition: RefBlock.h:203
void operator-=(int i)
Definition: RefBlock.h:214
T & operator[](int i) const
Definition: RefBlock.h:196
void invalidate()
Definition: RefBlock.h:241
RefBlockController(T *p, size_t size)
Definition: RefBlock.h:80
bool operator==(const RefBlockP< T, BoundsCheck > &a) const
Definition: RefBlock.h:232
RefBlockP< T, BoundsCheck > operator--(int)
Definition: RefBlock.h:183
void operator+=(int i)
Definition: RefBlock.h:210
RefBlockP< T, BoundsCheck > & operator++()
Definition: RefBlock.h:167
RefBlockP(T *p, size_t size)
Definition: RefBlock.h:131
RefBlockP< T, BoundsCheck > operator+(int i)
Definition: RefBlock.h:219
RefBlockP< T, BoundsCheck > operator++(int)
Definition: RefBlock.h:172
RefBlockP(const RefBlockP< T, BoundsCheck > &b)
Definition: RefBlock.h:137
RefBlockP(size_t size)
Definition: RefBlock.h:121