xref: /trunk/main/sal/inc/rtl/ref.hxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef _RTL_REF_HXX_
29 #define _RTL_REF_HXX_
30 
31 #include <sal/types.h>
32 #include <osl/diagnose.h>
33 #include <osl/interlck.h>
34 
35 namespace rtl
36 {
37 
38 /** Interface for a reference type.
39 */
40 class IReference
41 {
42 public:
43     /** @see osl_incrementInterlockedCount.
44      */
45     virtual oslInterlockedCount SAL_CALL acquire() = 0;
46 
47     /** @see osl_decrementInterlockedCount.
48      */
49     virtual oslInterlockedCount SAL_CALL release() = 0;
50 };
51 
52 
53 /** Template reference class for reference type derived from IReference.
54 */
55 template <class reference_type>
56 class Reference
57 {
58     /** The <b>reference_type</b> body pointer.
59      */
60     reference_type * m_pBody;
61 
62 
63 public:
64     /** Constructor...
65      */
66     inline Reference()
67         : m_pBody (0)
68     {}
69 
70 
71     /** Constructor...
72      */
73     inline Reference (reference_type * pBody)
74         : m_pBody (pBody)
75     {
76         if (m_pBody)
77             m_pBody->acquire();
78     }
79 
80 
81     /** Copy constructor...
82      */
83     inline Reference (const Reference<reference_type> & handle)
84         : m_pBody (handle.m_pBody)
85     {
86         if (m_pBody)
87             m_pBody->acquire();
88     }
89 
90 
91     /** Destructor...
92      */
93     inline ~Reference()
94     {
95         if (m_pBody)
96             m_pBody->release();
97     }
98 
99     /** Set...
100         Similar to assignment.
101      */
102     inline Reference<reference_type> &
103     SAL_CALL set (reference_type * pBody)
104     {
105         if (pBody)
106             pBody->acquire();
107         reference_type * const pOld = m_pBody;
108         m_pBody = pBody;
109         if (pOld)
110             pOld->release();
111         return *this;
112     }
113 
114     /** Assignment.
115         Unbinds this instance from its body (if bound) and
116         bind it to the body represented by the handle.
117      */
118     inline Reference<reference_type> &
119     SAL_CALL operator= (const Reference<reference_type> & handle)
120     {
121         return set( handle.m_pBody );
122     }
123 
124     /** Assignment...
125      */
126     inline Reference<reference_type> &
127     SAL_CALL operator= (reference_type * pBody)
128     {
129         return set( pBody );
130     }
131 
132     /** Unbind the body from this handle.
133         Note that for a handle representing a large body,
134         "handle.clear().set(new body());" _might_
135         perform a little bit better than "handle.set(new body());",
136         since in the second case two large objects exist in memory
137         (the old body and the new body).
138      */
139     inline Reference<reference_type> & SAL_CALL clear()
140     {
141         if (m_pBody)
142         {
143             reference_type * const pOld = m_pBody;
144             m_pBody = 0;
145             pOld->release();
146         }
147         return *this;
148     }
149 
150 
151     /** Get the body. Can be used instead of operator->().
152         I.e. handle->someBodyOp() and handle.get()->someBodyOp()
153         are the same.
154      */
155     inline reference_type * SAL_CALL get() const
156     {
157         return m_pBody;
158     }
159 
160 
161     /** Probably most common used: handle->someBodyOp().
162      */
163     inline reference_type * SAL_CALL operator->() const
164     {
165         OSL_PRECOND(m_pBody, "Reference::operator->() : null body");
166         return m_pBody;
167     }
168 
169 
170     /** Allows (*handle).someBodyOp().
171     */
172     inline reference_type & SAL_CALL operator*() const
173     {
174         OSL_PRECOND(m_pBody, "Reference::operator*() : null body");
175         return *m_pBody;
176     }
177 
178 
179     /** Returns True if the handle does point to a valid body.
180      */
181     inline sal_Bool SAL_CALL is() const
182     {
183         return (m_pBody != 0);
184     }
185 
186 
187     /** Returns True if this points to pBody.
188      */
189     inline sal_Bool SAL_CALL operator== (const reference_type * pBody) const
190     {
191         return (m_pBody == pBody);
192     }
193 
194 
195     /** Returns True if handle points to the same body.
196      */
197     inline sal_Bool
198     SAL_CALL operator== (const Reference<reference_type> & handle) const
199     {
200         return (m_pBody == handle.m_pBody);
201     }
202 
203 
204     /** Needed to place References into STL collection.
205      */
206     inline sal_Bool
207     SAL_CALL operator!= (const Reference<reference_type> & handle) const
208     {
209         return (m_pBody != handle.m_pBody);
210     }
211 
212 
213     /** Needed to place References into STL collection.
214      */
215     inline sal_Bool
216     SAL_CALL operator< (const Reference<reference_type> & handle) const
217     {
218         return (m_pBody < handle.m_pBody);
219     }
220 
221 
222     /** Needed to place References into STL collection.
223      */
224     inline sal_Bool
225     SAL_CALL operator> (const Reference<reference_type> & handle) const
226     {
227         return (m_pBody > handle.m_pBody);
228     }
229 };
230 
231 /** @internal
232     Enables boost::mem_fn and boost::bind to recognize Reference.
233 */
234 template <typename T>
235 inline T * get_pointer( Reference<T> const& r )
236 {
237     return r.get();
238 }
239 
240 } // namespace rtl
241 
242 #endif /* !_RTL_REF_HXX_ */
243