/usr/include/boost/flyweight/refcounted.hpp is in libboost1.62-dev 1.62.0+dfsg-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | /* Copyright 2006-2014 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/flyweight for library home page.
*/
#ifndef BOOST_FLYWEIGHT_REFCOUNTED_HPP
#define BOOST_FLYWEIGHT_REFCOUNTED_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/atomic_count.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/flyweight/refcounted_fwd.hpp>
#include <boost/flyweight/tracking_tag.hpp>
#include <boost/utility/swap.hpp>
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#include <utility>
#endif
/* Refcounting tracking policy.
* The implementation deserves some explanation; values are equipped with two
* reference counts:
* - a regular count of active references
* - a deleter count
* It looks like a value can be erased when the number of references reaches
* zero, but this condition alone can lead to data races:
* - Thread A detaches the last reference to x and is preempted.
* - Thread B looks for x, finds it and attaches a reference to it.
* - Thread A resumes and proceeds with erasing x, leaving a dangling
* reference in thread B.
* Here is where the deleter count comes into play. This count is
* incremented when the reference count changes from 0 to 1, and decremented
* when a thread is about to check a value for erasure; it can be seen that a
* value is effectively erasable only when the deleter count goes down to 0
* (unless there are dangling references due to abnormal program termination,
* for instance if std::exit is called).
*/
namespace boost{
namespace flyweights{
namespace detail{
template<typename Value,typename Key>
class refcounted_value
{
public:
explicit refcounted_value(const Value& x_):
x(x_),ref(0),del_ref(0)
{}
refcounted_value(const refcounted_value& r):
x(r.x),ref(0),del_ref(0)
{}
refcounted_value& operator=(const refcounted_value& r)
{
x=r.x;
return *this;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
explicit refcounted_value(Value&& x_):
x(std::move(x_)),ref(0),del_ref(0)
{}
refcounted_value(refcounted_value&& r):
x(std::move(r.x)),ref(0),del_ref(0)
{}
refcounted_value& operator=(refcounted_value&& r)
{
x=std::move(r.x);
return *this;
}
#endif
operator const Value&()const{return x;}
operator const Key&()const{return x;}
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
private:
template<typename,typename> friend class refcounted_handle;
#endif
long count()const{return ref;}
long add_ref()const{return ++ref;}
bool release()const{return (--ref==0);}
void add_deleter()const{++del_ref;}
bool release_deleter()const{return (--del_ref==0);}
private:
Value x;
mutable boost::detail::atomic_count ref;
mutable long del_ref;
};
template<typename Handle,typename TrackingHelper>
class refcounted_handle
{
public:
explicit refcounted_handle(const Handle& h_):h(h_)
{
if(TrackingHelper::entry(*this).add_ref()==1){
TrackingHelper::entry(*this).add_deleter();
}
}
refcounted_handle(const refcounted_handle& x):h(x.h)
{
TrackingHelper::entry(*this).add_ref();
}
refcounted_handle& operator=(refcounted_handle x)
{
this->swap(x);
return *this;
}
~refcounted_handle()
{
if(TrackingHelper::entry(*this).release()){
TrackingHelper::erase(*this,check_erase);
}
}
operator const Handle&()const{return h;}
void swap(refcounted_handle& x)
{
std::swap(h,x.h);
}
private:
static bool check_erase(const refcounted_handle& x)
{
return TrackingHelper::entry(x).release_deleter();
}
Handle h;
};
template<typename Handle,typename TrackingHelper>
void swap(
refcounted_handle<Handle,TrackingHelper>& x,
refcounted_handle<Handle,TrackingHelper>& y)
{
x.swap(y);
}
} /* namespace flyweights::detail */
#if BOOST_WORKAROUND(BOOST_MSVC,<=1500)
/* swap lookup by boost::swap fails under obscure circumstances */
} /* namespace flyweights */
template<typename Handle,typename TrackingHelper>
void swap(
::boost::flyweights::detail::refcounted_handle<Handle,TrackingHelper>& x,
::boost::flyweights::detail::refcounted_handle<Handle,TrackingHelper>& y)
{
::boost::flyweights::detail::swap(x,y);
}
namespace flyweights{
#endif
struct refcounted:tracking_marker
{
struct entry_type
{
template<typename Value,typename Key>
struct apply
{
typedef detail::refcounted_value<Value,Key> type;
};
};
struct handle_type
{
template<typename Handle,typename TrackingHelper>
struct apply
{
typedef detail::refcounted_handle<Handle,TrackingHelper> type;
};
};
};
} /* namespace flyweights */
} /* namespace boost */
#endif
|