memory.cpp revision 278724
1//===------------------------ memory.cpp ----------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#define _LIBCPP_BUILDING_MEMORY
11#include "memory"
12#ifndef _LIBCPP_HAS_NO_THREADS
13#include "mutex"
14#include "thread"
15#endif
16
17_LIBCPP_BEGIN_NAMESPACE_STD
18
19namespace
20{
21
22template <class T>
23inline T
24increment(T& t) _NOEXCEPT
25{
26    return __sync_add_and_fetch(&t, 1);
27}
28
29template <class T>
30inline T
31decrement(T& t) _NOEXCEPT
32{
33    return __sync_add_and_fetch(&t, -1);
34}
35
36}  // namespace
37
38const allocator_arg_t allocator_arg = allocator_arg_t();
39
40bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {}
41
42const char*
43bad_weak_ptr::what() const _NOEXCEPT
44{
45    return "bad_weak_ptr";
46}
47
48__shared_count::~__shared_count()
49{
50}
51
52void
53__shared_count::__add_shared() _NOEXCEPT
54{
55    increment(__shared_owners_);
56}
57
58bool
59__shared_count::__release_shared() _NOEXCEPT
60{
61    if (decrement(__shared_owners_) == -1)
62    {
63        __on_zero_shared();
64        return true;
65    }
66    return false;
67}
68
69__shared_weak_count::~__shared_weak_count()
70{
71}
72
73void
74__shared_weak_count::__add_shared() _NOEXCEPT
75{
76    __shared_count::__add_shared();
77}
78
79void
80__shared_weak_count::__add_weak() _NOEXCEPT
81{
82    increment(__shared_weak_owners_);
83}
84
85void
86__shared_weak_count::__release_shared() _NOEXCEPT
87{
88    if (__shared_count::__release_shared())
89        __release_weak();
90}
91
92void
93__shared_weak_count::__release_weak() _NOEXCEPT
94{
95    if (decrement(__shared_weak_owners_) == -1)
96        __on_zero_shared_weak();
97}
98
99__shared_weak_count*
100__shared_weak_count::lock() _NOEXCEPT
101{
102    long object_owners = __shared_owners_;
103    while (object_owners != -1)
104    {
105        if (__sync_bool_compare_and_swap(&__shared_owners_,
106                                         object_owners,
107                                         object_owners+1))
108            return this;
109        object_owners = __shared_owners_;
110    }
111    return 0;
112}
113
114#if !defined(_LIBCPP_NO_RTTI) || !defined(_LIBCPP_BUILD_STATIC)
115
116const void*
117__shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
118{
119    return 0;
120}
121
122#endif  // _LIBCPP_NO_RTTI
123
124#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
125
126static const std::size_t __sp_mut_count = 16;
127static pthread_mutex_t mut_back_imp[__sp_mut_count] =
128{
129    PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
130    PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
131    PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
132    PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER
133};
134
135static mutex* mut_back = reinterpret_cast<std::mutex*>(mut_back_imp);
136
137_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
138   : __lx(p)
139{
140}
141
142void
143__sp_mut::lock() _NOEXCEPT
144{
145    mutex& m = *static_cast<mutex*>(__lx);
146    unsigned count = 0;
147    while (!m.try_lock())
148    {
149        if (++count > 16)
150        {
151            m.lock();
152            break;
153        }
154        this_thread::yield();
155    }
156}
157
158void
159__sp_mut::unlock() _NOEXCEPT
160{
161    static_cast<mutex*>(__lx)->unlock();
162}
163
164__sp_mut&
165__get_sp_mut(const void* p)
166{
167    static __sp_mut muts[__sp_mut_count]
168    {
169        &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
170        &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
171        &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
172        &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15]
173    };
174    return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
175}
176
177#endif // __has_feature(cxx_atomic) && !_LIBCPP_HAS_NO_THREADS
178
179void
180declare_reachable(void*)
181{
182}
183
184void
185declare_no_pointers(char*, size_t)
186{
187}
188
189void
190undeclare_no_pointers(char*, size_t)
191{
192}
193
194pointer_safety
195get_pointer_safety() _NOEXCEPT
196{
197    return pointer_safety::relaxed;
198}
199
200void*
201__undeclare_reachable(void* p)
202{
203    return p;
204}
205
206void*
207align(size_t alignment, size_t size, void*& ptr, size_t& space)
208{
209    void* r = nullptr;
210    if (size <= space)
211    {
212        char* p1 = static_cast<char*>(ptr);
213        char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment);
214        size_t d = static_cast<size_t>(p2 - p1);
215        if (d <= space - size)
216        {
217            r = p2;
218            ptr = r;
219            space -= d;
220        }
221    }
222    return r;
223}
224
225_LIBCPP_END_NAMESPACE_STD
226