/* * 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 _DECAF_LANG_POINTER_H_ #define _DECAF_LANG_POINTER_H_ #include #include #include #include #include #include #include #include #include namespace decaf { namespace lang { // Used internally in Pointer. struct STATIC_CAST_TOKEN {}; struct DYNAMIC_CAST_TOKEN {}; /** * Decaf's implementation of a Smart Pointer that is a template on a Type * and is Thread Safe if the default Reference Counter is used. This Pointer * type allows for the substitution of different Reference Counter implementations * which provide a means of using invasive reference counting if desired using * a custom implementation of ReferenceCounter. *

* The Decaf smart pointer provide comparison operators for comparing Pointer * instances in the same manner as normal pointer, except that it does not provide * an overload of operators ( <, <=, >, >= ). To allow use of a Pointer in a STL * container that requires it, Pointer provides an implementation of std::less. * * @since 1.0 */ template class Pointer : public REFCOUNTER { private: typedef void (*deletionFuncPtr)(T* p); private: T* value; // Pointer to our internal delete function. deletionFuncPtr onDelete; public: typedef T* PointerType; // type returned by operator-> typedef T& ReferenceType; // type returned by operator* typedef REFCOUNTER CounterType; // Type of the Reference Counter public: /** * Default Constructor * * Initialized the contained pointer to NULL, using the -> operator * results in an exception unless reset to contain a real value. */ Pointer() : REFCOUNTER(), value(NULL), onDelete(onDeleteFunc) {} /** * Explicit Constructor, creates a Pointer that contains value with a * single reference. This object now has ownership until a call to release. * * @param value - * The instance of the type we are containing here. */ explicit Pointer(const PointerType value) : REFCOUNTER(), value(value), onDelete(onDeleteFunc) {} /** * Copy constructor. Copies the value contained in the pointer to the new * instance and increments the reference counter. * * @param value * Another instance of a Pointer that this Pointer will copy. */ Pointer(const Pointer& value) : REFCOUNTER(value), value(value.value), onDelete(onDeleteFunc) {} /** * Copy constructor. Copies the value contained in the pointer to the new * instance and increments the reference counter. * * @param value * A different but compatible Pointer instance that this Pointer will copy. */ template Pointer(const Pointer& value) : REFCOUNTER(value), value(value.get()), onDelete(onDeleteFunc) {} /** * Static Cast constructor. Copies the value contained in the pointer to the new * instance and increments the reference counter performing a static cast on the * value contained in the source Pointer object. * * @param value * Pointer instance to cast to this type using a static_cast. */ template Pointer(const Pointer& value, const STATIC_CAST_TOKEN&) : REFCOUNTER(value), value(static_cast (value.get())), onDelete(onDeleteFunc) {} /** * Dynamic Cast constructor. Copies the value contained in the pointer to the new * instance and increments the reference counter performing a dynamic cast on the * value contained in the source Pointer object. If the cast fails and return NULL * then this method throws a ClassCastException. * * @param value * Pointer instance to cast to this type using a dynamic_cast. * * @throw ClassCastException if the dynamic cast returns NULL */ template Pointer(const Pointer& value, const DYNAMIC_CAST_TOKEN&) : REFCOUNTER(value), value(dynamic_cast (value.get())), onDelete(onDeleteFunc) { if (this->value == NULL) { // Remove the reference we took in the Reference Counter's ctor since we // didn't actually create one as the dynamic cast failed. REFCOUNTER::release(); throw decaf::lang::exceptions::ClassCastException( __FILE__, __LINE__, "Failed to cast source pointer of type %s to this type: %s.", typeid(T1).name(), typeid(T).name()); } } virtual ~Pointer() { if (REFCOUNTER::release() == true) { onDelete(this->value); } } /** * Resets the Pointer to hold the new value. Before the new value is stored * reset checks if the old value should be destroyed and if so calls delete. * Call reset with a value of NULL is supported and acts to set this Pointer * to a NULL pointer. * * @param value * The new value to contain or NULL to empty the pointer (default NULL if not set). */ void reset(T* value = NULL) { Pointer(value).swap(*this); } /** * Releases the Pointer held and resets the internal pointer value to Null. This method * is not guaranteed to be safe if the Pointer is held by more than one object or this * method is called from more than one thread. * * @returns The pointer instance that was held by this Pointer object, the pointer is * no longer owned by this Pointer and won't be freed when this Pointer goes * out of scope. */ T* release() { T* temp = this->value; this->value = NULL; return temp; } /** * Gets the real pointer that is contained within this Pointer. This is * not really safe since the caller could delete or alter the pointer but * it mimics the STL auto_ptr and gives access in cases where the caller * absolutely needs the real Pointer. Use at your own risk. * * @return the contained pointer. */ PointerType get() const { return this->value; } /** * Exception Safe Swap Function * * @param value * The value to swap with this Pointer. */ void swap(Pointer& value) { std::swap(this->value, value.value); REFCOUNTER::swap(value); } /** * Assigns the value of right to this Pointer and increments the reference Count. * @param right - Pointer on the right hand side of an operator= call to this. */ Pointer& operator=(const Pointer& right) { if (this == (void*) &right) { return *this; } Pointer temp(right); temp.swap(*this); return *this; } template Pointer& operator=(const Pointer& right) { if (this == (void*) &right) { return *this; } Pointer temp(right); temp.swap(*this); return *this; } /** * Dereference Operator, returns a reference to the Contained value. This * method throws an NullPointerException if the contained value is NULL. * * @return reference to the contained pointer. * @throws NullPointerException if the contained value is Null */ ReferenceType operator*() { if (this->value == NULL) { throw decaf::lang::exceptions::NullPointerException( __FILE__, __LINE__, "Pointer operator& - Pointee is NULL."); } return *(this->value); } ReferenceType operator*() const { if (this->value == NULL) { throw decaf::lang::exceptions::NullPointerException( __FILE__, __LINE__, "Pointer operator& - Pointee is NULL."); } return *(this->value); } /** * Indirection Operator, returns a pointer to the Contained value. This * method throws an NullPointerException if the contained value is NULL. * * @return reference to the contained pointer. * @throws NullPointerException if the contained value is Null */ PointerType operator->() { if (this->value == NULL) { throw decaf::lang::exceptions::NullPointerException( __FILE__, __LINE__, "Pointer operator-> - Pointee is NULL."); } return this->value; } PointerType operator->() const { if (this->value == NULL) { throw decaf::lang::exceptions::NullPointerException( __FILE__, __LINE__, "Pointer operator-> - Pointee is NULL."); } return this->value; } bool operator!() const { return this->value == NULL; } inline friend bool operator==(const Pointer& left, const T* right) { return left.get() == right; } inline friend bool operator==(const T* left, const Pointer& right) { return left == right.get(); } inline friend bool operator!=(const Pointer& left, const T* right) { return left.get() != right; } inline friend bool operator!=(const T* left, const Pointer& right) { return left != right.get(); } template bool operator==(const Pointer& right) const { return this->value == right.get(); } template bool operator!=(const Pointer& right) const { return !(this->value == right.get()); } template Pointer dynamicCast() const { return Pointer (*this, DYNAMIC_CAST_TOKEN()); } template Pointer staticCast() const { return Pointer (*this, STATIC_CAST_TOKEN()); } private: // Internal Static deletion function. static void onDeleteFunc(T* value) { delete value; } }; //////////////////////////////////////////////////////////////////////////// template inline bool operator==(const Pointer& left, const U* right) { return left.get() == right; } //////////////////////////////////////////////////////////////////////////// template inline bool operator==(const U* left, const Pointer& right) { return right.get() == left; } //////////////////////////////////////////////////////////////////////////// template inline bool operator!=(const Pointer& left, const U* right) { return !(left.get() == right); } //////////////////////////////////////////////////////////////////////////// template inline bool operator!=(const U* left, const Pointer& right) { return right.get() != left; } //////////////////////////////////////////////////////////////////////////// template std::ostream& operator<<(std::ostream &out, const Pointer& pointer) { out << pointer.get(); return out; } /** * This implementation of Comparator is designed to allows objects in a Collection * to be sorted or tested for equality based on the value of the Object being Pointed * to and not the value of the contained pointer in the Pointer instance. This can * be useful in the case where a series of values in a Collection is more efficiently * accessed in the Objects Natural Order and not the underlying pointers location in * memory. *

* Also this allows Pointer objects that Point to different instances of the same type * to be compared based on the comparison of the object itself and not just the value of * the pointer. */ template class PointerComparator: public decaf::util::Comparator > { public: virtual ~PointerComparator() {} // Allows for operator less on types that implement Comparable or provide // a workable operator < virtual bool operator()(const Pointer& left, const Pointer& right) const { return *left < *right; } // Requires that the type in the pointer is an instance of a Comparable. virtual int compare(const Pointer& left, const Pointer& right) const { return *left < *right ? -1 : *right < *left ? 1 : 0; } }; }} //////////////////////////////////////////////////////////////////////////////// namespace std { /** * An override of the less function object so that the Pointer objects * can be stored in STL Maps, etc. */ template struct less > { //: public binary_function, decaf::lang::Pointer, bool> { typedef decaf::lang::Pointer first_argument_type; typedef decaf::lang::Pointer second_argument_type; typedef bool result_type; bool operator()(const decaf::lang::Pointer& left, const decaf::lang::Pointer& right) const { return less ()(left.get(), right.get()); } }; } #endif /*_DECAF_LANG_POINTER_H_*/