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 #include <boost/intrusive/list.hpp>
25 
26 namespace seastar {
27 
40 template<typename T>
41 class weak_ptr {
42  template<typename U>
43  friend class weakly_referencable;
44 private:
45  using hook_type = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
46  hook_type _hook;
47  T* _ptr = nullptr;
48  weak_ptr(T* p) noexcept : _ptr(p) {}
49  void clear() noexcept {
50  _hook = {};
51  _ptr = nullptr;
52  }
53  void swap(weak_ptr&& o) noexcept {
54  _hook.swap_nodes(o._hook);
55  std::swap(_ptr, o._ptr);
56  }
57 public:
58  // Note: The default constructor's body is implemented as no-op
59  // rather than `noexcept = default` due to a bug with gcc 9.3.1
60  // that deletes the constructor since boost::intrusive::list_member_hook
61  // is not default_nothrow_constructible.
62  weak_ptr() noexcept {}
63  weak_ptr(std::nullptr_t) noexcept : weak_ptr() {}
64  weak_ptr(weak_ptr&& o) noexcept
65  {
66  swap(std::move(o));
67  }
68  weak_ptr(const weak_ptr& o) noexcept {
69  if (o._ptr) {
70  swap(o._ptr->weak_from_this());
71  }
72  }
73  weak_ptr& operator=(weak_ptr&& o) noexcept {
74  if (this != &o) {
75  clear();
76  swap(std::move(o));
77  }
78  return *this;
79  }
80  weak_ptr& operator=(const weak_ptr& o) noexcept {
81  if (this != &o) {
82  clear();
83  if (o._ptr) {
84  swap(o._ptr->weak_from_this());
85  }
86  }
87  return *this;
88  }
89  explicit operator bool() const noexcept { return _ptr != nullptr; }
90  T* operator->() const noexcept { return _ptr; }
91  T& operator*() const noexcept { return *_ptr; }
92  T* get() const noexcept { return _ptr; }
93  bool operator==(const weak_ptr& o) const noexcept { return _ptr == o._ptr; }
94  bool operator!=(const weak_ptr& o) const noexcept { return _ptr != o._ptr; }
95 };
96 
114 template<typename T>
116  boost::intrusive::list<weak_ptr<T>,
117  boost::intrusive::member_hook<weak_ptr<T>, typename weak_ptr<T>::hook_type, &weak_ptr<T>::_hook>,
118  boost::intrusive::constant_time_size<false>> _ptr_list;
119 public:
120  // Note: The default constructor's body is implemented as no-op
121  // rather than `noexcept = default` due to a bug with gcc 9.3.1
122  // that deletes the constructor since boost::intrusive::member_hook
123  // is not default_nothrow_constructible.
124  weakly_referencable() noexcept {}
125  weakly_referencable(weakly_referencable&&) = delete; // pointer to this is captured and passed to weak_ptr
126  weakly_referencable(const weakly_referencable&) = delete;
127  ~weakly_referencable() noexcept {
128  _ptr_list.clear_and_dispose([] (weak_ptr<T>* wp) noexcept {
129  wp->_ptr = nullptr;
130  });
131  }
132  weak_ptr<T> weak_from_this() noexcept {
133  weak_ptr<T> ptr(static_cast<T*>(this));
134  _ptr_list.push_back(ptr);
135  return ptr;
136  }
137 };
138 
139 }
140 
Definition: weak_ptr.hh:41
Definition: weak_ptr.hh:115
Seastar API namespace.
Definition: abort_on_ebadf.hh:24