Alexander Terekhov wrote: [...] >> Pavel Vasiliev wrote: >> > The true locking/unlocking, not InterlockedIncrement/Decrement() > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Nah, pthread_refcount_t. ;-) >> > even if availabe, is necessary to support weak references. >> > [...] >> > It's probably a bit more exciting to take care of all possible races > without "a true lock" protecting both counters. I'm not sure that the > true locking is *necessary* to support weak references. Do you have > an illustration, Pavel? May be the following code answers the challenge? :-). The "true lock" is still used to protect deallocating code and to ensure cache sync before "delete something". But the most frequently used operations acquire/release now are "mutex-free" for both counters; they take only a single call to atomic_increment/decrement. Provided that this example is correct, I don't see necessity to remove the mutex completely. First, it may be used to ensure cache sync. Second, lock/unlock are to be implemented by atomic_exchange, and the mutex data - by one integer variable (lightweight spinlock mutex). All other possible implementations that I currently expect require at least one additional flag and atomic operations on it. Not cheaper than lightweight mutex. Or other solutions exist? Pavel ----- // Weak reference control block example. Pseudocode. // More source code comments in // http://groups.yahoo.com/group/boost/files/refc/weak_ref_atomicity_example.hpp // Acquires/releases strong count in weak_ref_control_block. class strong_ptr; // Acquires/releases weak count in weak_ref_control_block. class weak_ref; // Control block for an allocated object. Stores strong and weak counts. // Allocated object is destructed when strong count drops to 0. // Control block by itself is destructed when all strong and weak // references are lost. class weak_ref_control_block { public: // Called by existing strong_ptr. void acquire_strong(); void release_strong(); void acquire_weak_from_strong(); // Called by existing weak_ref. void acquire_weak(); void release_weak(); bool acquire_strong_from_weak(); private: void strong_refs_lost(); void weak_refs_lost(); void destruct_allocated(); // "delete p_allocated_obj". void destruct_self(); // "delete this". atomic_int_type strong_count; atomic_int_type weak_count; mutex mutex_destruct; T *p_allocated_obj; }; //--------------------------- void weak_ref_control_block::acquire_strong() { atomic_increment(&strong_count); } //--------------------------- void weak_ref_control_block::release_strong() { if(atomic_decrement(&strong_count) == 0) strong_refs_lost(); } //--------------------------- void weak_ref_control_block::acquire_weak() { atomic_increment(&weak_count); } //--------------------------- void weak_ref_control_block::release_weak() { if(atomic_decrement(&weak_count) == 0) weak_refs_lost(); } //--------------------------- void weak_ref_control_block::acquire_weak_from_strong() { acquire_weak(); } //--------------------------- bool weak_ref_control_block::acquire_strong_from_weak() { scope_lock lock(mutex_destruct); if(atomic_increment(&strong_count) > 0) return true; atomic_set(&strong_count, atomic_int_type_MIN); return false; } //--------------------------- void weak_ref_control_block::strong_refs_lost() { { scope_lock lock(mutex_destruct); if(atomic_query(&strong_count) != 0) return; acquire_weak(); atomic_set(&strong_count, atomic_int_type_MIN); } destruct_allocated(); // smp caches are in sync due to mutex above release_weak(); // fire destruct_self(). } //--------------------------- void weak_ref_control_block::weak_refs_lost() { bool b_destruct = atomic_query(&strong_count) < 0 && atomic_query(&weak_count) == 0; if(!b_destruct) return; sync_smp_caches(mutex_destruct); destruct_self(); } _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost