epoc32/include/stdapis/boost/detail/sp_counted_base_gcc_ppc.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
     1 #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
     2 #define BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
     3 
     4 // MS compatible compilers support #pragma once
     5 
     6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
     7 # pragma once
     8 #endif
     9 
    10 //
    11 //  detail/sp_counted_base_gcc_ppc.hpp - g++ on PowerPC
    12 //
    13 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
    14 //  Copyright 2004-2005 Peter Dimov
    15 //
    16 //  Distributed under the Boost Software License, Version 1.0. (See
    17 //  accompanying file LICENSE_1_0.txt or copy at
    18 //  http://www.boost.org/LICENSE_1_0.txt)
    19 //
    20 //
    21 //  Lock-free algorithm by Alexander Terekhov
    22 //
    23 //  Thanks to Ben Hitchings for the #weak + (#shared != 0)
    24 //  formulation
    25 //
    26 
    27 #include <typeinfo>
    28 
    29 namespace boost
    30 {
    31 
    32 namespace detail
    33 {
    34 
    35 inline void atomic_increment( int * pw )
    36 {
    37     // ++*pw;
    38 
    39     int tmp;
    40 
    41     __asm__
    42     (
    43         "0:\n\t"
    44         "lwarx %1, 0, %2\n\t"
    45         "addi %1, %1, 1\n\t"
    46         "stwcx. %1, 0, %2\n\t"
    47         "bne- 0b":
    48 
    49         "=m"( *pw ), "=&b"( tmp ):
    50         "r"( pw ), "m"( *pw ):
    51         "cc"
    52     );
    53 }
    54 
    55 inline int atomic_decrement( int * pw )
    56 {
    57     // return --*pw;
    58 
    59     int rv;
    60 
    61     __asm__ __volatile__
    62     (
    63         "sync\n\t"
    64         "0:\n\t"
    65         "lwarx %1, 0, %2\n\t"
    66         "addi %1, %1, -1\n\t"
    67         "stwcx. %1, 0, %2\n\t"
    68         "bne- 0b\n\t"
    69         "isync":
    70 
    71         "=m"( *pw ), "=&b"( rv ):
    72         "r"( pw ), "m"( *pw ):
    73         "memory", "cc"
    74     );
    75 
    76     return rv;
    77 }
    78 
    79 inline int atomic_conditional_increment( int * pw )
    80 {
    81     // if( *pw != 0 ) ++*pw;
    82     // return *pw;
    83 
    84     int rv;
    85 
    86     __asm__
    87     (
    88         "0:\n\t"
    89         "lwarx %1, 0, %2\n\t"
    90         "cmpwi %1, 0\n\t"
    91         "beq 1f\n\t"
    92         "addi %1, %1, 1\n\t"
    93         "1:\n\t"
    94         "stwcx. %1, 0, %2\n\t"
    95         "bne- 0b":
    96 
    97         "=m"( *pw ), "=&b"( rv ):
    98         "r"( pw ), "m"( *pw ):
    99         "cc"
   100     );
   101 
   102     return rv;
   103 }
   104 
   105 class sp_counted_base
   106 {
   107 private:
   108 
   109     sp_counted_base( sp_counted_base const & );
   110     sp_counted_base & operator= ( sp_counted_base const & );
   111 
   112     int use_count_;        // #shared
   113     int weak_count_;       // #weak + (#shared != 0)
   114 
   115 public:
   116 
   117     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
   118     {
   119     }
   120 
   121     virtual ~sp_counted_base() // nothrow
   122     {
   123     }
   124 
   125     // dispose() is called when use_count_ drops to zero, to release
   126     // the resources managed by *this.
   127 
   128     virtual void dispose() = 0; // nothrow
   129 
   130     // destroy() is called when weak_count_ drops to zero.
   131 
   132     virtual void destroy() // nothrow
   133     {
   134         delete this;
   135     }
   136 
   137     virtual void * get_deleter( std::type_info const & ti ) = 0;
   138 
   139     void add_ref_copy()
   140     {
   141         atomic_increment( &use_count_ );
   142     }
   143 
   144     bool add_ref_lock() // true on success
   145     {
   146         return atomic_conditional_increment( &use_count_ ) != 0;
   147     }
   148 
   149     void release() // nothrow
   150     {
   151         if( atomic_decrement( &use_count_ ) == 0 )
   152         {
   153             dispose();
   154             weak_release();
   155         }
   156     }
   157 
   158     void weak_add_ref() // nothrow
   159     {
   160         atomic_increment( &weak_count_ );
   161     }
   162 
   163     void weak_release() // nothrow
   164     {
   165         if( atomic_decrement( &weak_count_ ) == 0 )
   166         {
   167             destroy();
   168         }
   169     }
   170 
   171     long use_count() const // nothrow
   172     {
   173         return static_cast<int const volatile &>( use_count_ );
   174     }
   175 };
   176 
   177 } // namespace detail
   178 
   179 } // namespace boost
   180 
   181 #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED