log4cplus  1.1.0
pointer.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 // Module:  Log4CPLUS
00003 // File:    pointer.h
00004 // Created: 6/2001
00005 // Author:  Tad E. Smith
00006 //
00007 //
00008 // Copyright 2001-2010 Tad E. Smith
00009 //
00010 // Licensed under the Apache License, Version 2.0 (the "License");
00011 // you may not use this file except in compliance with the License.
00012 // You may obtain a copy of the License at
00013 //
00014 //     http://www.apache.org/licenses/LICENSE-2.0
00015 //
00016 // Unless required by applicable law or agreed to in writing, software
00017 // distributed under the License is distributed on an "AS IS" BASIS,
00018 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019 // See the License for the specific language governing permissions and
00020 // limitations under the License.
00021 
00022 //
00023 // Note: Some of this code uses ideas from "More Effective C++" by Scott
00024 // Myers, Addison Wesley Longmain, Inc., (c) 1996, Chapter 29, pp. 183-213
00025 //
00026 
00029 #ifndef LOG4CPLUS_HELPERS_POINTERS_HEADER_
00030 #define LOG4CPLUS_HELPERS_POINTERS_HEADER_
00031 
00032 #include <log4cplus/config.hxx>
00033 
00034 #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
00035 #pragma once
00036 #endif
00037 
00038 #include <log4cplus/thread/syncprims.h>
00039 #include <algorithm>
00040 #include <cassert>
00041 #if ! defined (LOG4CPLUS_SINGLE_THREADED) \
00042     && defined (LOG4CPLUS_HAVE_CXX11_ATOMICS)
00043 #include <atomic>
00044 #endif
00045 
00046 
00047 namespace log4cplus {
00048     namespace helpers {
00049 
00050         /******************************************************************************
00051          *                       Class SharedObject (from pp. 204-205)                *
00052          ******************************************************************************/
00053 
00054         class LOG4CPLUS_EXPORT SharedObject
00055         {
00056         public:
00057             void addReference() const;
00058             void removeReference() const;
00059 
00060         protected:
00061           // Ctor
00062             SharedObject()
00063                 : access_mutex()
00064                 , count(0)
00065             { }
00066 
00067             SharedObject(const SharedObject&)
00068                 : access_mutex()
00069                 , count(0)
00070             { }
00071 
00072           // Dtor
00073             virtual ~SharedObject();
00074 
00075           // Operators
00076             SharedObject& operator=(const SharedObject&) { return *this; }
00077 
00078         public:
00079             thread::Mutex access_mutex;
00080 
00081         private:
00082 #if defined (LOG4CPLUS_SINGLE_THREADED)
00083             typedef unsigned count_type;
00084 #elif defined (LOG4CPLUS_HAVE_CXX11_ATOMICS)
00085             typedef std::atomic<unsigned> count_type;
00086 #elif defined (_WIN32) || defined (__CYGWIN__)
00087             typedef long count_type;
00088 #else
00089             typedef unsigned count_type;
00090 #endif
00091             mutable count_type count;
00092         };
00093 
00094 
00095         /******************************************************************************
00096          *           Template Class SharedObjectPtr (from pp. 203, 206)               *
00097          ******************************************************************************/
00098         template<class T>
00099         class SharedObjectPtr
00100         {
00101         public:
00102             // Ctor
00103             explicit
00104             SharedObjectPtr(T* realPtr = 0)
00105                 : pointee(realPtr)
00106             {
00107                 addref ();
00108             }
00109 
00110             SharedObjectPtr(const SharedObjectPtr& rhs)
00111                 : pointee(rhs.pointee)
00112             {
00113                 addref ();
00114             }
00115 
00116 #if defined (LOG4CPLUS_HAVE_RVALUE_REFS)
00117             SharedObjectPtr(SharedObjectPtr && rhs)
00118                 : pointee (std::move (rhs.pointee))
00119             {
00120                 rhs.pointee = 0;
00121             }
00122 
00123             SharedObjectPtr & operator = (SharedObjectPtr && rhs)
00124             {
00125                 rhs.swap (*this);
00126                 return *this;
00127             }
00128 #endif
00129 
00130             // Dtor
00131             ~SharedObjectPtr()
00132             {
00133                 if (pointee)
00134                     pointee->removeReference();
00135             }
00136 
00137             // Operators
00138             bool operator==(const SharedObjectPtr& rhs) const { return (pointee == rhs.pointee); }
00139             bool operator!=(const SharedObjectPtr& rhs) const { return (pointee != rhs.pointee); }
00140             bool operator==(const T* rhs) const { return (pointee == rhs); }
00141             bool operator!=(const T* rhs) const { return (pointee != rhs); }
00142             T* operator->() const {assert (pointee); return pointee; }
00143             T& operator*() const {assert (pointee); return *pointee; }
00144 
00145             SharedObjectPtr& operator=(const SharedObjectPtr& rhs)
00146             {
00147                 return this->operator = (rhs.pointee);
00148             }
00149 
00150             SharedObjectPtr& operator=(T* rhs)
00151             {
00152                 SharedObjectPtr<T> (rhs).swap (*this);
00153                 return *this;
00154             }
00155 
00156           // Methods
00157             T* get() const { return pointee; }
00158 
00159             void swap (SharedObjectPtr & other) throw ()
00160             {
00161                 std::swap (pointee, other.pointee);
00162             }
00163 
00164             typedef T * (SharedObjectPtr:: * unspec_bool_type) () const;
00165             operator unspec_bool_type () const
00166             {
00167                 return pointee ? &SharedObjectPtr::get : 0;
00168             }
00169 
00170             bool operator ! () const
00171             {
00172                 return ! pointee;
00173             }
00174 
00175         private:
00176           // Methods
00177             void addref() const
00178             {
00179                 if (pointee)
00180                     pointee->addReference();
00181             }
00182 
00183           // Data
00184             T* pointee;
00185         };
00186 
00187     } // end namespace helpers
00188 } // end namespace log4cplus
00189 
00190 
00191 #endif // LOG4CPLUS_HELPERS_POINTERS_HEADER_