X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fmsg%2Fasync%2Fdpdk%2Fshared_ptr.h;fp=src%2Fceph%2Fsrc%2Fmsg%2Fasync%2Fdpdk%2Fshared_ptr.h;h=11fbf2c90582a2e81aac837d6b707f37950851c9;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/msg/async/dpdk/shared_ptr.h b/src/ceph/src/msg/async/dpdk/shared_ptr.h new file mode 100644 index 0000000..11fbf2c --- /dev/null +++ b/src/ceph/src/msg/async/dpdk/shared_ptr.h @@ -0,0 +1,266 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +/* + * This file is open source software, licensed to you under the terms + * of the Apache License, Version 2.0 (the "License"). See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. You may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * Copyright (C) 2014 Cloudius Systems, Ltd. + */ + +#ifndef CEPH_LW_SHARED_PTR_H_ +#define CEPH_LW_SHARED_PTR_H_ + +#include +#include +#include +#include + +// This header defines two shared pointer facilities, lw_shared_ptr<> +// modeled after std::shared_ptr<>. +// +// Unlike std::shared_ptr<>, neither of these implementations are thread +// safe, and two pointers sharing the same object must not be used in +// different threads. +// +// lw_shared_ptr<> is the more lightweight variant, with a lw_shared_ptr<> +// occupying just one machine word, and adding just one word to the shared +// object. However, it does not support polymorphism. +// +// Both variants support shared_from_this() via enable_shared_from_this<> +// and lw_enable_shared_from_this<>(). +// + +template< class T > +using remove_const_t = typename remove_const::type; + +template +class lw_shared_ptr; + +template +lw_shared_ptr make_lw_shared(A&&... a); + +template +lw_shared_ptr make_lw_shared(T&& a); + +template +lw_shared_ptr make_lw_shared(T& a); + +// CRTP from this to enable shared_from_this: +template +class enable_lw_shared_from_this { + long _count = 0; + using ctor = T; + T* to_value() { return static_cast(this); } + T* to_internal_object() { return static_cast(this); } + protected: + enable_lw_shared_from_this() noexcept {} + enable_lw_shared_from_this(enable_lw_shared_from_this&&) noexcept {} + enable_lw_shared_from_this(const enable_lw_shared_from_this&) noexcept {} + enable_lw_shared_from_this& operator=(const enable_lw_shared_from_this&) noexcept { return *this; } + enable_lw_shared_from_this& operator=(enable_lw_shared_from_this&&) noexcept { return *this; } + public: + lw_shared_ptr shared_from_this(); + lw_shared_ptr shared_from_this() const; + template + friend class lw_shared_ptr; +}; + +template +struct shared_ptr_no_esft { + T _value; + using ctor = shared_ptr_no_esft; + + T* to_value() { return &_value; } + shared_ptr_no_esft* to_internal_object() { return this; } + shared_ptr_no_esft() = default; + shared_ptr_no_esft(const T& x) : _value(x) {} + shared_ptr_no_esft(T&& x) : _value(std::move(x)) {} + template + shared_ptr_no_esft(A&&... a) : _value(std::forward(a)...) {} + template + friend class lw_shared_ptr; +}; + +template +using shared_ptr_impl = typename std::conditional< + std::is_base_of>, T>::value, + enable_lw_shared_from_this>, + shared_ptr_no_esft> >::type; + +template +class lw_shared_ptr { + mutable shared_ptr_impl* _p = nullptr; + private: + lw_shared_ptr(shared_ptr_impl* p) noexcept : _p(p) { + if (_p) { + ++_p->_count; + } + } + template + static lw_shared_ptr make(A&&... a) { + return lw_shared_ptr(new typename shared_ptr_impl::ctor(std::forward(a)...)); + } + public: + using element_type = T; + + lw_shared_ptr() noexcept = default; + lw_shared_ptr(std::nullptr_t) noexcept : lw_shared_ptr() {} + lw_shared_ptr(const lw_shared_ptr& x) noexcept : _p(x._p) { + if (_p) { + ++_p->_count; + } + } + lw_shared_ptr(lw_shared_ptr&& x) noexcept : _p(x._p) { + x._p = nullptr; + } + [[gnu::always_inline]] + ~lw_shared_ptr() { + if (_p && !--_p->_count) { + delete _p->to_internal_object(); + } + } + lw_shared_ptr& operator=(const lw_shared_ptr& x) noexcept { + if (_p != x._p) { + this->~lw_shared_ptr(); + new (this) lw_shared_ptr(x); + } + return *this; + } + lw_shared_ptr& operator=(lw_shared_ptr&& x) noexcept { + if (_p != x._p) { + this->~lw_shared_ptr(); + new (this) lw_shared_ptr(std::move(x)); + } + return *this; + } + lw_shared_ptr& operator=(std::nullptr_t) noexcept { + return *this = lw_shared_ptr(); + } + lw_shared_ptr& operator=(T&& x) noexcept { + this->~lw_shared_ptr(); + new (this) lw_shared_ptr(make_lw_shared(std::move(x))); + return *this; + } + + T& operator*() const noexcept { return *_p->to_value(); } + T* operator->() const noexcept { return _p->to_value(); } + T* get() const noexcept { return _p->to_value(); } + + long int use_count() const noexcept { + if (_p) { + return _p->_count; + } else { + return 0; + } + } + + operator lw_shared_ptr() const noexcept { + return lw_shared_ptr(_p); + } + + explicit operator bool() const noexcept { + return _p; + } + + bool owned() const noexcept { + return _p->_count == 1; + } + + bool operator==(const lw_shared_ptr& x) const { + return _p == x._p; + } + + bool operator!=(const lw_shared_ptr& x) const { + return !operator==(x); + } + + bool operator==(const lw_shared_ptr>& x) const { + return _p == x._p; + } + + bool operator!=(const lw_shared_ptr>& x) const { + return !operator==(x); + } + + template + friend class lw_shared_ptr; + + template + friend lw_shared_ptr make_lw_shared(A&&...); + + template + friend lw_shared_ptr make_lw_shared(U&&); + + template + friend lw_shared_ptr make_lw_shared(U&); + + template + friend class enable_lw_shared_from_this; +}; + +template +inline +lw_shared_ptr make_lw_shared(A&&... a) { + return lw_shared_ptr::make(std::forward(a)...); +} + +template +inline +lw_shared_ptr make_lw_shared(T&& a) { + return lw_shared_ptr::make(std::move(a)); +} + +template +inline +lw_shared_ptr make_lw_shared(T& a) { + return lw_shared_ptr::make(a); +} + +template +inline +lw_shared_ptr +enable_lw_shared_from_this::shared_from_this() { + return lw_shared_ptr(this); +} + +template +inline +lw_shared_ptr +enable_lw_shared_from_this::shared_from_this() const { + return lw_shared_ptr(const_cast(this)); +} + +template +static inline +std::ostream& operator<<(std::ostream& out, const lw_shared_ptr& p) { + if (!p) { + return out << "null"; + } + return out << *p; +} + +namespace std { + + template + struct hash> : private hash { + size_t operator()(const lw_shared_ptr& p) const { + return hash::operator()(p.get()); + } + }; + +} + +#endif /* CEPH_LW_SHARED_PTR_H_ */