virtmem
virtual memory library for Arduino
vptr.h
Go to the documentation of this file.
1 #ifndef VIRTMEM_VPTR_H
2 #define VIRTMEM_VPTR_H
3 
9 #include "internal/alloc.h"
10 #include "base_vptr.h"
11 #include "config/config.h"
12 #include "utils.h"
13 
14 #include <stddef.h>
15 
16 namespace virtmem {
17 
18 template <typename T, typename TA> class VPtr;
19 
20 namespace private_utils {
21 
22 template <typename T> struct Dereferenced { typedef T type; }; // dummy for non pointers
23 template <typename T> struct Dereferenced<T *(*)()> { typedef T *type; }; // dummy for function pointers. // UNDONE: only handles 1 arg
24 template <typename T> struct Dereferenced<T *> { typedef T type; };
25 template <typename T, typename A> struct Dereferenced<VPtr<T, A> > { typedef T type; };
26 
27 // get pointer to variable, use char & cast to override any operator & overload
28 template <typename T> T *pointerTo(const T &val) { return (T *)&(char &)val; }
29 }
30 
45 template <typename T, typename TA> class VPtr : public BaseVPtr
46 {
47 public:
48  typedef T *TPtr;
49  typedef TA Allocator;
50 
51 private:
53 
54  static T *read(PtrNum p)
55  {
56  if (!p)
57  return 0;
58 #ifdef VIRTMEM_WRAP_CPOINTERS
59  if (isWrapped(p))
60  return static_cast<T *>(BaseVPtr::unwrap(p));
61 #endif
62  return static_cast<T *>(getAlloc()->read(p, sizeof(T)));
63  }
64  T *read(void) const { return read(ptr); }
65 
66  static void write(PtrNum p, const T *d)
67  {
68 #ifdef VIRTMEM_WRAP_CPOINTERS
69  if (isWrapped(p))
70  *(static_cast<T *>(BaseVPtr::unwrap(p))) = *d;
71  else
72 #endif
73  getAlloc()->write(p, d, sizeof(T));
74  }
75  void write(const T *d) { write(ptr, d); }
76 
77  ThisVPtr copy(void) const { ThisVPtr ret; ret.ptr = ptr; return ret; }
78  template <typename> friend class VPtrLock;
79 
80 public:
86  {
87  PtrNum ptr;
88 
89  ValueWrapper(PtrNum p) : ptr(p) { }
90  ValueWrapper(const ValueWrapper &);
91 
92  template <typename, typename> friend class VPtr;
93 
94  public:
99  inline operator T(void) const { return *read(ptr); }
100  template <typename T2> VIRTMEM_EXPLICIT inline operator T2(void) const { return static_cast<T2>(operator T()); }
101 
102 // ValueWrapper &operator=(const ValueWrapper &v)
103  // HACK: 'allow' non const assignment of types. In reality this makes sure we don't define
104  // the assignment operator twice for const types (where T == const T)
105  ValueWrapper &operator=(const typename VPtr<typename private_utils::AntiConst<T>::type, TA>::ValueWrapper &v)
106  {
107  ASSERT(ptr != 0);
108  if (ptr != v.ptr)
109  {
110  const T val = *read(v.ptr);
111  write(ptr, &val);
112  }
113  return *this;
114  }
115  // const conversion
116  ValueWrapper &operator=(const typename VPtr<const T, TA>::ValueWrapper &v)
117  {
118  ASSERT(ptr != 0);
119  if (ptr != v.ptr)
120  {
121  const T val = *read(v.ptr);
122  write(ptr, &val);
123  }
124  return *this;
125  }
126 
127  inline ValueWrapper &operator=(const T &v) { write(ptr, &v); return *this; }
128  inline ThisVPtr operator&(void) { ThisVPtr ret; ret.ptr = ptr; return ret; }
129 
130  // allow pointer to pointer access
131  // UNDONE: use member wrapper here?
132  inline T operator->(void) { return operator T(); }
133  inline const T operator->(void) const { return operator T(); }
134  inline typename VPtr<typename private_utils::Dereferenced<T>::type, TA>::ValueWrapper operator*(void) { return *operator T(); }
135  inline const typename VPtr<typename private_utils::Dereferenced<T>::type, TA>::ValueWrapper operator*(void) const { return *operator T(); }
136 
138  { return operator T()[i]; }
139  const typename VPtr<typename private_utils::Dereferenced<T>::type, TA>::ValueWrapper operator[](int i) const
140  { return operator T()[i]; }
141 
142  template <typename T2> inline bool operator==(const T2 &v) const { return operator T() == v; }
143  template <typename T2> inline bool operator!=(const T2 &v) const { return operator T() != v; }
144 
145  ValueWrapper &operator+=(int n) { T newv = operator T() + n; write(ptr, private_utils::pointerTo(newv)); return *this; }
146  ValueWrapper &operator-=(int n) { return operator+=(-n); }
147  ValueWrapper &operator*=(int n) { T newv = operator T() * n; write(ptr, private_utils::pointerTo(newv)); return *this; }
148  ValueWrapper &operator/=(int n) { T newv = operator T() / n; write(ptr, private_utils::pointerTo(newv)); return *this; }
149  ValueWrapper &operator++(void) { return operator +=(1); }
150  T operator++(int) { T ret = operator T(); operator++(); return ret; }
152  };
153 
154  // Based on Stroustrup's general wrapper paper (http://www.stroustrup.com/wrapper.pdf)
160  {
161  const PtrNum ptr;
162 
163  template <typename, typename> friend class VPtr;
164 
165  MemberWrapper(PtrNum p) : ptr(p) { }
166  MemberWrapper(const MemberWrapper &);
167 
168  MemberWrapper &operator=(const MemberWrapper &); // No assignment
169 
170  public:
171  ~MemberWrapper(void)
172  {
173 #ifdef VIRTMEM_WRAP_CPOINTERS
174  if (!isWrapped(ptr))
175 #endif
176  getAlloc()->releaseLock(ptr);
177  }
178 
184  T *operator->(void)
185  {
186 #ifdef VIRTMEM_WRAP_CPOINTERS
187  if (isWrapped(ptr))
188  return static_cast<T *>(BaseVPtr::unwrap(ptr));
189 #endif
190  return static_cast<T *>(getAlloc()->makeDataLock(getPtrNum(ptr), sizeof(T)));
191  }
192  const T *operator->(void) const
193  {
194 #ifdef VIRTMEM_WRAP_CPOINTERS
195  if (isWrapped(ptr))
196  return static_cast<T *>(BaseVPtr::unwrap(ptr));
197 #endif
198  return static_cast<T *>(getAlloc()->makeDataLock(getPtrNum(ptr), sizeof(T), true));
199  }
201  };
202 
203 #ifdef VIRTMEM_CPP11
204  // Can only use these constructors on C++11, otherwise vptrs cannot be used with unions
205  VPtr(void) = default; // Must have this to remain union compatible
206  VPtr(NILL_t) : BaseVPtr(nullptr) { }
207 #endif
208 
209 #ifdef VIRTMEM_WRAP_CPOINTERS
210 
236  static ThisVPtr wrap(const T *p)
237  {
238  ThisVPtr ret;
239  ret.ptr = getWrapped(reinterpret_cast<PtrNum>(p));
240  return ret;
241  }
249  static T *unwrap(const ThisVPtr &p) { return static_cast<T *>(BaseVPtr::unwrap(p)); }
255  T *unwrap(void) { return static_cast<T *>(BaseVPtr::unwrap(ptr)); }
261  const T *unwrap(void) const { return static_cast<const T *>(BaseVPtr::unwrap(ptr)); }
262 
263 #ifdef VIRTMEM_VIRT_ADDRESS_OPERATOR
264 
270  VPtr<ThisVPtr, Allocator> operator&(void) { VPtr<ThisVPtr, Allocator> ret = ret.wrap(this); return ret; }
271 
278  const VPtr *addressOf(void) const { return this; }
279  VPtr *addressOf(void) { return this; }
280 #endif
281  // @}
282 
283 #endif
284 
292  ValueWrapper operator*(void) { return ValueWrapper(ptr); }
293  MemberWrapper operator->(void) { return MemberWrapper(ptr); }
294  const MemberWrapper operator->(void) const { return MemberWrapper(ptr); }
295  const ValueWrapper operator[](int i) const { return ValueWrapper(ptr + (i * sizeof(T))); }
296  ValueWrapper operator[](int i) { return ValueWrapper(ptr + (i * sizeof(T))); }
298 
303  inline operator VPtr<const T, Allocator>(void) { VPtr<const T, Allocator> ret; ret.ptr = ptr; return ret; }
304  // pointer to pointer conversion
305  template <typename T2> VIRTMEM_EXPLICIT inline operator VPtr<T2, Allocator>(void) { VPtr<T2, Allocator> ret; ret.ptr = ptr; return ret; }
307 
313  // NOTE: int cast is necessary to deal with negative numbers
314  ThisVPtr &operator+=(int n) { ptr += (n * (int)sizeof(T)); return *this; }
315  inline ThisVPtr &operator++(void) { return operator +=(1); }
316  inline ThisVPtr operator++(int) { ThisVPtr ret = copy(); operator++(); return ret; }
317  inline ThisVPtr &operator-=(int n) { return operator +=(-n); }
318  inline ThisVPtr &operator--(void) { return operator -=(1); }
319  inline ThisVPtr operator--(int) { ThisVPtr ret = copy(); operator--(); return ret; }
320  inline ThisVPtr operator+(int n) const { return (copy() += n); }
321  inline ThisVPtr operator-(int n) const { return (copy() -= n); }
322  int operator-(const ThisVPtr &other) const { return (ptr - other.ptr) / sizeof(T); }
324 // inline bool operator!=(const TVirtPtr &p) const { return ptr != p.ptr; } UNDONE: need this?
325 
330  static inline Allocator *getAlloc(void) { return static_cast<Allocator *>(Allocator::getInstance()); }
331 };
332 
333 }
334 
335 
336 #endif // VIRTMEM_VPTR_H
contains all code from virtmem
Definition: base_alloc.cpp:22
PtrNum ptr
Numeric representation of this virtual pointer.
Definition: base_vptr.h:96
private_utils::Conditional<(sizeof(intptr_t) > sizeof(VPtrNum)), intptr_t, VPtrNum >::type PtrNum
Platform dependent numeric type to store raw (virtual/regular) pointer addresses. ...
Definition: base_vptr.h:72
void * unwrap(void)
Provide access to wrapped regular pointer (non static version).
Definition: base_vptr.h:174
VPtr(NILL_t)
Construct from NILL/nullptr (C++11 only)
Definition: vptr.h:206
T * TPtr
(non virtual) pointer type to the base type of this virtual pointer.
Definition: vptr.h:48
This header file contains several variables that can be used to customize virtmem.
#define VIRTMEM_EXPLICIT
Used for explicit conversion operators.
Definition: config.h:72
static Allocator * getAlloc(void)
Returns instance of allocator bound to this virtual pointer.
Definition: vptr.h:330
Proxy class used when member access is requested on a virtual pointer.
Definition: vptr.h:159
virtual memory class header
T * unwrap(void)
Provide access to wrapped regular pointer (non static version).
Definition: vptr.h:255
VPtr * addressOf(void)
Returns a regular pointer to the address of this virtual pointer.
Definition: vptr.h:279
VPtr< ThisVPtr, Allocator > operator&(void)
Returns a virtual pointer that has the memory address of this virtual pointer wrapped.
Definition: vptr.h:270
static T * unwrap(const ThisVPtr &p)
Provide access to wrapped regular pointer.
Definition: vptr.h:249
Proxy class returned when dereferencing virtual pointers.
Definition: vptr.h:85
const T * unwrap(void) const
Provide access to wrapped regular pointer (non static const version).
Definition: vptr.h:261
bool isWrapped(void) const
Returns whether a virtual pointer has wrapped a regular pointer (non static version).
Definition: base_vptr.h:138
static PtrNum getWrapped(PtrNum p)
Returns raw address of regular pointer wrapped by a virtual pointer.
Definition: base_vptr.h:125
Generalized NULL pointer class.
This file contains the virtual pointer base class.
static ThisVPtr wrap(const T *p)
Wraps a regular pointer.
Definition: vptr.h:236
const VPtr * addressOf(void) const
Returns a regular pointer to the address of this virtual pointer.
Definition: vptr.h:278
Virtual pointer class that provides an interface to access virtual much like 'regular pointers'...
Definition: alloc.h:15
TA Allocator
Allocator type used by this virtual pointer class.
Definition: vptr.h:49
This is the base class of VPtr and can be used for typeless pointers.
Definition: base_vptr.h:51