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 public:
50  // Note: The default constructor's body is implemented as no-op
51  // rather than `noexcept = default` due to a bug with gcc 9.3.1
52  // that deletes the constructor since boost::intrusive::list_member_hook
53  // is not default_nothrow_constructible.
54  weak_ptr() noexcept {}
55  weak_ptr(std::nullptr_t) noexcept : weak_ptr() {}
56  weak_ptr(weak_ptr&& o) noexcept
57  : _ptr(o._ptr)
58  {
59  _hook.swap_nodes(o._hook);
60  o._ptr = nullptr;
61  }
62  weak_ptr& operator=(weak_ptr&& o) noexcept {
63  if (this != &o) {
64  this->~weak_ptr();
65  new (this) weak_ptr(std::move(o));
66  }
67  return *this;
68  }
69  explicit operator bool() const noexcept { return _ptr != nullptr; }
70  T* operator->() const noexcept { return _ptr; }
71  T& operator*() const noexcept { return *_ptr; }
72  T* get() const noexcept { return _ptr; }
73  bool operator==(const weak_ptr& o) const noexcept { return _ptr == o._ptr; }
74  bool operator!=(const weak_ptr& o) const noexcept { return _ptr != o._ptr; }
75 };
76 
94 template<typename T>
96  boost::intrusive::list<weak_ptr<T>,
97  boost::intrusive::member_hook<weak_ptr<T>, typename weak_ptr<T>::hook_type, &weak_ptr<T>::_hook>,
98  boost::intrusive::constant_time_size<false>> _ptr_list;
99 public:
100  // Note: The default constructor's body is implemented as no-op
101  // rather than `noexcept = default` due to a bug with gcc 9.3.1
102  // that deletes the constructor since boost::intrusive::member_hook
103  // is not default_nothrow_constructible.
104  weakly_referencable() noexcept {}
105  weakly_referencable(weakly_referencable&&) = delete; // pointer to this is captured and passed to weak_ptr
106  weakly_referencable(const weakly_referencable&) = delete;
107  ~weakly_referencable() noexcept {
108  _ptr_list.clear_and_dispose([] (weak_ptr<T>* wp) noexcept {
109  wp->_ptr = nullptr;
110  });
111  }
112  weak_ptr<T> weak_from_this() noexcept {
113  weak_ptr<T> ptr(static_cast<T*>(this));
114  _ptr_list.push_back(ptr);
115  return ptr;
116  }
117 };
118 
119 }
120 
seastar
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
seastar::weak_ptr
Definition: weak_ptr.hh:41
seastar::weakly_referencable
Definition: weak_ptr.hh:95