neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
i_reference_counted.hpp
Go to the documentation of this file.
1// i_reference_counted.hpp
2/*
3 * Copyright (c) 2019, 2020 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
39#include <type_traits>
40
41namespace neolib
42{
43 class i_reference_counted;
44
46 {
47 public:
48 virtual ~i_ref_control_block() = default;
49 public:
50 virtual i_reference_counted* ptr() const noexcept = 0;
51 virtual bool expired() const noexcept = 0;
52 virtual int32_t weak_use_count() const noexcept = 0;
53 virtual void add_ref() noexcept = 0;
54 virtual void release() = 0;
55 };
56
58 {
59 public:
60 struct too_many_references : std::logic_error { too_many_references() : std::logic_error("i_reference_counted::too_many_references") {} };
61 struct release_during_destruction : std::logic_error { release_during_destruction() : std::logic_error("i_reference_counted::release_during_destruction") {} };
62 public:
63 virtual ~i_reference_counted() = default;
64 public:
65 virtual void add_ref() const noexcept = 0;
66 virtual void release() const = 0;
67 virtual int32_t use_count() const noexcept = 0;
68 virtual const i_reference_counted* release_and_take_ownership() const = 0;
69 virtual i_reference_counted* release_and_take_ownership() = 0;
70 virtual void pin() const noexcept = 0;
71 virtual void unpin() const = 0;
72 public:
73 virtual i_ref_control_block& control_block() = 0;
74 };
75
76 template <typename Interface>
78 {
80 public:
81 struct no_object : std::logic_error { no_object() : std::logic_error("i_ref_ptr::no_object") {} };
82 struct no_managed_object : std::logic_error { no_managed_object() : std::logic_error("i_ref_ptr::no_managed_object") {} };
83 struct interface_not_found : std::logic_error { interface_not_found() : std::logic_error("i_ref_ptr::interface_not_found") {} };
84 public:
86 public:
87 virtual ~i_ref_ptr() = default;
88 public:
89 virtual bool reference_counted() const noexcept = 0;
90 virtual int32_t use_count() const noexcept = 0;
91 virtual void reset() = 0;
92 virtual void reset(Interface* aPtr) = 0;
93 virtual void reset(Interface* aPtr, Interface* aManagedPtr) = 0;
94 virtual void reset(Interface* aPtr, Interface* aManagedPtr, bool aReferenceCounted, bool aAddRef) = 0;
95 virtual Interface* release() = 0;
96 virtual Interface* detach() = 0;
97 virtual bool valid() const noexcept = 0;
98 virtual bool managing() const noexcept = 0;
99 virtual Interface* ptr() const noexcept = 0;
100 virtual Interface* managed_ptr() const noexcept = 0;
101 virtual Interface* operator->() const = 0;
102 virtual Interface& operator*() const = 0;
103 i_ref_ptr& operator=(const i_ref_ptr& aOther) { reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(), true); return *this; }
104 template <typename Interface2>
105 i_ref_ptr& operator=(const i_ref_ptr<Interface2>& aOther) { reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(), true); return *this; }
106 explicit operator bool() const noexcept { return valid(); }
107 bool operator==(std::nullptr_t) const noexcept { return !valid(); }
108 bool operator!=(std::nullptr_t) const noexcept { return valid(); }
109 template <typename Interface2>
110 bool operator==(const i_ref_ptr<Interface2>& aOther) const noexcept { return ptr() == aOther.ptr(); }
111 template <typename Interface2>
112 bool operator!=(const i_ref_ptr<Interface2>& aOther) const noexcept { return ptr() != aOther.ptr(); }
113 template <typename Interface2>
114 bool operator<(const i_ref_ptr<Interface2>& aOther) const noexcept { return ptr() < aOther.ptr(); }
115 };
116
117 template <typename Interface1, typename Interface2>
118 inline bool operator==(const i_ref_ptr<Interface1>& lhs, const Interface2* rhs) noexcept
119 {
120 return static_cast<const abstract_t<Interface1>*>(lhs.ptr()) == static_cast<const abstract_t<Interface1>*>(rhs);
121 }
122
123 template <typename Interface1, typename Interface2>
124 inline bool operator==(const Interface2* lhs, const i_ref_ptr<Interface1>& rhs) noexcept
125 {
126 return static_cast<const abstract_t<Interface1>*>(lhs) == static_cast<const abstract_t<Interface1>*>(rhs.ptr());
127 }
128
129 template <typename Interface1, typename Interface2>
130 inline bool operator!=(const i_ref_ptr<Interface1>& lhs, const Interface2* rhs) noexcept
131 {
132 return !(lhs == rhs);
133 }
134
135 template <typename Interface1, typename Interface2>
136 inline bool operator!=(const Interface2* lhs, const i_ref_ptr<Interface1>& rhs) noexcept
137 {
138 return !(lhs == rhs);
139 }
140
141 template <typename Interface1, typename Interface2>
142 inline bool operator<(const i_ref_ptr<Interface1>& lhs, const Interface2* rhs) noexcept
143 {
144 return static_cast<const abstract_t<Interface1>*>(lhs.ptr()) < static_cast<const abstract_t<Interface1>*>(rhs);
145 }
146
147 template <typename Interface1, typename Interface2>
148 inline bool operator<(const Interface2* lhs, const i_ref_ptr<Interface1>& rhs) noexcept
149 {
150 return static_cast<const abstract_t<Interface1>*>(lhs) < static_cast<const abstract_t<Interface1>*>(rhs.ptr());
151 }
152
153 template <typename Interface>
154 class i_weak_ref_ptr : public i_ref_ptr<Interface>
155 {
156 public:
157 struct bad_release : std::logic_error { bad_release() : std::logic_error("i_weak_ref_ptr::bad_release") {} };
158 struct wrong_object : std::logic_error { wrong_object() : std::logic_error("i_weak_ref_ptr::wrong_object") {} };
159 public:
160 virtual bool expired() const noexcept = 0;
161 };
162}
virtual void release()=0
virtual bool expired() const noexcept=0
virtual void add_ref() noexcept=0
virtual ~i_ref_control_block()=default
virtual i_reference_counted * ptr() const noexcept=0
virtual int32_t weak_use_count() const noexcept=0
bool operator!=(const i_ref_ptr< Interface2 > &aOther) const noexcept
virtual bool reference_counted() const noexcept=0
virtual ~i_ref_ptr()=default
bool operator==(const i_ref_ptr< Interface2 > &aOther) const noexcept
virtual Interface * ptr() const noexcept=0
bool operator<(const i_ref_ptr< Interface2 > &aOther) const noexcept
i_ref_ptr & operator=(const i_ref_ptr< Interface2 > &aOther)
bool operator!=(std::nullptr_t) const noexcept
virtual Interface * managed_ptr() const noexcept=0
bool operator==(std::nullptr_t) const noexcept
virtual ~i_reference_counted()=default
virtual void add_ref() const noexcept=0
virtual bool expired() const noexcept=0
typename detail::abstract_type< T >::type abstract_t
Definition neolib.hpp:178