atomic operations for shared_ptr ?

Bronek Kozicki brok@spamcop.net
Sat Aug 24 20:27:00 GMT 2013


On 24/08/2013 20:44, Bronek Kozicki wrote:
> On 24/08/2013 20:34, Bronek Kozicki wrote:
>>
>> Perhaps spinlock could be implemented without breaking ABI? Please check
>> performance comparison figures at the end of this document:
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2632.html
>>
>> Here they suggest use "a spinlock pool keyed on a hash of the address of
>> the instance", although perhaps a special value of _M_ptr might be used
>> instead (that value being the address of _M_ptr itself).
>>
>> Alternatively, a single bit might be sacrificed in existing data members
>> although that would most likely impose performance penalty on most
>> common uses, so I'm not really advocating it.
>
> Scratch the part starting with "although perhaps a special value of
> _M_ptr", it just occured to me it will have exactly same performance
> effect on common uses as taking a single bit from existing data members
> (i.e. not good).


Here is example naiive implementation with a spinlock pool. Even though 
far from perfect, I feel it would be improvement over existing 
siutuation, provided large enough pool.


B.


extern const size_t __shared_ptr_spinlocks_size = 256;
extern std::atomic_flag* __shared_ptr_spinlocks; // definition omitted

// platform dependent, drop least significant bits from a pointer
#define PTR_ALIGNMENT_BITS 3

namespace std
{
   template <typename T>
   shared_ptr<T> atomic_load(const shared_ptr<T>* p)
   {
     const size_t i = ((reinterpret_cast<size_t>(p) >> 
PTR_ALIGNMENT_BITS) & (__shared_ptr_spinlocks_size - 1));
     while (__shared_ptr_spinlocks[i].test_and_set()) ; // spin
     shared_ptr<T> r = *p;
     __shared_ptr_spinlocks[i].clear();
   }

   template <typename T>
   shared_ptr<T> atomic_store(shared_ptr<T>* p, shared_ptr<T> r)
   {
     const size_t i = ((reinterpret_cast<size_t>(p) >> 
PTR_ALIGNMENT_BITS) & (__shared_ptr_spinlocks_size - 1));
     while (__shared_ptr_spinlocks[i].test_and_set()) ; // spin
     swap(*p, r);
     __shared_ptr_spinlocks[i].clear();
   }

   // etc.
}




More information about the Libstdc++ mailing list