blob: 51c42a3f6f49cc8c36deb48cb73d5280ef67dd71 [file] [log] [blame]
Jeff Thompsonf7d49942013-08-01 16:47:40 -07001#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
2#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_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_pt.hpp
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
Jeff Thompson2277ce52013-08-01 17:34:11 -070021#include <ndnboost/detail/sp_typeinfo.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070022#include <pthread.h>
23
24namespace ndnboost
25{
26
27namespace detail
28{
29
30class sp_counted_base
31{
32private:
33
34 sp_counted_base( sp_counted_base const & );
35 sp_counted_base & operator= ( sp_counted_base const & );
36
37 long use_count_; // #shared
38 long weak_count_; // #weak + (#shared != 0)
39
40 mutable pthread_mutex_t m_;
41
42public:
43
44 sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
45 {
46// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
47
48#if defined(__hpux) && defined(_DECTHREADS_)
49 pthread_mutex_init( &m_, pthread_mutexattr_default );
50#else
51 pthread_mutex_init( &m_, 0 );
52#endif
53 }
54
55 virtual ~sp_counted_base() // nothrow
56 {
57 pthread_mutex_destroy( &m_ );
58 }
59
60 // dispose() is called when use_count_ drops to zero, to release
61 // the resources managed by *this.
62
63 virtual void dispose() = 0; // nothrow
64
65 // destroy() is called when weak_count_ drops to zero.
66
67 virtual void destroy() // nothrow
68 {
69 delete this;
70 }
71
72 virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
73 virtual void * get_untyped_deleter() = 0;
74
75 void add_ref_copy()
76 {
77 pthread_mutex_lock( &m_ );
78 ++use_count_;
79 pthread_mutex_unlock( &m_ );
80 }
81
82 bool add_ref_lock() // true on success
83 {
84 pthread_mutex_lock( &m_ );
85 bool r = use_count_ == 0? false: ( ++use_count_, true );
86 pthread_mutex_unlock( &m_ );
87 return r;
88 }
89
90 void release() // nothrow
91 {
92 pthread_mutex_lock( &m_ );
93 long new_use_count = --use_count_;
94 pthread_mutex_unlock( &m_ );
95
96 if( new_use_count == 0 )
97 {
98 dispose();
99 weak_release();
100 }
101 }
102
103 void weak_add_ref() // nothrow
104 {
105 pthread_mutex_lock( &m_ );
106 ++weak_count_;
107 pthread_mutex_unlock( &m_ );
108 }
109
110 void weak_release() // nothrow
111 {
112 pthread_mutex_lock( &m_ );
113 long new_weak_count = --weak_count_;
114 pthread_mutex_unlock( &m_ );
115
116 if( new_weak_count == 0 )
117 {
118 destroy();
119 }
120 }
121
122 long use_count() const // nothrow
123 {
124 pthread_mutex_lock( &m_ );
125 long r = use_count_;
126 pthread_mutex_unlock( &m_ );
127
128 return r;
129 }
130};
131
132} // namespace detail
133
134} // namespace ndnboost
135
136#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED