• Classes
  • Modules
  • Namespaces
  • Files
  • Related Pages
  • File List
  • File Members

acsComponentSmartPtr.h

Go to the documentation of this file.
00001 #ifndef ACSSMARTPOINTER_H
00002 #define ACSSMARTPOINTER_H
00003 /*******************************************************************************
00004 * ALMA - Atacama Large Millimiter Array
00005 * (c) National Research Council of Canada, 2007
00006 *
00007 * This library is free software; you can redistribute it and/or
00008 * modify it under the terms of the GNU Lesser General Public
00009 * License as published by the Free Software Foundation; either
00010 * version 2.1 of the License, or (at your option) any later version.
00011 *
00012 * This library is distributed in the hope that it will be useful,
00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 * Lesser General Public License for more details.
00016 *
00017 * You should have received a copy of the GNU Lesser General Public
00018 * License along with this library; if not, write to the Free Software
00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 *
00021 * "@(#) $Id: acsComponentSmartPtr.h,v 1.13 2009/11/04 20:44:29 agrimstrup Exp $"
00022 *
00023 * who       when      what
00024 * --------  --------  ----------------------------------------------
00025 * arne  2007-10-09  created
00026 */
00027 
00028 /************************************************************************
00029  *
00030  *----------------------------------------------------------------------
00031  */
00032 
00033 /* The following piece of code alternates the linkage type to C for all
00034 functions declared within the braces, which is necessary to use the
00035 functions in C++-code.
00036 */
00037 
00038 #ifndef __cplusplus
00039 #error This is a C++ include file and cannot be used from plain C
00040 #endif
00041 
00042 #include <logging.h>
00043 #include <lokiThreads.h>
00044 #include <lokiSmartPtr.h>
00045 #include <maciErrType.h>
00046 #include <ACSErrTypeCommon.h>
00047 
00048 namespace maci {
00049 
00056 template <class T, class H>
00057 class ComponentStorage
00058 {
00059   public:
00060     typedef T* StoredType;    // the type of the pointee_ object
00061     typedef T* PointerType;   // type returned by operator->
00062     typedef T& ReferenceType; // type returned by operator*
00063 
00067     ComponentStorage() : handle(0), sticky(false), pointee_(Default())
00068         {}
00069 
00073     ComponentStorage(const StoredType& p) : handle(0), sticky(false), pointee_(p)
00074         {}
00075 
00076     // The storage policy doesn't initialize the stored pointer
00077     // which will be initialized by the OwnershipPolicy's Clone fn
00081     ComponentStorage(const ComponentStorage& rhs) : handle(rhs.handle), sticky(rhs.sticky), pointee_(Default())
00082         {}
00083 
00088     template <typename U, typename V>
00089     ComponentStorage(const ComponentStorage<U,V>&) : handle(0), sticky(false), pointee_(Default())
00090         {}
00091 
00101     void setValues(H *h, bool s, const StoredType& p)
00102         {
00103             handle = h;
00104             sticky = s;
00105             pointee_ = p;
00106         };
00107 
00111     PointerType operator->() const { return pointee_; }
00112 
00116     ReferenceType operator*() const { return *pointee_; }
00117 
00123     void Swap(ComponentStorage& rhs)
00124         {
00125             std::swap(pointee_, rhs.pointee_);
00126             std::swap(sticky, rhs.sticky);
00127             std::swap(handle, rhs.handle);
00128         }
00129 
00130     // Accessors
00135     friend inline PointerType GetImpl(const ComponentStorage& sp)
00136         { return sp.pointee_; }
00137 
00142     friend inline const StoredType& GetImplRef(const ComponentStorage& sp)
00143         { return sp.pointee_; }
00144 
00149     friend inline StoredType& GetImplRef(ComponentStorage& sp)
00150         { return sp.pointee_; }
00151 
00156     bool inline isValid(const ComponentStorage& sp)
00157         { return sp.isNil() || sp.handle != (H *)0; }
00158 
00163     bool inline isNil()
00164     { return CORBA::is_nil(pointee_);}
00165 
00166 
00167   protected:
00168 
00173     void Destroy()
00174         {
00175             if (handle && pointee_ && sticky)
00176                 {
00177                 try
00178                     {
00179                     handle->releaseComponent(pointee_->name());
00180                     }
00181                 catch(maciErrType::CannotReleaseComponentExImpl& ex)
00182                     {
00183                     ACS_LOG(LM_RUNTIME_CONTEXT, "maci::ComponentStorage::Destroy",
00184                         (LM_ERROR, "Unable to release component"));
00185                     }
00186                 catch(...)
00187                     {
00188                     ACS_LOG(LM_RUNTIME_CONTEXT, "maci::ComponentStorage::Destroy",
00189                          (LM_ERROR, "Unexpected exception caught when releasing component."));
00190                     }
00191                 }
00192         }
00193 
00194 
00195     // Default value to initialize the pointer
00196     static StoredType Default()
00197         { return T::_nil(); }
00198 
00199   private:
00200     // Data
00201     H *handle;
00202     bool sticky;
00203     StoredType pointee_;
00204 };
00205 
00206 
00207 class ContainerServices;
00208 
00209 
00210 /******************************************************************************
00211  * The code below was taken from the lokiSmartPtr.h file, which is covered
00212  * by the license listed below.  It has been modified to allow two parameter
00213  * StoragePolicy classes to be used.
00214  ******************************************************************************/
00216 // The Loki Library
00217 // Copyright (c) 2001 by Andrei Alexandrescu
00218 // This code accompanies the book:
00219 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
00220 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00221 // Permission to use, copy, modify, distribute and sell this software for any
00222 //     purpose is hereby granted without fee, provided that the above copyright
00223 //     notice appear in all copies and that both that copyright notice and this
00224 //     permission notice appear in supporting documentation.
00225 // The author or Addison-Wesley Longman make no representations about the
00226 //     suitability of this software for any purpose. It is provided "as is"
00227 //     without express or implied warranty.
00229 
00230 template
00231 <
00232     typename T,
00233     typename H = ContainerServices,
00234     template <class> class OwnershipPolicy = Loki::RefCountedMTAdj<Loki::ObjectLevelLockable>::RefCountedMT,
00235     class ConversionPolicy = Loki::DisallowConversion,
00236     template <class> class CheckingPolicy = Loki::NoCheck,
00237     template <class,class> class StoragePolicy = ComponentStorage,
00238     template<class> class ConstnessPolicy = Loki::LOKI_DEFAULT_CONSTNESS
00239 >
00240 class SmartPtr
00241     : public StoragePolicy<T,H>
00242     , public OwnershipPolicy<typename StoragePolicy<T,H>::PointerType>
00243     , public CheckingPolicy<typename StoragePolicy<T,H>::StoredType>
00244     , public ConversionPolicy
00245 {
00246     typedef StoragePolicy<T,H> SP;
00247     typedef OwnershipPolicy<typename StoragePolicy<T,H>::PointerType> OP;
00248     typedef CheckingPolicy<typename StoragePolicy<T,H>::StoredType> KP;
00249     typedef ConversionPolicy CP;
00250 
00251   public:
00252     typedef typename ConstnessPolicy<T>::Type* ConstPointerType;
00253     typedef typename ConstnessPolicy<T>::Type& ConstReferenceType;
00254 
00255     typedef typename SP::PointerType PointerType;
00256     typedef typename SP::StoredType StoredType;
00257     typedef typename SP::ReferenceType ReferenceType;
00258 
00259     typedef typename Loki::Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result CopyArg;
00260 
00261     private:
00262         struct NeverMatched;
00263 
00264 #ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
00265         typedef typename Loki::Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
00266         typedef typename Loki::Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
00267 #else
00268         typedef const StoredType& ImplicitArg;
00269         typedef typename Loki::Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
00270 #endif
00271 
00272     public:
00273 
00274         SmartPtr()
00275         { KP::OnDefault(GetImpl(*this)); }
00276 
00284         SmartPtr(H* h, bool s, T* p)
00285         {
00286             setValues(h, s, p);
00287         }
00288 
00289         SmartPtr(CopyArg& rhs)
00290         : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00291         { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00292 
00293         template
00294         <
00295             typename T1,
00296             typename H1,
00297             template <class> class OP1,
00298             class CP1,
00299             template <class> class KP1,
00300             template <class,class> class SP1,
00301             template <class> class CNP1
00302         >
00303         SmartPtr(const SmartPtr<T1, H1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
00304         : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00305         { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00306 
00307         template
00308         <
00309             typename T1,
00310             typename H1,
00311             template <class> class OP1,
00312             class CP1,
00313             template <class> class KP1,
00314             template <class,class> class SP1,
00315             template <class> class CNP1
00316         >
00317         SmartPtr(SmartPtr<T1, H1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
00318         : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00319         { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00320 
00321         SmartPtr(Loki::RefToValue<SmartPtr> rhs)
00322         : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00323         {}
00324 
00325         operator Loki::RefToValue<SmartPtr>()
00326         { return Loki::RefToValue<SmartPtr>(*this); }
00327 
00328         SmartPtr& operator=(CopyArg& rhs)
00329         {
00330             SmartPtr temp(rhs);
00331             if (!isValid(rhs))
00332                 throw ACSErrTypeCommon::IllegalArgumentExImpl(__FILE__, __LINE__, "SmartPtr::operator=");
00333             else 
00334               temp.Swap(*this);
00335             return *this;
00336         }
00337 
00338         template
00339         <
00340             typename T1,
00341             typename H1,
00342             template <class> class OP1,
00343             class CP1,
00344             template <class> class KP1,
00345             template <class,class> class SP1,
00346             template <class> class CNP1
00347         >
00348         SmartPtr& operator=(const SmartPtr<T1, H1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
00349         {
00350             SmartPtr temp(rhs);
00351             if (!isValid(rhs))
00352               throw ACSErrTypeCommon::IllegalArgumentExImpl(__FILE__, __LINE__, "SmartPtr::operator=");
00353             else 
00354               temp.Swap(*this);
00355             return *this;
00356         }
00357 
00358         template
00359         <
00360             typename T1,
00361             typename H1,
00362             template <class> class OP1,
00363             class CP1,
00364             template <class> class KP1,
00365             template <class,class> class SP1,
00366             template <class> class CNP1
00367         >
00368         SmartPtr& operator=(SmartPtr<T1, H1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
00369         {
00370             SmartPtr temp(rhs);
00371             if (!isValid(rhs))
00372               throw ACSErrTypeCommon::IllegalArgumentExImpl(__FILE__, __LINE__, "SmartPtr::operator=");
00373             else 
00374               temp.Swap(*this);
00375             return *this;
00376         }
00377 
00378         void Swap(SmartPtr& rhs)
00379         {
00380             OP::Swap(rhs);
00381             CP::Swap(rhs);
00382             KP::Swap(rhs);
00383             SP::Swap(rhs);
00384         }
00385 
00386         ~SmartPtr()
00387         {
00388             if (!SP::isNil() && OP::Release(GetImpl(*static_cast<SP*>(this))))
00389             {
00390                 SP::Destroy();
00391             }
00392         }
00393 
00394         void release()
00395         {
00396             OP temp;
00397             this->~SmartPtr();
00398             this->setValues((H *)0, false, SP::Default());
00399             OP::Swap(temp);
00400         }
00401 
00402         friend inline void Release(SmartPtr& sp, typename SP::StoredType& p)
00403         {
00404             p = GetImplRef(sp);
00405             GetImplRef(sp) = SP::Default();
00406         }
00407 
00408         friend inline void Reset(SmartPtr& sp, typename SP::StoredType p)
00409         { SmartPtr(p).Swap(sp); }
00410 
00411         template
00412         <
00413             typename T1,
00414             typename H1,
00415             template <class> class OP1,
00416             class CP1,
00417             template <class> class KP1,
00418             template <class,class> class SP1,
00419             template <class> class CNP1
00420         >
00421         bool Merge( SmartPtr< T1, H1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
00422         {
00423             if ( GetImpl( *this ) != GetImpl( rhs ) )
00424             {
00425                 return false;
00426             }
00427             return OP::Merge( rhs );
00428         }
00429 
00430         PointerType operator->()
00431         {
00432             KP::OnDereference(GetImplRef(*this));
00433             return SP::operator->();
00434         }
00435 
00436         ConstPointerType operator->() const
00437         {
00438             KP::OnDereference(GetImplRef(*this));
00439             return SP::operator->();
00440         }
00441 
00442         ReferenceType operator*()
00443         {
00444             KP::OnDereference(GetImplRef(*this));
00445             return SP::operator*();
00446         }
00447 
00448         ConstReferenceType operator*() const
00449         {
00450             KP::OnDereference(GetImplRef(*this));
00451             return SP::operator*();
00452         }
00453 
00454         bool operator!() const // Enables "if (!sp) ..."
00455         { return GetImpl(*this) == 0; }
00456 
00457         static inline T * GetPointer( const SmartPtr & sp )
00458         { return GetImpl( sp ); }
00459 
00460         // Ambiguity buster
00461         template
00462         <
00463             typename T1,
00464             typename H1,
00465             template <class> class OP1,
00466             class CP1,
00467             template <class> class KP1,
00468             template <class,class> class SP1,
00469             template <class> class CNP1
00470         >
00471         bool operator==(const SmartPtr<T1, H1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
00472         { return GetImpl(*this) == GetImpl(rhs); }
00473 
00474         // Ambiguity buster
00475         template
00476         <
00477             typename T1,
00478             typename H1,
00479             template <class> class OP1,
00480             class CP1,
00481             template <class> class KP1,
00482             template <class,class> class SP1,
00483             template <class> class CNP1
00484         >
00485         bool operator!=(const SmartPtr<T1, H1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
00486         { return !(*this == rhs); }
00487 
00488         // Ambiguity buster
00489         template
00490         <
00491             typename T1,
00492             typename H1,
00493             template <class> class OP1,
00494             class CP1,
00495             template <class> class KP1,
00496             template <class,class> class SP1,
00497             template <class> class CNP1
00498         >
00499         bool operator<(const SmartPtr<T1, H1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
00500         { return GetImpl(*this) < GetImpl(rhs); }
00501 
00502         // Ambiguity buster
00503         template
00504         <
00505             typename T1,
00506             typename H1,
00507             template <class> class OP1,
00508             class CP1,
00509             template <class> class KP1,
00510             template <class,class> class SP1,
00511             template <class> class CNP1
00512         >
00513         inline bool operator > ( const SmartPtr< T1, H1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
00514         {
00515             return ( GetImpl( rhs ) < GetImpl( *this ) );
00516         }
00517 
00518         // Ambiguity buster
00519         template
00520         <
00521             typename T1,
00522             typename H1,
00523             template <class> class OP1,
00524             class CP1,
00525             template <class> class KP1,
00526             template <class,class> class SP1,
00527             template <class> class CNP1
00528         >
00529         inline bool operator <= ( const SmartPtr< T1, H1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
00530         {
00531             return !( GetImpl( rhs ) < GetImpl( *this ) );
00532         }
00533 
00534         // Ambiguity buster
00535         template
00536         <
00537             typename T1,
00538             typename H1,
00539             template <class> class OP1,
00540             class CP1,
00541             template <class> class KP1,
00542             template <class,class> class SP1,
00543             template <class> class CNP1
00544         >
00545         inline bool operator >= ( const SmartPtr< T1, H1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
00546         {
00547             return !( GetImpl( *this ) < GetImpl( rhs ) );
00548         }
00549 
00550     private:
00551         // Helper for enabling 'if (sp)'
00552         struct Tester
00553         {
00554             Tester(int) {}
00555             void dummy() {}
00556         };
00557 
00558         typedef void (Tester::*unspecified_boolean_type_)();
00559 
00560         typedef typename Loki::Select<CP::allow, Tester, unspecified_boolean_type_>::Result
00561             unspecified_boolean_type;
00562 
00563     public:
00564         // enable 'if (sp)'
00565         operator unspecified_boolean_type() const
00566         {
00567             return !*this ? 0 : &Tester::dummy;
00568         }
00569 
00570     private:
00571         // Helper for disallowing automatic conversion
00572         struct Insipid
00573         {
00574             Insipid(PointerType) {}
00575         };
00576 
00577         typedef typename Loki::Select<CP::allow, PointerType, Insipid>::Result
00578             AutomaticConversionResult;
00579 
00580     public:
00581         operator AutomaticConversionResult() const
00582         { return GetImpl(*this); }
00583 };
00584 
00586 // free comparison operators for class template SmartPtr
00588 
00593 
00594     template
00595     <
00596         typename T,
00597         typename H,
00598         template <class> class OP,
00599         class CP,
00600         template <class> class KP,
00601         template <class,class> class SP,
00602         template <class> class CNP1,
00603         typename U
00604     >
00605     inline bool operator==(const SmartPtr<T, H, OP, CP, KP, SP, CNP1 >& lhs,
00606         U* rhs)
00607     { return GetImpl(lhs) == rhs; }
00608 
00613 
00614     template
00615     <
00616         typename T,
00617         typename H,
00618         template <class> class OP,
00619         class CP,
00620         template <class> class KP,
00621         template <class,class> class SP,
00622         template <class> class CNP1,
00623         typename U
00624     >
00625     inline bool operator==(U* lhs,
00626         const SmartPtr<T, H, OP, CP, KP, SP, CNP1 >& rhs)
00627     { return rhs == lhs; }
00628 
00633 
00634     template
00635     <
00636         typename T,
00637         typename H,
00638         template <class> class OP,
00639         class CP,
00640         template <class> class KP,
00641         template <class,class> class SP,
00642         template <class> class CNP,
00643         typename U
00644     >
00645     inline bool operator!=(const SmartPtr<T, H, OP, CP, KP, SP, CNP >& lhs,
00646         U* rhs)
00647     { return !(lhs == rhs); }
00648 
00653 
00654     template
00655     <
00656         typename T,
00657         typename H,
00658         template <class> class OP,
00659         class CP,
00660         template <class> class KP,
00661         template <class,class> class SP,
00662         template <class> class CNP,
00663         typename U
00664     >
00665     inline bool operator!=(U* lhs,
00666         const SmartPtr<T, H, OP, CP, KP, SP, CNP >& rhs)
00667     { return rhs != lhs; }
00668 
00673 
00674     template
00675     <
00676         typename T,
00677         typename H,
00678         template <class> class OP,
00679         class CP,
00680         template <class> class KP,
00681         template <class,class> class SP,
00682         template <class> class CNP,
00683         typename U
00684     >
00685     inline bool operator<(const SmartPtr<T, H, OP, CP, KP, SP, CNP >& lhs,
00686         U* rhs)
00687     {
00688         return ( GetImpl( lhs ) < rhs );
00689     }
00690 
00695 
00696     template
00697     <
00698         typename T,
00699         typename H,
00700         template <class> class OP,
00701         class CP,
00702         template <class> class KP,
00703         template <class,class> class SP,
00704         template <class> class CNP,
00705         typename U
00706     >
00707     inline bool operator<(U* lhs,
00708         const SmartPtr<T, H, OP, CP, KP, SP, CNP >& rhs)
00709     {
00710         return ( GetImpl( rhs ) < lhs );
00711     }
00712 
00714 //  operator> for lhs = SmartPtr, rhs = raw pointer
00717 
00718     template
00719     <
00720         typename T,
00721         typename H,
00722         template <class> class OP,
00723         class CP,
00724         template <class> class KP,
00725         template <class,class> class SP,
00726         template <class> class CNP,
00727         typename U
00728     >
00729     inline bool operator>(const SmartPtr<T, H, OP, CP, KP, SP, CNP >& lhs,
00730         U* rhs)
00731     { return rhs < lhs; }
00732 
00737 
00738     template
00739     <
00740         typename T,
00741         typename H,
00742         template <class> class OP,
00743         class CP,
00744         template <class> class KP,
00745         template <class,class> class SP,
00746         template <class> class CNP,
00747         typename U
00748     >
00749     inline bool operator>(U* lhs,
00750         const SmartPtr<T, H, OP, CP, KP, SP, CNP >& rhs)
00751     { return rhs < lhs; }
00752 
00757 
00758     template
00759     <
00760         typename T,
00761         typename H,
00762         template <class> class OP,
00763         class CP,
00764         template <class> class KP,
00765         template <class,class> class SP,
00766         template <class> class CNP,
00767         typename U
00768     >
00769     inline bool operator<=(const SmartPtr<T, H, OP, CP, KP, SP, CNP >& lhs,
00770         U* rhs)
00771     { return !(rhs < lhs); }
00772 
00777 
00778     template
00779     <
00780         typename T,
00781         typename H,
00782         template <class> class OP,
00783         class CP,
00784         template <class> class KP,
00785         template <class,class> class SP,
00786         template <class> class CNP,
00787         typename U
00788     >
00789     inline bool operator<=(U* lhs,
00790         const SmartPtr<T, H, OP, CP, KP, SP, CNP >& rhs)
00791     { return !(rhs < lhs); }
00792 
00797 
00798     template
00799     <
00800         typename T,
00801         typename H,
00802         template <class> class OP,
00803         class CP,
00804         template <class> class KP,
00805         template <class,class> class SP,
00806         template <class> class CNP,
00807         typename U
00808     >
00809     inline bool operator>=(const SmartPtr<T, H, OP, CP, KP, SP, CNP >& lhs,
00810         U* rhs)
00811     { return !(lhs < rhs); }
00812 
00817 
00818     template
00819     <
00820         typename T,
00821         typename H,
00822         template <class> class OP,
00823         class CP,
00824         template <class> class KP,
00825         template <class,class> class SP,
00826         template <class> class CNP,
00827         typename U
00828     >
00829     inline bool operator>=(U* lhs,
00830         const SmartPtr<T, H, OP, CP, KP, SP, CNP >& rhs)
00831     { return !(lhs < rhs); }
00832 
00833 };
00834 
00839 
00840 namespace std
00841 {
00842     template
00843     <
00844         typename T,
00845         typename H,
00846         template <class> class OP,
00847         class CP,
00848         template <class> class KP,
00849         template <class,class> class SP,
00850         template <class> class CNP
00851     >
00852     struct less< maci::SmartPtr<T, H, OP, CP, KP, SP, CNP > >
00853         : public binary_function<maci::SmartPtr<T, H, OP, CP, KP, SP, CNP >,
00854             maci::SmartPtr<T, H, OP, CP, KP, SP, CNP >, bool>
00855     {
00856         bool operator()(const maci::SmartPtr<T, H, OP, CP, KP, SP, CNP >& lhs,
00857             const maci::SmartPtr<T, H, OP, CP, KP, SP, CNP >& rhs) const
00858         { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); }
00859     };
00860 };
00861 
00862 #endif /* ACSSMARTPOINTER_H */

Generated on Thu Jul 8 2010 19:47:46 for ACS-9.0 C++ API by  doxygen 1.7.0