OSDN Git Service

delimiter.h/cppを、term_lexer、term_checkerとしてテンプレートを利用するように分離した。
[simplecms/utakata.git] / lib / smart_ptr.h
1 // 参照カウンタによるスマートポインタを提供します。
2 //
3 // ここで定義されるスマートポインタは、scoped_ptrとは異なり、
4 // 最終的に参照しているデータが、解体責任を負う点で異なります。
5 // 最終的に参照しているデータを判定するため、参照カウンタ形式で
6 // 解体責任を移譲していきます。
7 //
8 // また、このスマートポインタは配列を扱うことができます。
9 //
10 // example
11 // -------
12 // smart_ptr<CHoge> h(new CHoge());
13 //
14 // smart_ptr<CHoge> ha();
15 // h.add(new CHuga);
16
17 #ifndef _UTAKATA_LIB_SMART_PTR_H_
18 #define _UTAKATA_LIB_SMART_PTR_H_
19
20 #include "lib/ref_delete.h"
21
22 namespace akebono {
23
24 template<class T> class smart_ptr {
25  public:
26   template<class S> explicit
27   smart_ptr(S* p, bool owner = true, ref_delete_base* ref = NULL) :
28       obj_(NULL),ref_obj_(NULL) {
29     if (p != NULL) {
30       init(p,owner, ref);
31     }
32   }
33
34   //デフォルトコンストラクタ
35   smart_ptr() : obj_(NULL),ref_obj_(NULL) {}
36
37   //コピーコンストラクタ
38   smart_ptr(const smart_ptr<T>& p) :
39       obj_(NULL),ref_obj_(NULL) {
40     //参照カウントを増やしつつ、コピー。
41     inc(p);
42   }
43
44   // 自分にコピーされる前に、前のオブジェクトの参照カウントを
45   // 減らしておく。
46   smart_ptr<T>& operator=(const smart_ptr<T>& obj) {
47     dec();
48
49     smart_ptr<T> tmp(obj);
50     swap(tmp);
51     return *this;
52   }
53
54   //参照数を減らすだけ。
55   virtual ~smart_ptr() {dec();}
56
57   //明示的に削除するための構文
58   virtual void release() {dec();}
59
60   //ここからは、ポインタの振りをするための仕掛け。
61   T& operator*() const {return *get();}
62   T* operator->() const {return get();}
63
64   // 同一かどうかをチェックする。
65   bool operator==(const smart_ptr<T>& rh) const {
66     return obj_ == rh.obj_;
67   }
68
69   bool operator!=(const smart_ptr<T>& rh) const {
70     return !(*this.obj_ == rh.obj_);
71   }
72
73   // 現在保持しているポインタを明示的に返します。
74   T* get() const {
75     if (ref_obj_ == NULL) {
76       return NULL;
77     }
78
79     return obj_;
80   }
81
82   // 内部で参照しているオブジェクトがNULLであるかどうかを返します。
83   bool is_null() const {
84     return ref_obj_ == NULL && obj_ == NULL;
85   }
86
87   // オブジェクトが単一の場所からのみ参照されているか。
88   bool is_only_ref() const {
89     return ref_obj_->reference() == 1;
90   }
91
92   //=============================================
93   //追加生成関数群
94   //=============================================
95
96   // 渡されたsmart_ptrが格納しているオブジェクトを参照するようにします。
97   // テンプレートパラメータSは、Tの派生クラスである必要があります。
98   template<class S>
99   void upcast(const smart_ptr<S>& p) {
100     if (reinterpret_cast<void*>(this) != reinterpret_cast<void*>(&p)) {
101       dec();
102
103       obj_ = p.object();
104       ref_obj_ = p.ref_obj();
105
106       if (ref_obj_ != NULL) {
107         ref_obj_->inc_ref();
108       }
109     }
110   }
111
112   // 現在保持している型を新規に生成します。新規の生成では、デフォルトコ
113   // ンストラクタが使用されます。
114   void reset() {
115     dec();
116     init(new T, true);
117   }
118
119   // 外部より明示的に新しい管理対象オブジェクトを渡して初期化を行います。
120   // ownerが指定されない場合、デフォルトで管理が行われます。
121   template<class S>
122   void reset(S* object, bool owner = true) {
123     dec();
124     if (object != NULL) {
125       init(object, owner);
126     }
127   }
128
129   // 外部より明示的に新しい管理対象オブジェクトを渡して初期化を行います。
130   // ownerが指定されない場合、デフォルトで管理が行われます。
131   // 削除時には、渡されたdeleterによって処理が行われます。
132   template<class S>
133   void reset(S* _p, ref_delete_base* ref, bool owner = true) {
134     dec();
135     if (_p != NULL && ref != NULL) {
136       init(_p, owner, ref);
137     }
138   }
139
140  private:
141
142   // smart_ptrの初期化処理を行います。ref_delete_baseが指定されている場合
143   // には、渡されたオブジェクトが解体オブジェクトとして利用されます。
144   template<class S>
145   void init(S* _p, bool owner, ref_delete_base* ref = NULL) {
146     obj_ = _p;
147
148     if (ref_obj_ != NULL) {
149       ref_obj_ = NULL;
150     }
151
152     if (ref != NULL) {
153       ref_obj_ = ref;
154     } else if (owner) {
155       ref_obj_ = new ref_noarray_object<S>(_p);
156     } else {
157       ref_obj_ = new ref_null_object<S>(_p);
158     }
159
160     ref_obj_->set_reference(1);
161     ref_obj_->set_maxnum(1);
162     ref_obj_->set_objsize(sizeof(S));
163     ref_obj_->set_owner(owner);
164   }
165
166   // 渡されたsmart_ptrを参照するように変更し、参照数を加算します。
167   void inc(const smart_ptr<T>& p) {
168     ref_obj_ = p.ref_obj_;
169     obj_ = p.obj_;
170     if (ref_obj_ != NULL) {
171       ref_obj_->inc_ref();
172     }
173   }
174
175   void swap(smart_ptr<T>& p) {
176     std::swap(ref_obj_, p.ref_obj_);
177     std::swap(obj_, p.obj_);
178   }
179
180   // 現在自身が参照しているオブジェクトの参照数を減算し、
181   // オブジェクトの参照を初期化します。
182   // 参照数の減算時、参照数がゼロになった場合にのみ、ref_objをdeleteします。
183   void dec() {
184     if (ref_obj_ != NULL) {
185       if (ref_obj_->dec_ref()) {
186         delete ref_obj_;
187       }
188     }
189     ref_obj_ = NULL;
190     obj_ = NULL;
191   }
192
193   //========================================
194   //コピーの際に使用するconst関数群
195   //========================================
196
197   // 現在保持しているデリータを返します。
198   ref_delete_base* ref_obj() const {return ref_obj_;}
199
200   // 現在保持しているオブジェクトを返します
201   T* obj() const {return obj_;}
202
203  private:
204
205   T* obj_;      //保持すべきオブジェクト。参照カウントオブジェクトと同一
206
207   ref_delete_base* ref_obj_;     //参照カウントオブジェクト
208 };
209 }; // end of namespace utility
210
211 #endif /* _UTAKATA_LIB_SMART_PTR_H_ */