staticlib_support  1.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
release_deleter.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018, alex at staticlibs.net
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * File: release_deleter.hpp
19  * Author: alex
20  *
21  * Created on June 12, 2018, 11:13 AM
22  */
23 
24 #ifndef STATICLIB_SUPPORT_RELEASE_DELETER_HPP
25 #define STATICLIB_SUPPORT_RELEASE_DELETER_HPP
26 
27 #include <atomic>
28 #include <memory>
29 
30 namespace staticlib {
31 namespace support {
32 
37 template<typename T, typename Deleter = typename std::default_delete<T>>
38 class release_deleter : private Deleter {
39  std::shared_ptr<std::atomic_flag> released;
40 
41 public:
42 
47  released(std::make_shared<std::atomic_flag>()) {
48  released->clear();
49  }
50 
57  Deleter(other),
58  released(other.released) { }
59 
66  release_deleter& operator=(const release_deleter& other) = delete;
67 
73  void operator()(T* ptr) {
74  if (!released->test_and_set(std::memory_order_acq_rel)) {
76  }
77  }
78 
84  bool release() {
85  return !released->test_and_set(std::memory_order_acq_rel);
86  }
87 };
88 
89 template<typename T>
90 std::shared_ptr<T> make_shared_with_release_deleter(T* ptr) {
91  return std::shared_ptr<T>(ptr, release_deleter<T>());
92 }
93 
94 template<typename T>
95 std::unique_ptr<T> make_unique_from_shared_with_release_deleter(std::shared_ptr<T> ptr) {
96  release_deleter<T>* deleter = std::get_deleter<release_deleter<T>>(ptr);
97  if (nullptr != deleter) {
98  bool released = deleter->release();
99  if (released) {
100  return std::unique_ptr<T>(ptr.get());
101  } else {
102  return std::unique_ptr<T>();
103  }
104  } else {
105  return std::unique_ptr<T>();
106  }
107 }
108 
109 } // namespace
110 }
111 
112 #endif /* STATICLIB_SUPPORT_RELEASE_DELETER_HPP */
113