Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save anonymous/3155906 to your computer and use it in GitHub Desktop.
Save anonymous/3155906 to your computer and use it in GitHub Desktop.
#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
#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