1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/epoc32/include/stdapis/boost/detail/sp_counted_base_gcc_x86.hpp Tue Mar 16 16:12:26 2010 +0000
1.3 @@ -0,0 +1,173 @@
1.4 +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
1.5 +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
1.6 +
1.7 +// MS compatible compilers support #pragma once
1.8 +
1.9 +#if defined(_MSC_VER) && (_MSC_VER >= 1020)
1.10 +# pragma once
1.11 +#endif
1.12 +
1.13 +//
1.14 +// detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64
1.15 +//
1.16 +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
1.17 +// Copyright 2004-2005 Peter Dimov
1.18 +//
1.19 +// Distributed under the Boost Software License, Version 1.0. (See
1.20 +// accompanying file LICENSE_1_0.txt or copy at
1.21 +// http://www.boost.org/LICENSE_1_0.txt)
1.22 +//
1.23 +//
1.24 +// Lock-free algorithm by Alexander Terekhov
1.25 +//
1.26 +// Thanks to Ben Hitchings for the #weak + (#shared != 0)
1.27 +// formulation
1.28 +//
1.29 +
1.30 +#include <typeinfo>
1.31 +
1.32 +namespace boost
1.33 +{
1.34 +
1.35 +namespace detail
1.36 +{
1.37 +
1.38 +inline int atomic_exchange_and_add( int * pw, int dv )
1.39 +{
1.40 + // int r = *pw;
1.41 + // *pw += dv;
1.42 + // return r;
1.43 +
1.44 + int r;
1.45 +
1.46 + __asm__ __volatile__
1.47 + (
1.48 + "lock\n\t"
1.49 + "xadd %1, %0":
1.50 + "=m"( *pw ), "=r"( r ): // outputs (%0, %1)
1.51 + "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
1.52 + "memory", "cc" // clobbers
1.53 + );
1.54 +
1.55 + return r;
1.56 +}
1.57 +
1.58 +inline void atomic_increment( int * pw )
1.59 +{
1.60 + //atomic_exchange_and_add( pw, 1 );
1.61 +
1.62 + __asm__
1.63 + (
1.64 + "lock\n\t"
1.65 + "incl %0":
1.66 + "=m"( *pw ): // output (%0)
1.67 + "m"( *pw ): // input (%1)
1.68 + "cc" // clobbers
1.69 + );
1.70 +}
1.71 +
1.72 +inline int atomic_conditional_increment( int * pw )
1.73 +{
1.74 + // int rv = *pw;
1.75 + // if( rv != 0 ) ++*pw;
1.76 + // return rv;
1.77 +
1.78 + int rv, tmp;
1.79 +
1.80 + __asm__
1.81 + (
1.82 + "movl %0, %%eax\n\t"
1.83 + "0:\n\t"
1.84 + "test %%eax, %%eax\n\t"
1.85 + "je 1f\n\t"
1.86 + "movl %%eax, %2\n\t"
1.87 + "incl %2\n\t"
1.88 + "lock\n\t"
1.89 + "cmpxchgl %2, %0\n\t"
1.90 + "jne 0b\n\t"
1.91 + "1:":
1.92 + "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
1.93 + "m"( *pw ): // input (%3)
1.94 + "cc" // clobbers
1.95 + );
1.96 +
1.97 + return rv;
1.98 +}
1.99 +
1.100 +class sp_counted_base
1.101 +{
1.102 +private:
1.103 +
1.104 + sp_counted_base( sp_counted_base const & );
1.105 + sp_counted_base & operator= ( sp_counted_base const & );
1.106 +
1.107 + int use_count_; // #shared
1.108 + int weak_count_; // #weak + (#shared != 0)
1.109 +
1.110 +public:
1.111 +
1.112 + sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
1.113 + {
1.114 + }
1.115 +
1.116 + virtual ~sp_counted_base() // nothrow
1.117 + {
1.118 + }
1.119 +
1.120 + // dispose() is called when use_count_ drops to zero, to release
1.121 + // the resources managed by *this.
1.122 +
1.123 + virtual void dispose() = 0; // nothrow
1.124 +
1.125 + // destroy() is called when weak_count_ drops to zero.
1.126 +
1.127 + virtual void destroy() // nothrow
1.128 + {
1.129 + delete this;
1.130 + }
1.131 +
1.132 + virtual void * get_deleter( std::type_info const & ti ) = 0;
1.133 +
1.134 + void add_ref_copy()
1.135 + {
1.136 + atomic_increment( &use_count_ );
1.137 + }
1.138 +
1.139 + bool add_ref_lock() // true on success
1.140 + {
1.141 + return atomic_conditional_increment( &use_count_ ) != 0;
1.142 + }
1.143 +
1.144 + void release() // nothrow
1.145 + {
1.146 + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
1.147 + {
1.148 + dispose();
1.149 + weak_release();
1.150 + }
1.151 + }
1.152 +
1.153 + void weak_add_ref() // nothrow
1.154 + {
1.155 + atomic_increment( &weak_count_ );
1.156 + }
1.157 +
1.158 + void weak_release() // nothrow
1.159 + {
1.160 + if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
1.161 + {
1.162 + destroy();
1.163 + }
1.164 + }
1.165 +
1.166 + long use_count() const // nothrow
1.167 + {
1.168 + return static_cast<int const volatile &>( use_count_ );
1.169 + }
1.170 +};
1.171 +
1.172 +} // namespace detail
1.173 +
1.174 +} // namespace boost
1.175 +
1.176 +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED