edit
[c11concurrency-benchmarks.git] / silo / marked_ptr.h
1 #ifndef _MARKED_PTR_H_
2 #define _MARKED_PTR_H_
3
4 #include <functional>
5 #include <iostream>
6
7 #include "macros.h"
8 #include "util.h"
9
10 template <typename T>
11 class marked_ptr {
12 public:
13
14   // can take the bottom 3 bits of a ptr [ptrs must be 8-byte aligned]
15   static const uintptr_t LowBitsMask = 0x7;
16
17   constexpr inline marked_ptr() : px(0) {}
18
19   template <typename U>
20   inline marked_ptr(U *px) : px(reinterpret_cast<uintptr_t>(px))
21   {
22     // type-safety
23     if (static_cast<T *>(px))
24       ;
25     INVARIANT(!(this->px & LowBitsMask));
26   }
27
28   // both operator= and copy-ctor PROPAGATE mark bits
29
30   template <typename U>
31   inline marked_ptr(const marked_ptr<U> &o)
32     : px(o.px)
33   {
34     // type-safety
35     if (static_cast<T *>((U *) nullptr))
36       ;
37   }
38
39   template <typename U>
40   inline marked_ptr &
41   operator=(const marked_ptr<U> &o)
42   {
43     // type-safety
44     if (static_cast<T *>((U *) nullptr))
45       ;
46     px = o.px;
47     return *this;
48   }
49
50   inline
51   operator bool() const
52   {
53     return get();
54   }
55
56   inline T *
57   operator->() const
58   {
59     return get();
60   }
61
62   inline T &
63   operator*() const
64   {
65     return *get();
66   }
67
68   inline T *
69   get() const
70   {
71     return reinterpret_cast<T *>(px & ~LowBitsMask);
72   }
73
74   template <typename U>
75   inline void
76   reset(U *px)
77   {
78     INVARIANT(!(px & LowBitsMask));
79     // type-safety
80     if (static_cast<T *>(px))
81       ;
82     this->px = reinterpret_cast<uintptr_t>(px);
83   }
84
85   inline uint8_t
86   get_flags() const
87   {
88     return px & LowBitsMask;
89   }
90
91   inline void
92   set_flags(uint8_t flags)
93   {
94     INVARIANT(!(flags & ~LowBitsMask));
95     px = (px & ~LowBitsMask) | flags;
96   }
97
98   inline void
99   or_flags(uint8_t flags)
100   {
101     INVARIANT(!(flags & ~LowBitsMask));
102     px |= flags;
103   }
104
105   template <typename U>
106   inline bool
107   operator==(const marked_ptr<U> &o) const
108   {
109     return get() == o.get();
110   }
111
112   template <typename U>
113   inline bool
114   operator!=(const marked_ptr<U> &o) const
115   {
116     return !operator==(o);
117   }
118
119   template <typename U>
120   inline bool
121   operator<(const marked_ptr<U> &o) const
122   {
123     return get() < o.get();
124   }
125
126   template <typename U>
127   inline bool
128   operator>=(const marked_ptr<U> &o) const
129   {
130     return !operator<(o);
131   }
132
133   template <typename U>
134   inline bool
135   operator>(const marked_ptr<U> &o) const
136   {
137     return get() > o.get();
138   }
139
140   template <typename U>
141   inline bool
142   operator<=(const marked_ptr<U> &o) const
143   {
144     return !operator>(o);
145   }
146
147 private:
148   uintptr_t px;
149 };
150
151 template <typename T>
152 inline std::ostream &
153 operator<<(std::ostream &o, const marked_ptr<T> &p)
154 {
155   o << "[px=" << util::hexify(p.get()) << ", flags=0x" << util::hexify(p.get_flags()) << "]";
156   return o;
157 }
158
159 namespace std {
160   template <typename T>
161   struct hash<marked_ptr<T>> {
162     inline size_t
163     operator()(marked_ptr<T> p) const
164     {
165       return hash<T *>()(p.get());
166     }
167   };
168 }
169
170 #endif /* _MARKED_PTR_H_ */