仕様:
・ADL
intrusive_ptr_add_ref, intrusive_ptr_release, intrusive_ptr_use_count は
- ADLによってのみ呼び出されます。gintenlib::intrusive_ptr_xxx とは呼べません。
- intrusive_ptr_hook を継承することが原因で、継承先のクラスのADL対象に
+ ADLによってのみ呼び出されます。明示的に名前空間修飾することは出来ません。
+ また、 intrusive_ptr_hook を継承することが原因で、継承先のクラスのADL対象に
gintenlib 名前空間が加わることはありません。
・例外仕様
Deleter のコピーコンストラクタにおいて例外が投げられない限り、例外安全です。
・マルチスレッド対応
- カウンタによって対処します(現在検討中)。
+ 参照カウントによって対処します。
+ ・increment:インクリメント操作
+ ・decrement_and_compare_to_zero:デクリメントしてゼロ比較する操作
+ この二つの操作がスレッドセーフならば、全体としてスレッドセーフに動作します。
・コピー関連の動作
コピー、代入操作は、一貫して「何も行わない」方針を採っています。
コピー初期化される場合は、カウンタ、削除子、共にデフォルト値で初期化されます。
{
namespace intrusive_ptr_hook_ // ADL 回避用
{
+ // インクリメント/デクリメント処理(これがアトミックならスレッドセーフ)
+ // デフォルトの処理(ADLで書き換えられる。通常は書き換える必要はない)
+ template<typename T>
+ void increment( T& x )
+ {
+ // これは T が atomic<U> ならアトミック
+ ++x;
+ }
+ template<typename T>
+ bool decrement_and_compare_to_zero( T& x )
+ {
+ // これが問題。ロックするなりして対処する必要がある
+ return --x == 0;
+ }
+
+ // 本体
template<typename Derived, typename Deleter = deleter, typename Counter = int>
class intrusive_ptr_hook
{
counter_type& count = get_count(*p);
assert( count >= 0 );
-
- ++count;
+
+ increment( count );
}
friend void intrusive_ptr_release( Derived const* p )
counter_type& count = get_count(*p);
assert( count > 0 );
- --count;
-
- if( count == 0 )
+ if( decrement_and_compare_to_zero(count) )
{
// p の破棄処理の途中で deleter が削除されると困るのでコピーする
deleter d = get_deleter(*p);