1 #ifndef GINTENLIB_INCLUDED_REFERENCE_COUNTER_HPP_
2 #define GINTENLIB_INCLUDED_REFERENCE_COUNTER_HPP_
6 <gintenlib/reference_counter.hpp>
8 reference_counter : boost::intrusive_ptr 用オブジェクト生成
11 template<typename Derived, bool multiplely_successable = false >
12 class reference_counter
24 reference_counter( int initial_count );
27 reference_counter( const reference_counter& );
33 void operator=( const reference_counter& );
37 template< typename T, bool b >
38 inline void intrusive_ptr_add_ref( const reference_counter<T, b>* ptr );
39 template< typename T, bool b >
40 inline void intrusive_ptr_release( const reference_counter<T, b>* ptr );
43 class hoge : public gintenlib::reference_counter<hoge>
48 boost::intrusive_ptr<hoge> p = new hoge;
49 // or gintenlib::com_ptr<hoge> p( new hoge );
51 // 多重継承も出来ます。その場合はテンプレート第二引数に true を渡してください
52 struct base1 : gintenlib::reference_counter<base1, true>
56 struct base2 : gintenlib::reference_counter<base2, true>
60 struct derived : base1, base2
66 使用法を見れば一目瞭然でしょう。テンプレート引数に自身を渡して継承すればOKです。
67 第二テンプレート引数は、多重継承が出来るか否か。trueを渡せば多重継承できるようになります。
68 デフォルトでは false です。この場合、仮想関数テーブルは使用していません。
69 よって、非多重継承版で継承をしたい場合、デストラクタを virtual 指定する必要があります。
70 多重継承版では、そういった気遣いをする必要はありません。が、その分コストが高いです。
73 このクラスは、当初は noncopyable として製作されていました。
74 しかし、派生先でコピーコンストラクタを自動生成してくれないのは面倒なので、コピーに限り可能になっています。
75 この際、参照カウントに関しては、コピー元には無関係に 0 に初期化されます。
76 また代入演算は「 copy して swap 」という例外安全な方法があるので、そちらを推奨する意味で禁止になっています。
85 // 非仮想バージョン。サイズや速度の面で最適化されますが、多重継承は出来ません
86 template<typename Derived, bool multiplely_successable = false >
87 struct reference_counter
103 delete static_cast<const Derived*>(this);
108 int use_count() const { return count; }
111 reference_counter() : count(0) {}
112 reference_counter( int initial_count ) : count(initial_count) {}
116 assert( count == 0 );
120 reference_counter( const reference_counter& ) : count(0) {}
125 void operator=( const reference_counter& );
129 // boost::intrusive_ptr 用のインターフェイス
130 // reference_counter<T> は reference_counter<T, false> の意味なので
132 template< typename T >
133 inline void intrusive_ptr_add_ref( const reference_counter<T>* ptr )
137 template< typename T >
138 inline void intrusive_ptr_release( const reference_counter<T>* ptr )
145 struct reference_counter_base
150 assert( count >= 0 );
165 int use_count() const { return count; }
168 reference_counter_base() : count(0) {}
169 reference_counter_base( int initial_count ) : count(initial_count) {}
170 virtual ~reference_counter_base()
173 assert( count == 0 );
177 reference_counter_base( const reference_counter_base& ) : count(0) {}
182 void operator=( const reference_counter_base& );
186 // 仮想継承版本体。コストは高いですがダイアモンド継承できます
187 template<typename Derived>
188 struct reference_counter<Derived, true>
189 : virtual reference_counter_base
193 : reference_counter_base() {}
194 reference_counter( int initial_count = 0 )
195 : reference_counter_base(initial_count) {}
196 virtual ~reference_counter(){}
200 // 仮想継承版では reference_counter_base に対し add_ref/release を定義することで
201 // 衝突が起こらないように工夫されています
202 inline void intrusive_ptr_add_ref( const reference_counter_base* ptr )
206 inline void intrusive_ptr_release( const reference_counter_base* ptr )
212 } // namespace gintenlib
215 #endif // #ifndef GINTENLIB_INCLUDED_REFERENCE_COUNTER_HPP_