C++ BitArray 引用计数实现

  1 #ifndef __BITARRAY__  //数组不支持多线程同时访问,没有对引用计数以及分配的资源做任何锁处理
  2 #define __BITARRAY__ 1 //越界访问修改为抛出异常
  3 
  4 #ifdef __BIT_DEBUG__  //__BIT_DEBUG__是调试用的宏定义
  5 #include <cstdio>
  6 #endif
  7 
  8 #ifdef __cplusplus > 201103L
  9 #include <cstdint>
 10 #else
 11 #include <stdint.h>
 12 #define nullptr NULL
 13 #define noexcept throw()
 14 #endif
 15 
 16 #define __BIT_ERRMSG_LEN__ 512
 17 
 18 #include <cstring>
 19 #include <stdexcept>
 20 
 21 class BitArray
 22 {
 23 private:
 24     enum __e_bit_size {bit = 8};
 25     
 26     class __Ref_Array  //引用计数类
 27     {
 28     public:
 29         __Ref_Array(int64_t __size)
 30         :m_ref_count(0), m_size(__size)
 31         {
 32 #ifdef __BIT_DEBUG__
 33             fprintf(stderr, "__Ref_Array ctor @addr: %p with size:%ld\n", this, __size);
 34 #endif
 35             init();
 36         }
 37         
 38         ~__Ref_Array()
 39         {
 40 #ifdef __BIT_DEBUG__
 41             fprintf(stderr, "__Ref_Array dtor @addr: %p with size:%ld\n", this, __size);
 42 #endif
 43             delete[] m_array;
 44         }
 45         
 46         __Ref_Array(const __Ref_Array& o)
 47         :m_ref_count(1),
 48          m_size(o.m_size),
 49          m_array_size(o.m_array_size),
 50          m_used(o.m_used)
 51         {
 52 #ifdef __BIT_DEBUG__
 53             fprintf(stderr, "__Ref_Array copytor @addr: %p with @addr: %p && size:%ld\n", this, &o, __size);
 54 #endif
 55             m_array = new int8_t[m_array_size];
 56             memcpy(m_array, o.m_array, m_array_size);
 57         }
 58         
 59         inline bool
 60         get(int64_t __pos) const
 61         {return *(m_array + slot_bit(__pos)) & mask(__pos);}
 62         
 63         inline void
 64         set(int64_t __pos)
 65         {
 66             *(m_array + slot_bit(__pos)) |= mask(__pos);
 67             m_used ++;
 68         }
 69         
 70         inline void
 71         clear(int64_t __pos)
 72         {
 73             *(m_array + slot_bit(__pos)) &= ~mask(__pos);
 74             m_used --;
 75         }
 76         
 77         inline void
 78         reset()
 79         {
 80             std::memset(m_array, 0, m_array_size);
 81             m_used = 0;
 82         }
 83         
 84         inline int64_t
 85         length() const
 86         {return m_size;}
 87         
 88         inline int64_t
 89         size() const
 90         {return m_size;}
 91         
 92         inline int64_t
 93         used() const
 94         {return m_used;}
 95         
 96         inline int64_t
 97         refCount() const
 98         {return m_ref_count;}
 99         
100         inline bool
101         sizeRange(int64_t __pos) const
102         {return __pos >= 0 && __pos < m_size;}
103         
104         inline int64_t
105         sharedPlus()
106         {return ++ m_ref_count;}
107         
108         inline int64_t
109         sharedSub()
110         {return -- m_ref_count;}
111         
112         inline bool
113         isShared() const
114         {return m_ref_count > 1;}
115         
116     private:        
117         inline void
118         init()
119         {
120             m_array_size = nslot(m_size);
121             m_array = new int8_t[m_array_size];
122             reset();
123         }
124         
125         inline int64_t
126         slot_bit(int64_t __n) const
127         {return __n / bit;}
128         
129         inline int64_t
130         nslot(int64_t __size) const
131         {return slot_bit(__size + bit - 1);}
132         
133         inline int8_t
134         mask(int64_t __pos) const
135         {return int8_t(1) << (__pos % bit);}
136         
137     private:
138         int8_t    m_array;    //位数组存储
139         int64_t    m_ref_count; //引用计数
140         int64_t    m_size;    //引用计数大小
141         int64_t m_array_size;  //分配的int8_t数组大小
142         int64_t m_used;      //已经使用的bit位数
143     };
144     
145 private:
146     class BitProxy  //代理类  为了区分 x = ba[?]; 和 ba[?];
147     {
148         BitProxy(BitArray& ba, int64_t pos)
149         :m_array(ba), m_pos(pos)
150         {}
151         
152         BitProxy& operator = (const BitProxy& rh)
153         {
154             if(rh)
155                 m_array.set(m_pos);
156             else{
157                 m_array.clear(m_pos);
158             }
159             
160             return *this;
161         }
162         
163         BitProxy& operator = (bool status)
164         {
165             if(status)
166                 m_array.set(m_pos);
167             else{
168                 m_array.clear(m_pos);
169             }
170             
171             return *this;
172         }
173         
174         operator bool() const
175         {
176             return m_array.get(m_pos);
177         }
178         
179     private:
180         BitArray& m_array;
181         int64_t    m_pos;
182     };
183     
184 public:
185     
186     BitArray() noexcept //无参数构造函数
187     :m_ref(nullptr)
188     {
189 #ifdef __BIT_DEBUG__
190         fprintf(stderr, "BitArray ctor @addr: %p with nullptr ...\n", this);
191 #endif
192     }
193     
194     BitArray(int64_t size) noexcept //构造函数
195     :m_ref(size > 0 new __Ref_Array(size) : nullptr)
196     {
197 #ifdef __BIT_DEBUG__
198         fprintf(stderr, "BitArray ctor @addr: %p with size: %d ...\n", this, size);
199 #endif
200     }
201     
202     ~BitArray()  //析构函数
203     {release()}
204     
205     BitArray(const BitArray& o) noexcept  //copy构造函数
206     m_ref(o.m_ref)
207     {
208 #ifdef __BIT_DEBUG__
209         fprintf(stderr, "BitArray copy tor @addr: %p with other BitArray @addr: %p ...\n", this, &o);
210 #endif
211     }
212     
213 #ifdef __cplusplus >= 201103L
214     BitArray(BitArray&& o) noexcept  //move构造函数
215     m_ref(o.m_ref)
216     {
217 #ifdef __BIT_DEBUG__
218         fprintf(stderr, "BitArray move tor @addr: %p <--- other BitArray @addr: %p ...\n", this, &o);
219 #endif
220         o.m_ref = nullptr;
221     }
222 #endif
223     
224     BitArray& operator=(const BitArray& o)  //赋值运算符
225     {
226         if(m_ref != o.m_ref)
227         {
228             release();
229             m_ref = o.m_ref;
230 #ifdef __BIT_DEBUG__
231         fprintf(stderr, "BitArray assign @addr: %p with other BitArray @addr: %p ...\n", this, &o);
232 #endif
233             if(m_ref)
234                 m_ref->sharedPlus();
235         }
236     }
237     
238     const BitProxy
239     operator[] (int64_t pos) const  //下标运算符
240     {return BitProxy(const_cast<BitArray&>(*this), pos);}
241     
242     BitProxy
243     operator[] (int64_t pos)  //下标运算符
244     {return BitProxy(*this, pos);}
245     
246 public:
247     inline bool
248     get(int64_t pos) const throw(std::out_of_range)
249     {
250         if(!m_ref || !m_ref->sizeRange(pos))
251         {
252             char errmsg[__BIT_ERRMSG_LEN__] = {0};
253             
254             snprintf(errmsg, sizeof(errmsg), "out of range in get -> pos : %d | size : %d\n", pos, size());
255             
256             throw std::out_of_range(errmsg);
257         }
258         else
259             return m_ref->get(pos);
260     }
261     
262     inline bool
263     set(int64_t pos) const throw(std::out_of_range)
264     {
265         if(!m_ref || !m_ref->sizeRange(pos))
266         {
267             char errmsg[__BIT_ERRMSG_LEN__] = {0};
268             
269             snprintf(errmsg, sizeof(errmsg), "out of range in set -> pos : %d | size : %d\n", pos, size());
270             
271             throw std::out_of_range(errmsg);
272         }
273         else if(m_ref->get(pos))
274         {
275             return true;
276         }
277         else
278         {
279             if(m_ref->isShared())
280             {
281                 __Ref_Array* last_ref = m_ref;
282                 
283                 m_ref = new __Ref_Array(*last_ref);
284                 
285                 last_ref->sharedSub();
286             }
287             
288             return m_ref->get(pos);
289         }
290     }
291     
292     
293     inline bool
294     clear(int64_t pos) const throw(std::out_of_range)
295     {
296         if(!m_ref || !m_ref->sizeRange(pos))
297         {
298             char errmsg[__BIT_ERRMSG_LEN__] = {0};
299             
300             snprintf(errmsg, sizeof(errmsg), "out of range in clear -> pos : %d | size : %d\n", pos, size());
301             
302             throw std::out_of_range(errmsg);
303         }
304         else if(!m_ref->get(pos))
305         {
306             return true;
307         }
308         else
309         {
310             if(m_ref->isShared())
311             {
312                 __Ref_Array* last_ref = m_ref;
313                 
314                 m_ref = new __Ref_Array(*last_ref);
315                 
316                 last_ref->sharedSub();
317             }
318             
319             return m_ref->clear(pos);
320         }
321     }
322     
323     inline void
324     reset()
325     {if(m_ref) m_ref->reset();}
326     
327     inline int64_t
328     size()
329     {return m_ref ? m_ref->size() : 0;}
330     
331     inline int64_t
332     length()
333     {return m_ref ? m_ref->length() : 0;}
334     
335     inline int64_t
336     count()
337     {return m_ref ? m_ref->count() : 0;}    
338 private:
339     inline void
340     release()  //引用计数释放
341     {
342 #ifdef __BIT_DEBUG__
343         fprintf(stderr, "BitArray released @addr: %p  current reference : %d ...\n", this, m_ref->refCount());
344 #endif
345         if(m_ref && (m_ref->sharedSub() == 0))
346         {
347             delete m_ref;
348             m_ref = null;
349         }
350     }
351     
352     __Ref_Array* m_ref;
353 };
354 
355 #endif

 

posted @ 2015-01-03 11:41  araraloren  阅读(706)  评论(0)    收藏  举报