xref: /trunk/main/sal/inc/rtl/ref.hxx (revision 565d668c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _RTL_REF_HXX_
25 #define _RTL_REF_HXX_
26 
27 #include <sal/types.h>
28 #include <osl/diagnose.h>
29 #include <osl/interlck.h>
30 
31 namespace rtl
32 {
33 
34 /** Interface for a reference type.
35 */
36 class IReference
37 {
38 public:
39 	/** @see osl_incrementInterlockedCount.
40 	 */
41 	virtual oslInterlockedCount SAL_CALL acquire() = 0;
42 
43 	/** @see osl_decrementInterlockedCount.
44 	 */
45 	virtual oslInterlockedCount SAL_CALL release() = 0;
46 };
47 
48 
49 /** Template reference class for reference type derived from IReference.
50 */
51 template <class reference_type>
52 class Reference
53 {
54 	/** The <b>reference_type</b> body pointer.
55 	 */
56 	reference_type * m_pBody;
57 
58 
59 public:
60 	/** Constructor...
61 	 */
Reference()62 	inline Reference()
63 		: m_pBody (0)
64 	{}
65 
66 
67 	/** Constructor...
68 	 */
Reference(reference_type * pBody)69 	inline Reference (reference_type * pBody)
70 		: m_pBody (pBody)
71 	{
72 		if (m_pBody)
73 			m_pBody->acquire();
74 	}
75 
76 
77 	/** Copy constructor...
78 	 */
Reference(const Reference<reference_type> & handle)79 	inline Reference (const Reference<reference_type> & handle)
80 		: m_pBody (handle.m_pBody)
81 	{
82 		if (m_pBody)
83 			m_pBody->acquire();
84 	}
85 
86 
87 	/** Destructor...
88 	 */
~Reference()89 	inline ~Reference()
90 	{
91 		if (m_pBody)
92 			m_pBody->release();
93 	}
94 
95 	/** Set...
96 	 	Similar to assignment.
97 	 */
98 	inline Reference<reference_type> &
set(reference_type * pBody)99 	SAL_CALL set (reference_type * pBody)
100 	{
101 		if (pBody)
102 			pBody->acquire();
103         reference_type * const pOld = m_pBody;
104 		m_pBody = pBody;
105 		if (pOld)
106 			pOld->release();
107 		return *this;
108 	}
109 
110 	/** Assignment.
111 	 	Unbinds this instance from its body (if bound) and
112 	 	bind it to the body represented by the handle.
113 	 */
114 	inline Reference<reference_type> &
operator =(const Reference<reference_type> & handle)115 	SAL_CALL operator= (const Reference<reference_type> & handle)
116 	{
117         return set( handle.m_pBody );
118 	}
119 
120 	/** Assignment...
121 	 */
122 	inline Reference<reference_type> &
operator =(reference_type * pBody)123 	SAL_CALL operator= (reference_type * pBody)
124 	{
125         return set( pBody );
126 	}
127 
128 	/** Unbind the body from this handle.
129 	 	Note that for a handle representing a large body,
130 	 	"handle.clear().set(new body());" _might_
131 	 	perform a little bit better than "handle.set(new body());",
132 	 	since in the second case two large objects exist in memory
133 	 	(the old body and the new body).
134 	 */
clear()135 	inline Reference<reference_type> & SAL_CALL clear()
136 	{
137 		if (m_pBody)
138 		{
139             reference_type * const pOld = m_pBody;
140 			m_pBody = 0;
141 			pOld->release();
142 		}
143 		return *this;
144 	}
145 
146 
147 	/** Get the body. Can be used instead of operator->().
148 	 	I.e. handle->someBodyOp() and handle.get()->someBodyOp()
149 	 	are the same.
150 	 */
get() const151 	inline reference_type * SAL_CALL get() const
152 	{
153 		return m_pBody;
154 	}
155 
156 
157 	/** Probably most common used: handle->someBodyOp().
158 	 */
operator ->() const159 	inline reference_type * SAL_CALL operator->() const
160 	{
161 		OSL_PRECOND(m_pBody, "Reference::operator->() : null body");
162 		return m_pBody;
163 	}
164 
165 
166 	/** Allows (*handle).someBodyOp().
167 	*/
operator *() const168 	inline reference_type & SAL_CALL operator*() const
169 	{
170 		OSL_PRECOND(m_pBody, "Reference::operator*() : null body");
171 		return *m_pBody;
172 	}
173 
174 
175 	/** Returns True if the handle does point to a valid body.
176 	 */
is() const177 	inline sal_Bool SAL_CALL is() const
178 	{
179 		return (m_pBody != 0);
180 	}
181 
182 
183 	/** Returns True if this points to pBody.
184 	 */
operator ==(const reference_type * pBody) const185 	inline sal_Bool SAL_CALL operator== (const reference_type * pBody) const
186 	{
187 		return (m_pBody == pBody);
188 	}
189 
190 
191 	/** Returns True if handle points to the same body.
192 	 */
193 	inline sal_Bool
operator ==(const Reference<reference_type> & handle) const194 	SAL_CALL operator== (const Reference<reference_type> & handle) const
195 	{
196 		return (m_pBody == handle.m_pBody);
197 	}
198 
199 
200 	/** Needed to place References into STL collection.
201 	 */
202 	inline sal_Bool
operator !=(const Reference<reference_type> & handle) const203 	SAL_CALL operator!= (const Reference<reference_type> & handle) const
204 	{
205 		return (m_pBody != handle.m_pBody);
206 	}
207 
208 
209 	/** Needed to place References into STL collection.
210 	 */
211 	inline sal_Bool
operator <(const Reference<reference_type> & handle) const212 	SAL_CALL operator< (const Reference<reference_type> & handle) const
213 	{
214 		return (m_pBody < handle.m_pBody);
215 	}
216 
217 
218 	/** Needed to place References into STL collection.
219 	 */
220 	inline sal_Bool
operator >(const Reference<reference_type> & handle) const221 	SAL_CALL operator> (const Reference<reference_type> & handle) const
222 	{
223 		return (m_pBody > handle.m_pBody);
224 	}
225 };
226 
227 /** @internal
228     Enables boost::mem_fn and boost::bind to recognize Reference.
229 */
230 template <typename T>
get_pointer(Reference<T> const & r)231 inline T * get_pointer( Reference<T> const& r )
232 {
233     return r.get();
234 }
235 
236 } // namespace rtl
237 
238 #endif /* !_RTL_REF_HXX_ */
239