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
30namespace seastar {
31
44SEASTAR_MODULE_EXPORT
45template<typename T>
46class weak_ptr {
47 template<typename U>
48 friend class weakly_referencable;
49 template <typename U>
50 friend class weak_ptr;
51private:
52 using hook_type = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
53 hook_type _hook;
54 T* _ptr = nullptr;
55 weak_ptr(T* p) noexcept : _ptr(p) {}
56 void clear() noexcept {
57 _hook = {};
58 _ptr = nullptr;
59 }
60 void swap(weak_ptr&& o) noexcept {
61 _hook.swap_nodes(o._hook);
62 std::swap(_ptr, o._ptr);
63 }
64
65public:
66 template <typename U>
67 requires std::convertible_to<U*, T*>
69 {
70 if (o._ptr) {
71 _ptr = std::exchange(o._ptr, nullptr);
72 _hook.swap_nodes(o._hook);
73 }
74 }
75
76 // Note: The default constructor's body is implemented as no-op
77 // rather than `noexcept = default` due to a bug with gcc 9.3.1
78 // that deletes the constructor since boost::intrusive::list_member_hook
79 // is not default_nothrow_constructible.
80 weak_ptr() noexcept {}
81 weak_ptr(std::nullptr_t) noexcept : weak_ptr() {}
82 weak_ptr(weak_ptr&& o) noexcept
83 {
84 swap(std::move(o));
85 }
86 weak_ptr(const weak_ptr& o) noexcept {
87 if (o._ptr) {
88 swap(o._ptr->weak_from_this());
89 }
90 }
91 weak_ptr& operator=(weak_ptr&& o) noexcept {
92 if (this != &o) {
93 clear();
94 swap(std::move(o));
95 }
96 return *this;
97 }
98 weak_ptr& operator=(const weak_ptr& o) noexcept {
99 if (this != &o) {
100 clear();
101 if (o._ptr) {
102 swap(o._ptr->weak_from_this());
103 }
104 }
105 return *this;
106 }
107 explicit operator bool() const noexcept { return _ptr != nullptr; }
108 T* operator->() const noexcept { return _ptr; }
109 T& operator*() const noexcept { return *_ptr; }
110 T* get() const noexcept { return _ptr; }
111 bool operator==(const weak_ptr& o) const noexcept { return _ptr == o._ptr; }
112 bool operator!=(const weak_ptr& o) const noexcept { return _ptr != o._ptr; }
113};
114
132template<typename T>
134 boost::intrusive::list<weak_ptr<T>,
135 boost::intrusive::member_hook<weak_ptr<T>, typename weak_ptr<T>::hook_type, &weak_ptr<T>::_hook>,
136 boost::intrusive::constant_time_size<false>> _ptr_list;
137public:
138 // Note: The default constructor's body is implemented as no-op
139 // rather than `noexcept = default` due to a bug with gcc 9.3.1
140 // that deletes the constructor since boost::intrusive::member_hook
141 // is not default_nothrow_constructible.
142 weakly_referencable() noexcept {}
143 weakly_referencable(weakly_referencable&&) = delete; // pointer to this is captured and passed to weak_ptr
145 ~weakly_referencable() noexcept {
146 _ptr_list.clear_and_dispose([] (weak_ptr<T>* wp) noexcept {
147 wp->_ptr = nullptr;
148 });
149 }
150 weak_ptr<T> weak_from_this() noexcept {
151 weak_ptr<T> ptr(static_cast<T*>(this));
152 _ptr_list.push_back(ptr);
153 return ptr;
154 }
155
156 weak_ptr<const T> weak_from_this() const noexcept {
157 return const_cast<weakly_referencable*>(this)->weak_from_this();
158 }
159};
160
161}
162
Definition: weak_ptr.hh:46
Definition: weak_ptr.hh:133
Seastar API namespace.
Definition: abort_on_ebadf.hh:26