Fix #10490: Allow ships to exit depots if another is not moving at the exit point...
[openttd-github.git] / src / misc / countedptr.hpp
blob625b124200eafed057e0c890aa6bd60ce8b4d13c
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
8 /** @file countedptr.hpp CCountedPtr - smart pointer implementation. */
10 #ifndef COUNTEDPTR_HPP
11 #define COUNTEDPTR_HPP
13 /**
14 * CCountedPtr - simple reference counting smart pointer.
16 * One of the standard ways how to maintain object's lifetime.
18 * See http://ootips.org/yonat/4dev/smart-pointers.html for more
19 * general info about smart pointers.
21 * This class implements ref-counted pointer for objects/interfaces that
22 * support AddRef() and Release() methods.
24 template <class Tcls_>
25 class CCountedPtr {
26 /** redefine the template argument to make it visible for derived classes */
27 public:
28 typedef Tcls_ Tcls;
30 protected:
31 /** here we hold our pointer to the target */
32 Tcls *m_pT;
34 public:
35 /** default (nullptr) construct or construct from a raw pointer */
36 inline CCountedPtr(Tcls *pObj = nullptr) : m_pT(pObj)
38 AddRef();
41 /** copy constructor (invoked also when initializing from another smart ptr) */
42 inline CCountedPtr(const CCountedPtr &src) : m_pT(src.m_pT)
44 AddRef();
47 /** destructor releasing the reference */
48 inline ~CCountedPtr()
50 Release();
53 protected:
54 /** add one ref to the underlying object */
55 inline void AddRef()
57 if (m_pT != nullptr) m_pT->AddRef();
60 public:
61 /** release smart pointer (and decrement ref count) if not null */
62 inline void Release()
64 if (m_pT != nullptr) {
65 Tcls *pT = m_pT;
66 m_pT = nullptr;
67 pT->Release();
71 /** dereference of smart pointer - const way */
72 inline const Tcls *operator->() const
74 assert(m_pT != nullptr);
75 return m_pT;
78 /** dereference of smart pointer - non const way */
79 inline Tcls *operator->()
81 assert(m_pT != nullptr);
82 return m_pT;
85 /** raw pointer casting operator - const way */
86 inline operator const Tcls*() const
88 assert(m_pT == nullptr);
89 return m_pT;
92 /** raw pointer casting operator - non-const way */
93 inline operator Tcls*()
95 return m_pT;
98 /** operator & to support output arguments */
99 inline Tcls** operator&()
101 assert(m_pT == nullptr);
102 return &m_pT;
105 /** assignment operator from raw ptr */
106 inline CCountedPtr& operator=(Tcls *pT)
108 Assign(pT);
109 return *this;
112 /** assignment operator from another smart ptr */
113 inline CCountedPtr& operator=(const CCountedPtr &src)
115 Assign(src.m_pT);
116 return *this;
119 /** assignment operator helper */
120 inline void Assign(Tcls *pT);
122 /** one way how to test for nullptr value */
123 inline bool IsNull() const
125 return m_pT == nullptr;
128 /** assign pointer w/o incrementing ref count */
129 inline void Attach(Tcls *pT)
131 Release();
132 m_pT = pT;
135 /** detach pointer w/o decrementing ref count */
136 inline Tcls *Detach()
138 Tcls *pT = m_pT;
139 m_pT = nullptr;
140 return pT;
144 template <class Tcls_>
145 inline void CCountedPtr<Tcls_>::Assign(Tcls *pT)
147 /* if they are the same, we do nothing */
148 if (pT != m_pT) {
149 if (pT != nullptr) pT->AddRef(); // AddRef new pointer if any
150 Tcls *pTold = m_pT; // save original ptr
151 m_pT = pT; // update m_pT to new value
152 if (pTold != nullptr) pTold->Release(); // release old ptr if any
157 * Adapter wrapper for CCountedPtr like classes that can't be used directly by stl
158 * collections as item type. For example CCountedPtr has overloaded operator & which
159 * prevents using CCountedPtr in stl collections (i.e. std::list<CCountedPtr<MyType> >)
161 template <class T> struct AdaptT {
162 T m_t;
164 /** construct by wrapping the given object */
165 AdaptT(const T &t)
166 : m_t(t)
169 /** assignment operator */
170 T& operator = (const T &t)
172 m_t = t;
173 return t;
176 /** type-cast operator (used when AdaptT is used instead of T) */
177 operator T& ()
179 return m_t;
182 /** const type-cast operator (used when AdaptT is used instead of const T) */
183 operator const T& () const
185 return m_t;
190 * Simple counted object. Use it as base of your struct/class if you want to use
191 * basic reference counting. Your struct/class will destroy and free itself when
192 * last reference to it is released (using Release() method). The initial reference
193 * count (when it is created) is zero (don't forget AddRef() at least one time if
194 * not using CCountedPtr<T>.
196 * @see misc/countedobj.cpp for implementation.
198 struct SimpleCountedObject {
199 int32_t m_ref_cnt;
201 SimpleCountedObject()
202 : m_ref_cnt(0)
205 virtual ~SimpleCountedObject()
208 virtual int32_t AddRef();
209 virtual int32_t Release();
210 virtual void FinalRelease() {};
213 #endif /* COUNTEDPTR_HPP */