Created
          July 21, 2012 14:08 
        
      - 
      
- 
        Save anonymous/3155906 to your computer and use it in GitHub Desktop. 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | #pragma once | |
| // #include <progrock/cpp/classkinds/SelfDestroyingObject.h> | |
| // | |
| // Copyright (c) 2012 Alf P. Steinbach | |
| //----------------------------------------------- Dependencies: | |
| #include <progrock/cpp/classkinds/DynamicallyAllocatedObject.h> // cpp::DynamicallyAllocatedObject | |
| #include <progrock/cpp/c++11_emulation.h> // CPP_NOEXCEPT | |
| #include <algorithm> // std::for_each | |
| #include <functional> // std::function | |
| #include <map> // std::map | |
| #include <utility> // std::begin, std::end | |
| //----------------------------------------------- Interface: | |
| namespace progrock{ namespace cpp{ | |
| using std::begin; | |
| using std::default_delete; | |
| using std::end; | |
| using std::for_each; | |
| using std::function; | |
| using std::map; | |
| class DestructionEvent | |
| { | |
| public: | |
| class Listener | |
| { | |
| public: | |
| virtual void on( DestructionEvent const& ) CPP_NOEXCEPT = 0; | |
| }; | |
| }; | |
| class SelfDestroyingObject | |
| : public DynamicallyAllocatedObject | |
| { | |
| CPP_DECLARE_IS_DYNAMICALLY_ALLOCATED( SelfDestroyingObject ); | |
| private: | |
| typedef function< void(void) > Callback; // Is really CPP_NOEXCEPT | |
| typedef map< DestructionEvent::Listener*, Callback > Listeners; | |
| typedef Listeners::value_type Pair; | |
| bool isDestroyingSelf_; | |
| Listeners destructionListeners_; | |
| void notifyDestructionListeners() const | |
| { | |
| for_each( begin( destructionListeners_ ), end( destructionListeners_ ), [&] | |
| ( Pair const& pair ) | |
| { | |
| Callback const& fireDestructionEvent = pair.second; | |
| fireDestructionEvent(); | |
| } ); | |
| } | |
| protected: | |
| void destroySelf() | |
| { | |
| if( !isDestroyingSelf_ ) | |
| { | |
| isDestroyingSelf_ = true; | |
| notifyDestructionListeners(); | |
| default_delete<SelfDestroyingObject>()( this ); | |
| } | |
| } | |
| public: | |
| SelfDestroyingObject() | |
| : isDestroyingSelf_( false ) | |
| {} | |
| void addDestructionListener( DestructionEvent::Listener& listener ) | |
| { | |
| destructionListeners_.insert( Pair( | |
| &listener, | |
| [&]{ listener.on( DestructionEvent() ); } | |
| ) ); | |
| } | |
| void removeDestructionListener( DestructionEvent::Listener const& listener ) | |
| { | |
| destructionListeners_.erase( const_cast< DestructionEvent::Listener* >( | |
| &listener | |
| ) ); | |
| } | |
| }; | |
| } } // namespace progrock::cpp | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | #pragma once | |
| // #include <progrock/cpp/pointers/NullCheckingPtr.h> | |
| // | |
| // Formerly known as "ZPtr". | |
| // Copyright (c) 200x - 2012 Alf P. Steinbach | |
| //----------------------------------------------- Dependencies: | |
| #include <progrock/cpp/classkinds/SelfDestroyingObject.h> // cpp::DestructionEvent, cpp::SelfDestroyingObject | |
| #include <progrock/cpp/throwx.h> // cpp::hopefully, cpp::throwX | |
| #include <progrock/cpp/c++11_emulation.h> // CPP_NOEXCEPT | |
| #include <algorithm> // std::swap | |
| #include <stddef.h> // std::nullptr_t | |
| //----------------------------------------------- Interface: | |
| namespace progrock{ namespace cpp{ | |
| using std::swap; | |
| using std::nullptr_t; | |
| template< class Pointee > | |
| class NullCheckingPtr | |
| : private DestructionEvent::Listener | |
| { | |
| private: | |
| Pointee* p_; | |
| virtual void on( DestructionEvent const& ) CPP_NOEXCEPT CPP_IS_OVERRIDE | |
| { | |
| p_ = nullptr; | |
| } | |
| Pointee* goodPointer() const | |
| { | |
| hopefully( p_ != 0 ) | |
| || throwX( "cpp::NullCheckingPtr: attempted access of non-existent pointee" ); | |
| return p_; | |
| } | |
| public: | |
| bool operator!() const CPP_NOEXCEPT { return (p_ != 0); } | |
| Pointee* operator->() const { return goodPointer(); } | |
| Pointee& operator*() const { return *goodPointer(); } | |
| void swapWith( NullCheckingPtr& other ) | |
| { | |
| swap( p_, other.p_ ); | |
| } | |
| void operator=( NullCheckingPtr other ) CPP_NOEXCEPT | |
| { | |
| swapWith( other ); | |
| } | |
| ~NullCheckingPtr() | |
| { | |
| if( p_ != 0 ) | |
| { | |
| p_->removeDestructionListener( *this ); | |
| } | |
| } | |
| explicit NullCheckingPtr( Pointee* p = nullptr ) | |
| : p_( p ) | |
| { | |
| if( p_ != 0 ) | |
| { | |
| p_->addDestructionListener( *this ); | |
| } | |
| } | |
| NullCheckingPtr( NullCheckingPtr const& other ) | |
| : p_( other.p_ ) | |
| { | |
| if( p_ != 0 ) | |
| { | |
| p_->addDestructionListener( *this ); | |
| } | |
| } | |
| }; | |
| template< class Pointee > | |
| inline bool operator==( NullCheckingPtr< Pointee > const& p, std::nullptr_t ) | |
| CPP_NOEXCEPT | |
| { | |
| return !p; | |
| } | |
| template< class Pointee > | |
| inline bool operator==( std::nullptr_t, NullCheckingPtr< Pointee > const& p ) | |
| CPP_NOEXCEPT | |
| { | |
| return !p; | |
| } | |
| template< class Pointee > | |
| inline bool operator!=( NullCheckingPtr< Pointee > const& p, std::nullptr_t ) | |
| CPP_NOEXCEPT | |
| { | |
| return !!p; | |
| } | |
| template< class Pointee > | |
| inline bool operator!=( std::nullptr_t, NullCheckingPtr< Pointee > const& p ) | |
| CPP_NOEXCEPT | |
| { | |
| return !!p; | |
| } | |
| template< class Pointee > | |
| inline void swap( NullCheckingPtr< Pointee >& a, NullCheckingPtr< Pointee >& b ) | |
| CPP_NOEXCEPT | |
| { | |
| a.swapWith( b ); | |
| } | |
| } } // namespace progrock::cpp | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment