1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef _LOG4CXX_HELPERS_OBJECT_PTR_H
19 #define _LOG4CXX_HELPERS_OBJECT_PTR_H
20 
21 #include <log4cxx/log4cxx.h>
22 
23 //
24 //   Helgrind (race detection tool for Valgrind) will complain if pointer
25 //   is not initialized in an atomic operation.  Static analysis tools
26 //   (gcc's -Weffc++, for example) will complain if pointer is not initialized
27 //   in member initialization list.  The use of a macro allows quick
28 //   switching between the initialization styles.
29 //
30 #if LOG4CXX_HELGRIND
31 	#define _LOG4CXX_OBJECTPTR_INIT(x) : ObjectPtrBase() { exchange(x);
32 #else
33 	#define _LOG4CXX_OBJECTPTR_INIT(x) : ObjectPtrBase(), p(x) {
34 #endif
35 
36 namespace log4cxx
37 {
38 namespace helpers
39 {
40 class Class;
41 
42 class LOG4CXX_EXPORT ObjectPtrBase
43 {
44 	public:
45 		ObjectPtrBase();
46 		virtual ~ObjectPtrBase();
47 		static void checkNull(const int& null);
48 		static void* exchange(void** destination, void* newValue);
49 		virtual void* cast(const Class& cls) const = 0;
50 };
51 
52 
53 /** smart pointer to a Object descendant */
54 template<typename T> class ObjectPtrT : public ObjectPtrBase
55 {
56 	public:
57 		ObjectPtrT(const int& null)
58 		_LOG4CXX_OBJECTPTR_INIT(0)
59 		ObjectPtrBase::checkNull(null);
60 }
61 
62 ObjectPtrT()
63 _LOG4CXX_OBJECTPTR_INIT(0)
64 }
65 
66 ObjectPtrT(T* p1)
67 _LOG4CXX_OBJECTPTR_INIT(p1)
68 
69 if (this->p != 0)
70 {
71 	this->p->addRef();
72 }
73 }
74 
75 
76 ObjectPtrT(const ObjectPtrT& p1)
77 _LOG4CXX_OBJECTPTR_INIT(p1.p)
78 
79 if (this->p != 0)
80 {
81 	this->p->addRef();
82 }
83 }
84 
85 ObjectPtrT(const ObjectPtrBase& p1)
86 _LOG4CXX_OBJECTPTR_INIT(reinterpret_cast<T*>(p1.cast(T::getStaticClass())))
87 
88 if (this->p != 0)
89 {
90 	this->p->addRef();
91 }
92 }
93 
94 ObjectPtrT(ObjectPtrBase& p1)
95 _LOG4CXX_OBJECTPTR_INIT(reinterpret_cast<T*>(p1.cast(T::getStaticClass())))
96 
97 if (this->p != 0)
98 {
99 	this->p->addRef();
100 }
101 }
102 
103 
104 ~ObjectPtrT()
105 {
106 	if (p != 0)
107 	{
108 		p->releaseRef();
109 	}
110 }
111 
112 ObjectPtrT& operator=(const ObjectPtrT& p1)
113 {
114 	T* newPtr = p1.p;
115 
116 	if (newPtr != 0)
117 	{
118 		newPtr->addRef();
119 	}
120 
121 	T* oldPtr = exchange(newPtr);
122 
123 	if (oldPtr != 0)
124 	{
125 		oldPtr->releaseRef();
126 	}
127 
128 	return *this;
129 }
130 
131 ObjectPtrT& operator=(const int& null)   //throw(IllegalArgumentException)
132 {
133 	//
134 	//   throws IllegalArgumentException if null != 0
135 	//
136 	ObjectPtrBase::checkNull(null);
137 	T* oldPtr = exchange(0);
138 
139 	if (oldPtr != 0)
140 	{
141 		oldPtr->releaseRef();
142 	}
143 
144 	return *this;
145 }
146 
147 ObjectPtrT& operator=(T* p1)
148 {
149 	if (p1 != 0)
150 	{
151 		p1->addRef();
152 	}
153 
154 	T* oldPtr = exchange(p1);
155 
156 	if (oldPtr != 0)
157 	{
158 		oldPtr->releaseRef();
159 	}
160 
161 	return *this;
162 }
163 
164 
165 ObjectPtrT& operator=(ObjectPtrBase& p1)
166 {
167 	T* newPtr = reinterpret_cast<T*>(p1.cast(T::getStaticClass()));
168 	return operator=(newPtr);
169 }
170 
171 ObjectPtrT& operator=(const ObjectPtrBase& p1)
172 {
173 	T* newPtr = reinterpret_cast<T*>(p1.cast(T::getStaticClass()));
174 	return operator=(newPtr);
175 }
176 
177 bool operator==(const ObjectPtrT& p1) const
178 {
179 	return (this->p == p1.p);
180 }
181 bool operator!=(const ObjectPtrT& p1) const
182 {
183 	return (this->p != p1.p);
184 }
185 bool operator<(const ObjectPtrT& p1) const
186 {
187 	return (this->p < p1.p);
188 }
189 bool operator==(const T* p1) const
190 {
191 	return (this->p == p1);
192 }
193 bool operator!=(const T* p1) const
194 {
195 	return (this->p != p1);
196 }
197 bool operator<(const T* p1) const
198 {
199 	return (this->p < p1);
200 }
201 T* operator->() const
202 {
203 	return p;
204 }
205 T& operator*() const
206 {
207 	return *p;
208 }
209 operator T* () const
210 {
211 	return p;
212 }
213 
214 
215 
216 private:
217 T* p;
218 virtual void* cast(const Class& cls) const
219 {
220 	if (p != 0)
221 	{
222 		return const_cast<void*>(p->cast(cls));
223 	}
224 
225 	return 0;
226 }
227 T* exchange(const T* newValue)
228 {
229 	// Avoid GCC strict aliasing warnings
230 	union
231 	{
232 		T** in;
233 		void** out;
234 	} temp = { &p };
235 	return static_cast<T*>(ObjectPtrBase::exchange(
236 				temp.out,
237 				const_cast<T*>(newValue)));
238 }
239 
240 };
241 
242 
243 }
244 }
245 
246 #endif //_LOG4CXX_HELPERS_OBJECT_PTR_H
247