virtmem
virtual memory library for Arduino
base_vptr.h
Go to the documentation of this file.
1 #ifndef VIRTMEM_BASE_VPTR_H
2 #define VIRTMEM_BASE_VPTR_H
3 
9 #include "config/config.h"
10 #include "internal/alloc.h"
11 #include "utils.h"
12 
13 #include <stddef.h>
14 
15 namespace virtmem {
16 
17 #ifndef VIRTMEM_CPP11
18 class NILL_t;
19 #else
20 typedef nullptr_t NILL_t;
21 #endif
22 
23 namespace private_utils {
24 
25 template <bool, typename T1, typename T2> struct Conditional
26 {
27  typedef T1 type;
28 };
29 
30 template <typename T1, typename T2> struct Conditional<false, T1, T2>
31 {
32  typedef T2 type;
33 };
34 
35 }
36 
37 template <typename, typename> class VPtr;
38 
51 class BaseVPtr
52 {
53  struct Null { };
54 
55  // Safe bool idiom from boost::function
56  struct Dummy { void nonNull(void) { } };
57  typedef void (Dummy::*TSafeBool)(void);
58 
59  template <typename, typename> friend class VPtr;
60  template <typename> friend class VPtrLock;
61 
62 public:
66 #ifdef VIRTMEM_WRAP_CPOINTERS
67 #if defined(__x86_64__) || defined(_M_X64)
68  typedef __uint128_t PtrNum;
69 #elif defined(__i386) || defined(_M_IX86)
70  typedef uint64_t PtrNum;
71 #else
72  typedef private_utils::Conditional<(sizeof(intptr_t) > sizeof(VPtrNum)), intptr_t, VPtrNum>::type PtrNum;
73 #endif
74 #else
75  typedef VPtrNum PtrNum;
76 #endif
77 
78 private:
79 #ifdef VIRTMEM_WRAP_CPOINTERS
80  enum { WRAP_BIT = sizeof(PtrNum) * 8 - 1 }; // Last bit is used to check if wrapping real pointer
81 #endif
82 
83 protected:
84  // UNDONE
85  // For debug
86 #if defined(VIRTMEM_WRAP_CPOINTERS) && (defined(__x86_64__) || defined(_M_X64))
87  union
88  {
89  PtrNum ptr;
90  struct
91  {
92  VPtrNum addr, wrapped;
93  } ugh;
94  };
95 #else
96  PtrNum ptr;
97 #endif
98 
99  // @cond HIDDEN_SYMBOLS
100 #ifdef VIRTMEM_WRAP_CPOINTERS
101  // Return 'real' address of pointer, ie without wrapping bit
102  // static so that ValueWrapper can use it as well
103  static intptr_t getPtrNum(PtrNum p) { return p & ~((PtrNum)1 << WRAP_BIT); }
104  static void *unwrap(PtrNum p) { ASSERT(isWrapped(p)); return reinterpret_cast<void *>(getPtrNum(p)); }
105 #else
106  static intptr_t getPtrNum(PtrNum p) { return p; }
107 #endif
108  intptr_t getPtrNum(void) const { return getPtrNum(ptr); } // Shortcut
109  // @endcond
110 
111 public:
112 #ifdef VIRTMEM_CPP11
113  // Can only use these constructors on C++11, otherwise vptrs cannot be used with unions
114  BaseVPtr(void) = default; // Must have this to remain union compatible
115  BaseVPtr(NILL_t) : ptr(0) { }
116 #endif
117 
118 #ifdef VIRTMEM_WRAP_CPOINTERS
119 
125  static PtrNum getWrapped(PtrNum p) { return p | ((PtrNum)1 << WRAP_BIT); }
132  static bool isWrapped(PtrNum p) { return p & ((PtrNum)1 << WRAP_BIT); }
138  bool isWrapped(void) const { return isWrapped(ptr); }
139 #endif
140 
153  PtrNum getRawNum(void) const { return ptr; }
159  void setRawNum(PtrNum p) { ptr = p; }
160 
161 #ifdef VIRTMEM_WRAP_CPOINTERS
162 
167  static BaseVPtr wrap(const void *p)
168  {
169  BaseVPtr ret;
170  ret.ptr = getWrapped(reinterpret_cast<PtrNum>(p));
171  return ret;
172  }
173  void *unwrap(const BaseVPtr &p) { return unwrap(p); }
174  void *unwrap(void) { return unwrap(ptr); }
175  const void *unwrap(void) const { return unwrap(ptr); }
176 #endif
177 
178  // HACK: this allows constructing VPtr objects from BaseVPtr variables, similar to
179  // initializing non void pointers with a void pointer
180  // Note that we could have used a copy constructor in VPtr instead, but this would make the latter
181  // class non-POD
183  template <typename T, typename A> VIRTMEM_EXPLICIT operator VPtr<T, A>(void) const { VPtr<T, A> ret; ret.ptr = ptr; return ret; }
184 
185  // allow checking with NULL
193 #ifndef VIRTMEM_CPP11
194  inline bool operator==(const Null *) const { return getPtrNum() == 0; }
195  friend inline bool operator==(const Null *, const BaseVPtr &pw) { return pw.getPtrNum() == 0; }
196  inline bool operator!=(const Null *) const { return getPtrNum() != 0; }
197  friend inline bool operator!=(const Null *, const BaseVPtr &pw) { return pw.getPtrNum() != 0; }
198 #endif
199  inline bool operator==(const NILL_t &) const { return getPtrNum() == 0; }
200  friend inline bool operator==(const NILL_t &, const BaseVPtr &pw) { return pw.getPtrNum() == 0; }
201  inline bool operator!=(const NILL_t &) const { return getPtrNum() != 0; }
202  friend inline bool operator!=(const NILL_t &, const BaseVPtr &pw) { return pw.getPtrNum() != 0; }
204  inline operator TSafeBool (void) const { return getPtrNum() == 0 ? 0 : &Dummy::nonNull; }
205  // @}
206 
213  // UNDONE: _int128_t comparison sometimes fails??? Perhaps only check for ptrnums/iswrapped when on x86-64? Test this!
214 #if (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)) && defined(VIRTMEM_WRAP_CPOINTERS)
215  inline bool operator==(const BaseVPtr &pb) const { return getPtrNum() == pb.getPtrNum() && isWrapped() == pb.isWrapped(); }
216  inline bool operator!=(const BaseVPtr &pb) const { return getPtrNum() != pb.getPtrNum() && isWrapped() == pb.isWrapped(); }
217  inline bool operator<(const BaseVPtr &pb) const { return getPtrNum() < pb.getPtrNum() && isWrapped() == pb.isWrapped(); }
218  inline bool operator<=(const BaseVPtr &pb) const { return getPtrNum() <= pb.getPtrNum() && isWrapped() == pb.isWrapped(); }
219  inline bool operator>=(const BaseVPtr &pb) const { return getPtrNum() >= pb.getPtrNum() && isWrapped() == pb.isWrapped(); }
220  inline bool operator>(const BaseVPtr &pb) const { return getPtrNum() > pb.getPtrNum() && isWrapped() == pb.isWrapped(); }
221  // @}
222 #else
223  inline bool operator==(const BaseVPtr &pb) const { return ptr == pb.ptr; }
224  inline bool operator!=(const BaseVPtr &pb) const { return ptr != pb.ptr; }
225  inline bool operator<(const BaseVPtr &pb) const { return ptr < pb.ptr; }
226  inline bool operator<=(const BaseVPtr &pb) const { return ptr <= pb.ptr; }
227  inline bool operator>=(const BaseVPtr &pb) const { return ptr >= pb.ptr; }
228  inline bool operator>(const BaseVPtr &pb) const { return ptr > pb.ptr; }
229 #endif
230 
231 };
232 
233 }
234 
235 
236 #endif // VIRTMEM_BASE_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
PtrNum getRawNum(void) const
Returns a numeric representation of this virtual pointer.
Definition: base_vptr.h:153
static BaseVPtr wrap(const void *p)
Wraps a regular pointer.
Definition: base_vptr.h:167
void * unwrap(void)
Provide access to wrapped regular pointer (non static version).
Definition: base_vptr.h:174
This header file contains several variables that can be used to customize virtmem.
void setRawNum(PtrNum p)
Sets a virtual pointer from a numeric value.
Definition: base_vptr.h:159
#define VIRTMEM_EXPLICIT
Used for explicit conversion operators.
Definition: config.h:72
const void * unwrap(void) const
Provide access to wrapped regular pointer (non static const version).
Definition: base_vptr.h:175
uint32_t VPtrNum
Numeric type used to store raw virtual pointer addresses.
Definition: base_alloc.h:21
virtual memory class header
Creates a lock to some virtual data.
Definition: vptr_utils.h:76
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.
Virtual pointer class that provides an interface to access virtual much like 'regular pointers'...
Definition: alloc.h:15
BaseVPtr(NILL_t)
Construct from NILL/nullptr (C++11 only)
Definition: base_vptr.h:115
void * unwrap(const BaseVPtr &p)
Provide access to wrapped regular pointer.
Definition: base_vptr.h:173
static bool isWrapped(PtrNum p)
Returns whether a virtual pointer has wrapped a regular pointer.
Definition: base_vptr.h:132
This is the base class of VPtr and can be used for typeless pointers.
Definition: base_vptr.h:51