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

 

你可能感兴趣的:(array)