blob: a831dd98066191a0a1dc80d83c6e49f63f7125a8 [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