blob: 673f462ea5075fb303a5980c4675f13bc42a25ab [file] [log] [blame]
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001#ifndef NDNBOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED
2#define NDNBOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED
Jeff Thompsonf7d49942013-08-01 16:47:40 -07003
4//
5// detail/sp_counted_base_vacpp_ppc.hpp - xlC(vacpp) on POWER
6// based on: detail/sp_counted_base_w32.hpp
7//
8// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
9// Copyright 2004-2005 Peter Dimov
10// Copyright 2006 Michael van der Westhuizen
11// Copyright 2012 IBM Corp.
12//
13// Distributed under the Boost Software License, Version 1.0. (See
14// accompanying file LICENSE_1_0.txt or copy at
15// http://www.boost.org/LICENSE_1_0.txt)
16//
17//
18// Lock-free algorithm by Alexander Terekhov
19//
20// Thanks to Ben Hitchings for the #weak + (#shared != 0)
21// formulation
22//
23
Jeff Thompson2277ce52013-08-01 17:34:11 -070024#include <ndnboost/detail/sp_typeinfo.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070025
26extern "builtin" void __lwsync(void);
27extern "builtin" void __isync(void);
28extern "builtin" int __fetch_and_add(volatile int* addr, int val);
29extern "builtin" int __compare_and_swap(volatile int*, int*, int);
30
31namespace ndnboost
32{
33
34namespace detail
35{
36
37inline void atomic_increment( int *pw )
38{
39 // ++*pw;
40 __lwsync();
41 __fetch_and_add(pw, 1);
42 __isync();
43}
44
45inline int atomic_decrement( int *pw )
46{
47 // return --*pw;
48 __lwsync();
49 int originalValue = __fetch_and_add(pw, -1);
50 __isync();
51
52 return (originalValue - 1);
53}
54
55inline int atomic_conditional_increment( int *pw )
56{
57 // if( *pw != 0 ) ++*pw;
58 // return *pw;
59
60 __lwsync();
61 int v = *const_cast<volatile int*>(pw);
62 for (;;)
63 // loop until state is known
64 {
65 if (v == 0) return 0;
66 if (__compare_and_swap(pw, &v, v + 1))
67 {
68 __isync(); return (v + 1);
69 }
70 }
71}
72
73class sp_counted_base
74{
75private:
76
77 sp_counted_base( sp_counted_base const & );
78 sp_counted_base & operator= ( sp_counted_base const & );
79
80 int use_count_; // #shared
81 int weak_count_; // #weak + (#shared != 0)
82 char pad[64] __attribute__((__aligned__(64)));
83 // pad to prevent false sharing
84public:
85
86 sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
87 {
88 }
89
90 virtual ~sp_counted_base() // nothrow
91 {
92 }
93
94 // dispose() is called when use_count_ drops to zero, to release
95 // the resources managed by *this.
96
97 virtual void dispose() = 0; // nothrow
98
99 // destroy() is called when weak_count_ drops to zero.
100
101 virtual void destroy() // nothrow
102 {
103 delete this;
104 }
105
106 virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
107 virtual void * get_untyped_deleter() = 0;
108
109 void add_ref_copy()
110 {
111 atomic_increment( &use_count_ );
112 }
113
114 bool add_ref_lock() // true on success
115 {
116 return atomic_conditional_increment( &use_count_ ) != 0;
117 }
118
119 void release() // nothrow
120 {
121 if( atomic_decrement( &use_count_ ) == 0 )
122 {
123 dispose();
124 weak_release();
125 }
126 }
127
128 void weak_add_ref() // nothrow
129 {
130 atomic_increment( &weak_count_ );
131 }
132
133 void weak_release() // nothrow
134 {
135 if( atomic_decrement( &weak_count_ ) == 0 )
136 {
137 destroy();
138 }
139 }
140
141 long use_count() const // nothrow
142 {
143 return *const_cast<volatile int*>(&use_count_);
144 }
145};
146
147} // namespace detail
148
149} // namespace ndnboost
150
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700151#endif // #ifndef NDNBOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED