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