blob: e54728758602fa3f9fffaeb3ecbfd61d1f877d4a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _LOG4CXX_HELPERS_OBJECT_PTR_H
#define _LOG4CXX_HELPERS_OBJECT_PTR_H
#include <log4cxx/log4cxx.h>
//
// Helgrind (race detection tool for Valgrind) will complain if pointer
// is not initialized in an atomic operation. Static analysis tools
// (gcc's -Weffc++, for example) will complain if pointer is not initialized
// in member initialization list. The use of a macro allows quick
// switching between the initialization styles.
//
#if LOG4CXX_HELGRIND
#define _LOG4CXX_OBJECTPTR_INIT(x) : ObjectPtrBase() { exchange(x);
#else
#define _LOG4CXX_OBJECTPTR_INIT(x) : ObjectPtrBase(), p(x) {
#endif
namespace log4cxx
{
namespace helpers
{
class Class;
class LOG4CXX_EXPORT ObjectPtrBase {
public:
ObjectPtrBase();
virtual ~ObjectPtrBase();
static void checkNull(const int& null);
static void* exchange(void** destination, void* newValue);
virtual void* cast(const Class& cls) const = 0;
};
/** smart pointer to a Object descendant */
template<typename T> class ObjectPtrT : public ObjectPtrBase
{
public:
ObjectPtrT(const int& null)
_LOG4CXX_OBJECTPTR_INIT(0)
ObjectPtrBase::checkNull(null);
}
ObjectPtrT()
_LOG4CXX_OBJECTPTR_INIT(0)
}
ObjectPtrT(T * p1)
_LOG4CXX_OBJECTPTR_INIT(p1)
if (this->p != 0)
{
this->p->addRef();
}
}
ObjectPtrT(const ObjectPtrT& p1)
_LOG4CXX_OBJECTPTR_INIT(p1.p)
if (this->p != 0)
{
this->p->addRef();
}
}
ObjectPtrT(const ObjectPtrBase& p1)
_LOG4CXX_OBJECTPTR_INIT(reinterpret_cast<T*>(p1.cast(T::getStaticClass())))
if (this->p != 0) {
this->p->addRef();
}
}
ObjectPtrT(ObjectPtrBase& p1)
_LOG4CXX_OBJECTPTR_INIT(reinterpret_cast<T*>(p1.cast(T::getStaticClass())))
if (this->p != 0) {
this->p->addRef();
}
}
~ObjectPtrT()
{
if (p != 0) {
p->releaseRef();
}
}
ObjectPtrT& operator=(const ObjectPtrT& p1) {
T* newPtr = p1.p;
if (newPtr != 0) {
newPtr->addRef();
}
T* oldPtr = exchange(newPtr);
if (oldPtr != 0) {
oldPtr->releaseRef();
}
return *this;
}
ObjectPtrT& operator=(const int& null) //throw(IllegalArgumentException)
{
//
// throws IllegalArgumentException if null != 0
//
ObjectPtrBase::checkNull(null);
T* oldPtr = exchange(0);
if (oldPtr != 0) {
oldPtr->releaseRef();
}
return *this;
}
ObjectPtrT& operator=(T* p1) {
if (p1 != 0) {
p1->addRef();
}
T* oldPtr = exchange(p1);
if (oldPtr != 0) {
oldPtr->releaseRef();
}
return *this;
}
ObjectPtrT& operator=(ObjectPtrBase& p1) {
T* newPtr = reinterpret_cast<T*>(p1.cast(T::getStaticClass()));
return operator=(newPtr);
}
ObjectPtrT& operator=(const ObjectPtrBase& p1) {
T* newPtr = reinterpret_cast<T*>(p1.cast(T::getStaticClass()));
return operator=(newPtr);
}
bool operator==(const ObjectPtrT& p1) const { return (this->p == p1.p); }
bool operator!=(const ObjectPtrT& p1) const { return (this->p != p1.p); }
bool operator<(const ObjectPtrT& p1) const { return (this->p < p1.p); }
bool operator==(const T* p1) const { return (this->p == p1); }
bool operator!=(const T* p1) const { return (this->p != p1); }
bool operator<(const T* p1) const { return (this->p < p1); }
T* operator->() const {return p; }
T& operator*() const {return *p; }
operator T*() const {return p; }
private:
T * p;
virtual void* cast(const Class& cls) const {
if (p != 0) {
return const_cast<void*>(p->cast(cls));
}
return 0;
}
T* exchange(const T* newValue) {
// Avoid GCC strict aliasing warnings
union {
T** in;
void** out;
} temp = { &p };
return static_cast<T*>(ObjectPtrBase::exchange(
temp.out,
const_cast<T*>(newValue)));
}
};
}
}
#endif //_LOG4CXX_HELPERS_OBJECT_PTR_H