Seastar
High performance C++ framework for concurrent servers
weak_ptr.hh
1 /*
2  * This file is open source software, licensed to you under the terms
3  * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4  * distributed with this work for additional information regarding copyright
5  * ownership. You may not use this file except in compliance with the License.
6  *
7  * 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 /*
19  * Copyright (C) 2016 ScyllaDB
20  */
21 
22 #pragma once
23 
24 #ifndef SEASTAR_MODULE
25 #include <utility>
26 #include <boost/intrusive/list.hpp>
27 #include <seastar/util/modules.hh>
28 #endif
29 
30 namespace seastar {
31 
44 SEASTAR_MODULE_EXPORT
45 template<typename T>
46 class weak_ptr {
47  template<typename U>
48  friend class weakly_referencable;
49 private:
50  using hook_type = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
51  hook_type _hook;
52  T* _ptr = nullptr;
53  weak_ptr(T* p) noexcept : _ptr(p) {}
54  void clear() noexcept {
55  _hook = {};
56  _ptr = nullptr;
57  }
58  void swap(weak_ptr&& o) noexcept {
59  _hook.swap_nodes(o._hook);
60  std::swap(_ptr, o._ptr);
61  }
62 public:
63  // Note: The default constructor's body is implemented as no-op
64  // rather than `noexcept = default` due to a bug with gcc 9.3.1
65  // that deletes the constructor since boost::intrusive::list_member_hook
66  // is not default_nothrow_constructible.
67  weak_ptr() noexcept {}
68  weak_ptr(std::nullptr_t) noexcept : weak_ptr() {}
69  weak_ptr(weak_ptr&& o) noexcept
70  {
71  swap(std::move(o));
72  }
73  weak_ptr(const weak_ptr& o) noexcept {
74  if (o._ptr) {
75  swap(o._ptr->weak_from_this());
76  }
77  }
78  weak_ptr& operator=(weak_ptr&& o) noexcept {
79  if (this != &o) {
80  clear();
81  swap(std::move(o));
82  }
83  return *this;
84  }
85  weak_ptr& operator=(const weak_ptr& o) noexcept {
86  if (this != &o) {
87  clear();
88  if (o._ptr) {
89  swap(o._ptr->weak_from_this());
90  }
91  }
92  return *this;
93  }
94  explicit operator bool() const noexcept { return _ptr != nullptr; }
95  T* operator->() const noexcept { return _ptr; }
96  T& operator*() const noexcept { return *_ptr; }
97  T* get() const noexcept { return _ptr; }
98  bool operator==(const weak_ptr& o) const noexcept { return _ptr == o._ptr; }
99  bool operator!=(const weak_ptr& o) const noexcept { return _ptr != o._ptr; }
100 };
101 
119 template<typename T>
121  boost::intrusive::list<weak_ptr<T>,
122  boost::intrusive::member_hook<weak_ptr<T>, typename weak_ptr<T>::hook_type, &weak_ptr<T>::_hook>,
123  boost::intrusive::constant_time_size<false>> _ptr_list;
124 public:
125  // Note: The default constructor's body is implemented as no-op
126  // rather than `noexcept = default` due to a bug with gcc 9.3.1
127  // that deletes the constructor since boost::intrusive::member_hook
128  // is not default_nothrow_constructible.
129  weakly_referencable() noexcept {}
130  weakly_referencable(weakly_referencable&&) = delete; // pointer to this is captured and passed to weak_ptr
131  weakly_referencable(const weakly_referencable&) = delete;
132  ~weakly_referencable() noexcept {
133  _ptr_list.clear_and_dispose([] (weak_ptr<T>* wp) noexcept {
134  wp->_ptr = nullptr;
135  });
136  }
137  weak_ptr<T> weak_from_this() noexcept {
138  weak_ptr<T> ptr(static_cast<T*>(this));
139  _ptr_list.push_back(ptr);
140  return ptr;
141  }
142 };
143 
144 }
145 
Definition: weak_ptr.hh:46
Definition: weak_ptr.hh:120
Seastar API namespace.
Definition: abort_on_ebadf.hh:26