]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/cpp/src/arrow/util/atomic_shared_ptr.h
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / arrow / util / atomic_shared_ptr.h
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 #pragma once
19
20 #include <atomic>
21 #include <memory>
22 #include <utility>
23
24 #include "arrow/type_traits.h"
25
26 namespace arrow {
27 namespace internal {
28
29 // Atomic shared_ptr operations only appeared in libstdc++ since GCC 5,
30 // emulate them with unsafe ops if unavailable.
31 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250
32
33 template <typename T, typename = void>
34 struct is_atomic_load_shared_ptr_available : std::false_type {};
35
36 template <typename T>
37 struct is_atomic_load_shared_ptr_available<
38 T, void_t<decltype(std::atomic_load(std::declval<const std::shared_ptr<T>*>()))>>
39 : std::true_type {};
40
41 template <typename T>
42 using enable_if_atomic_load_shared_ptr_available =
43 enable_if_t<is_atomic_load_shared_ptr_available<T>::value, T>;
44
45 template <typename T>
46 using enable_if_atomic_load_shared_ptr_unavailable =
47 enable_if_t<!is_atomic_load_shared_ptr_available<T>::value, T>;
48
49 template <class T>
50 enable_if_atomic_load_shared_ptr_available<std::shared_ptr<T>> atomic_load(
51 const std::shared_ptr<T>* p) {
52 return std::atomic_load(p);
53 }
54
55 template <class T>
56 enable_if_atomic_load_shared_ptr_unavailable<std::shared_ptr<T>> atomic_load(
57 const std::shared_ptr<T>* p) {
58 return *p;
59 }
60
61 template <typename T, typename = void>
62 struct is_atomic_store_shared_ptr_available : std::false_type {};
63
64 template <typename T>
65 struct is_atomic_store_shared_ptr_available<
66 T, void_t<decltype(std::atomic_store(std::declval<std::shared_ptr<T>*>(),
67 std::declval<std::shared_ptr<T>>()))>>
68 : std::true_type {};
69
70 template <typename T>
71 using enable_if_atomic_store_shared_ptr_available =
72 enable_if_t<is_atomic_store_shared_ptr_available<T>::value, T>;
73
74 template <typename T>
75 using enable_if_atomic_store_shared_ptr_unavailable =
76 enable_if_t<!is_atomic_store_shared_ptr_available<T>::value, T>;
77
78 template <class T>
79 void atomic_store(enable_if_atomic_store_shared_ptr_available<std::shared_ptr<T>*> p,
80 std::shared_ptr<T> r) {
81 std::atomic_store(p, std::move(r));
82 }
83
84 template <class T>
85 void atomic_store(enable_if_atomic_store_shared_ptr_unavailable<std::shared_ptr<T>*> p,
86 std::shared_ptr<T> r) {
87 *p = r;
88 }
89
90 template <class T>
91 bool atomic_compare_exchange_strong(
92 enable_if_atomic_store_shared_ptr_available<std::shared_ptr<T>*> p,
93 std::shared_ptr<T>* expected, std::shared_ptr<T> desired) {
94 return std::atomic_compare_exchange_strong(p, expected, std::move(desired));
95 }
96
97 template <class T>
98 bool atomic_compare_exchange_strong(
99 enable_if_atomic_store_shared_ptr_unavailable<std::shared_ptr<T>*> p,
100 std::shared_ptr<T>* expected, std::shared_ptr<T> desired) {
101 if (*p == *expected) {
102 *p = std::move(desired);
103 return true;
104 } else {
105 *expected = *p;
106 return false;
107 }
108 }
109
110 } // namespace internal
111 } // namespace arrow