1 | |
2 | // |
3 | // This source file is part of appleseed. |
4 | // Visit http://appleseedhq.net/ for additional information and resources. |
5 | // |
6 | // This software is released under the MIT license. |
7 | // |
8 | // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited |
9 | // Copyright (c) 2014-2017 Francois Beaune, The appleseedhq Organization |
10 | // |
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
12 | // of this software and associated documentation files (the "Software"), to deal |
13 | // in the Software without restriction, including without limitation the rights |
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
15 | // copies of the Software, and to permit persons to whom the Software is |
16 | // furnished to do so, subject to the following conditions: |
17 | // |
18 | // The above copyright notice and this permission notice shall be included in |
19 | // all copies or substantial portions of the Software. |
20 | // |
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
27 | // THE SOFTWARE. |
28 | // |
29 | |
30 | #ifndef APPLESEED_FOUNDATION_UTILITY_AUTORELEASEPTR_H |
31 | #define APPLESEED_FOUNDATION_UTILITY_AUTORELEASEPTR_H |
32 | |
33 | // Standard headers. |
34 | #include <cassert> |
35 | |
36 | namespace foundation |
37 | { |
38 | |
39 | // |
40 | // Similarly to std::auto_ptr, foundation::auto_release_ptr is a smart pointer |
41 | // providing strict ownership semantics. The only difference with std::auto_ptr |
42 | // is that the pointed object is deleted using foundation::IUnknown::release() |
43 | // instead of the delete operator. |
44 | // |
45 | |
46 | // A wrapper class to provide auto_release_ptr with reference semantics. |
47 | template <typename T> |
48 | struct auto_release_ptr_ref |
49 | { |
50 | T* m_ptr; |
51 | |
52 | explicit auto_release_ptr_ref(T* ptr) |
53 | : m_ptr(ptr) |
54 | { |
55 | } |
56 | }; |
57 | |
58 | template <typename T> |
59 | class auto_release_ptr |
60 | { |
61 | public: |
62 | typedef T element_type; |
63 | |
64 | // Construct from a raw pointer. |
65 | explicit auto_release_ptr(T* ptr = 0) throw() |
66 | : m_ptr(ptr) |
67 | { |
68 | } |
69 | |
70 | // Construct from another auto_release_ptr of the same type. |
71 | auto_release_ptr(auto_release_ptr& rhs) throw() |
72 | : m_ptr(rhs.release()) |
73 | { |
74 | } |
75 | |
76 | // Construct from another auto_release_ptr of a different but related type. |
77 | template <typename U> |
78 | auto_release_ptr(auto_release_ptr<U>& rhs) throw() |
79 | : m_ptr(rhs.release()) |
80 | { |
81 | } |
82 | |
83 | // Construct from an auto_release_ptr_ref. |
84 | auto_release_ptr(auto_release_ptr_ref<T> ref) throw() |
85 | : m_ptr(ref.m_ptr) |
86 | { |
87 | } |
88 | |
89 | // Assign from another auto_release_ptr of the same type. |
90 | auto_release_ptr& operator=(auto_release_ptr& rhs) throw() |
91 | { |
92 | reset(rhs.release()); |
93 | return *this; |
94 | } |
95 | |
96 | // Assign from another auto_release_ptr of a different but related type. |
97 | template <typename U> |
98 | auto_release_ptr& operator=(auto_release_ptr<U>& rhs) throw() |
99 | { |
100 | reset(rhs.release()); |
101 | return *this; |
102 | } |
103 | |
104 | // Assign from an auto_release_ptr_ref. |
105 | auto_release_ptr<T>& operator=(auto_release_ptr_ref<T> ref) throw() |
106 | { |
107 | if (m_ptr != ref.m_ptr) |
108 | { |
109 | if (m_ptr) |
110 | m_ptr->release(); |
111 | |
112 | m_ptr = ref.m_ptr; |
113 | } |
114 | |
115 | return *this; |
116 | } |
117 | |
118 | // Delete the wrapped pointer. |
119 | ~auto_release_ptr() |
120 | { |
121 | if (m_ptr) |
122 | m_ptr->release(); |
123 | } |
124 | |
125 | // Automatic conversion to an auto_release_ptr_ref. |
126 | template <typename U> |
127 | operator auto_release_ptr_ref<U>() throw() |
128 | { |
129 | return auto_release_ptr_ref<U>(release()); |
130 | } |
131 | |
132 | // Automatic conversion to an auto_release_ptr of a different type. |
133 | template <typename U> |
134 | operator auto_release_ptr<U>() throw() |
135 | { |
136 | return auto_release_ptr<U>(release()); |
137 | } |
138 | |
139 | // Dereference the wrapped pointer. |
140 | T& operator*() const throw() |
141 | { |
142 | assert(m_ptr); |
143 | return *m_ptr; |
144 | } |
145 | T* operator->() const throw() |
146 | { |
147 | assert(m_ptr); |
148 | return m_ptr; |
149 | } |
150 | |
151 | // Return the wrapped pointer. |
152 | T* get() const throw() |
153 | { |
154 | return m_ptr; |
155 | } |
156 | T& ref() const throw() |
157 | { |
158 | assert(m_ptr); |
159 | return *m_ptr; |
160 | } |
161 | |
162 | // Return the wrapped pointer and give up ownership. |
163 | T* release() throw() |
164 | { |
165 | T* rv = m_ptr; |
166 | m_ptr = 0; |
167 | return rv; |
168 | } |
169 | |
170 | // Delete the owned pointer and replace it with the provided raw pointer. |
171 | void reset(T* ptr = 0) throw() |
172 | { |
173 | if (m_ptr != ptr) |
174 | { |
175 | if (m_ptr) |
176 | m_ptr->release(); |
177 | |
178 | m_ptr = ptr; |
179 | } |
180 | } |
181 | |
182 | private: |
183 | T* m_ptr; |
184 | }; |
185 | |
186 | } // namespace foundation |
187 | |
188 | #endif // !APPLESEED_FOUNDATION_UTILITY_AUTORELEASEPTR_H |
189 | |