1 // 参照カウンタによるスマートポインタを提供します。
3 // ここで定義されるスマートポインタは、scoped_ptrとは異なり、
4 // 最終的に参照しているデータが、解体責任を負う点で異なります。
5 // 最終的に参照しているデータを判定するため、参照カウンタ形式で
8 // また、このスマートポインタは配列を扱うことができます。
12 // smart_ptr<CHoge> h(new CHoge());
14 // smart_ptr<CHoge> ha();
17 #ifndef _UTAKATA_SRC_COMMON_SMART_PTR_H_
18 #define _UTAKATA_SRC_COMMON_SMART_PTR_H_
20 #include "src/common/ref_delete.h"
24 template<class T> class smart_ptr {
26 template<class S> explicit
27 smart_ptr(S* p, bool owner = true, ref_delete_base* ref = NULL) :
28 obj_(NULL),ref_obj_(NULL) {
35 smart_ptr() : obj_(NULL),ref_obj_(NULL) {}
38 smart_ptr(const smart_ptr<T>& p) :
39 obj_(NULL),ref_obj_(NULL) {
44 // 自分にコピーされる前に、前のオブジェクトの参照カウントを
46 smart_ptr<T>& operator=(const smart_ptr<T>& obj) {
49 smart_ptr<T> tmp(obj);
55 virtual ~smart_ptr() {dec();}
58 virtual void release() {dec();}
60 //ここからは、ポインタの振りをするための仕掛け。
61 T& operator*() const {return *get();}
62 T* operator->() const {return get();}
65 bool operator==(const smart_ptr<T>& rh) {
66 return obj_ == rh.obj_;
68 bool operator!=(const smart_ptr<T>& rh) {
69 return !(*this.obj_ == rh.obj_);
72 // 現在保持しているポインタを明示的に返します。
74 if (ref_obj_ == NULL) {
81 // 内部で参照しているオブジェクトがNULLであるかどうかを返します。
82 bool is_null() const {
83 return ref_obj_ == NULL && obj_ == NULL;
86 // オブジェクトが単一の場所からのみ参照されているか。
87 bool is_only_ref() const {
88 return ref_obj_->reference() == 1;
91 //=============================================
93 //=============================================
95 // 渡されたsmart_ptrが格納しているオブジェクトを参照するようにします。
96 // テンプレートパラメータSは、Tの派生クラスである必要があります。
98 void upcast(const smart_ptr<S>& p) {
99 if (reinterpret_cast<void*>(this) != reinterpret_cast<void*>(&p)) {
103 ref_obj_ = p.ref_obj();
105 if (ref_obj_ != NULL) {
111 // 現在保持している型を新規に生成します。新規の生成では、デフォルトコ
118 // 外部より明示的に新しい管理対象オブジェクトを渡して初期化を行います。
119 // ownerが指定されない場合、デフォルトで管理が行われます。
121 void reset(S* object, bool owner = true) {
123 if (object != NULL) {
128 // 外部より明示的に新しい管理対象オブジェクトを渡して初期化を行います。
129 // ownerが指定されない場合、デフォルトで管理が行われます。
130 // 削除時には、渡されたdeleterによって処理が行われます。
132 void reset(S* _p, ref_delete_base* ref, bool owner = true) {
134 if (_p != NULL && ref != NULL) {
135 init(_p, owner, ref);
141 // smart_ptrの初期化処理を行います。ref_delete_baseが指定されている場合
142 // には、渡されたオブジェクトが解体オブジェクトとして利用されます。
144 void init(S* _p, bool owner, ref_delete_base* ref = NULL) {
147 if (ref_obj_ != NULL) {
154 ref_obj_ = new ref_noarray_object<S>(_p);
156 ref_obj_ = new ref_null_object<S>(_p);
159 ref_obj_->set_reference(1);
160 ref_obj_->set_maxnum(1);
161 ref_obj_->set_objsize(sizeof(S));
162 ref_obj_->set_owner(owner);
165 // 渡されたsmart_ptrを参照するように変更し、参照数を加算します。
166 void inc(const smart_ptr<T>& p) {
167 ref_obj_ = p.ref_obj_;
169 if (ref_obj_ != NULL) {
174 void swap(smart_ptr<T>& p) {
175 std::swap(ref_obj_, p.ref_obj_);
176 std::swap(obj_, p.obj_);
179 // 現在自身が参照しているオブジェクトの参照数を減算し、
181 // 参照数の減算時、参照数がゼロになった場合にのみ、ref_objをdeleteします。
183 if (ref_obj_ != NULL) {
184 if (ref_obj_->dec_ref()) {
192 //========================================
194 //========================================
196 // 現在保持しているデリータを返します。
197 ref_delete_base* ref_obj() const {return ref_obj_;}
199 // 現在保持しているオブジェクトを返します
200 T* obj() const {return obj_;}
204 T* obj_; //保持すべきオブジェクト。参照カウントオブジェクトと同一
206 ref_delete_base* ref_obj_; //参照カウントオブジェクト
208 }; // end of namespace utility
210 #endif /* _UTAKATA_SRC_COMMON_SMART_PTR_H_ */