xref: /AOO41X/main/sal/inc/rtl/ref.hxx (revision 565d668c30d8a6cacc881c774c5068be5401257d)
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