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 _SALHELPER_SIMPLEREFERENCEOBJECT_HXX_
25 #define _SALHELPER_SIMPLEREFERENCEOBJECT_HXX_
26 
27 #include "osl/interlck.h"
28 #include "sal/types.h"
29 
30 #ifndef INCLUDED_CSTDDEF
31 #include <cstddef>
32 #define INCLUDED_CSTDDEF
33 #endif
34 #ifndef INCLUDED_NEW
35 #include <new>
36 #define INCLUDED_NEW
37 #endif
38 
39 #include <salhelper/salhelperdllapi.h>
40 
41 namespace salhelper {
42 
43 /** A simple base implementation for reference-counted objects.
44 
45     Classes that want to implement a reference-counting mechanism based on the
46     acquire()/release() interface should derive from this class.
47 
48     The reason to have class local operators new and delete here is technical.
49     Imagine a class D derived from SimpleReferenceObject, but implemented in
50     another shared library that happens to use different global operators new
51     and delete from those used in this shared library (which, sadly, seems to
52     be possible with shared libraries).  Now, without the class local
53     operators new and delete here, a code sequence like "new D" would use the
54     global operator new as found in the other shared library, while the code
55     sequence "delete this" in release() would use the global operator delete
56     as found in this shared library---and these two operators would not be
57     guaranteed to match.
58 
59     There are no overloaded operators new and delete for placement new here,
60     because it is felt that the concept of placement new does not work well
61     with the concept of reference-counted objects; so it seems best to simply
62     leave those operators out.
63 
64     The same problem as with operators new and delete would also be there with
65     operators new[] and delete[].  But since arrays of reference-counted
66     objects are of no use, anyway, it seems best to simply declare and not
67     define (private) operators new[] and delete[].
68 
69     Note how during the move to gbuild, the delete[] had to be implemented,
70     as missing vector delete errors stopped linking. The small consolation is
71     that is a private method, so it may as well not exist. Right?
72  */
73 #if defined _MSC_VER
74 class SimpleReferenceObject
75 #else
76 class SALHELPER_DLLPUBLIC SimpleReferenceObject
77 #endif
78 {
79 public:
80     inline SimpleReferenceObject() SAL_THROW(()): m_nCount(0) {}
81 
82     /** @ATTENTION
83         The results are undefined if, for any individual instance of
84         SimpleReferenceObject, the total number of calls to acquire() exceeds
85         the total number of calls to release() by a platform dependent amount
86         (which, hopefully, is quite large).
87      */
acquire()88     inline void acquire() SAL_THROW(())
89     { osl_incrementInterlockedCount(&m_nCount); }
90 
release()91     inline void release() SAL_THROW(())
92     { if (osl_decrementInterlockedCount(&m_nCount) == 0) delete this; }
93 
94     /** see general class documentation
95      */
96     SALHELPER_DLLPUBLIC static void * operator new(std::size_t nSize) SAL_THROW((std::bad_alloc));
97 
98     /** see general class documentation
99      */
100     SALHELPER_DLLPUBLIC static void * operator new(std::size_t nSize,
101                                std::nothrow_t const & rNothrow)
102         SAL_THROW(());
103 
104     /** see general class documentation
105      */
106     SALHELPER_DLLPUBLIC static void operator delete(void * pPtr) SAL_THROW(());
107 
108     /** see general class documentation
109      */
110     SALHELPER_DLLPUBLIC static void operator delete(void * pPtr, std::nothrow_t const & rNothrow)
111         SAL_THROW(());
112 
113 protected:
114     SALHELPER_DLLPUBLIC virtual ~SimpleReferenceObject() SAL_THROW(());
115 
116 private:
117     oslInterlockedCount m_nCount;
118 
119     /** not implemented
120         @internal
121      */
122     SimpleReferenceObject(SimpleReferenceObject &);
123 
124     /** not implemented
125         @internal
126      */
127     void operator =(SimpleReferenceObject);
128 
129     /** not implemented (see general class documentation)
130         @internal
131      */
132     static void * operator new[](std::size_t);
133 
134     /** not implemented (see general class documentation)
135         @internal
136      */
137     SALHELPER_DLLPUBLIC static void operator delete[](void * pPtr);
138 };
139 
140 }
141 
142 #endif // _SALHELPER_SIMPLEREFERENCEOBJECT_HXX_
143