A generic opaque Handle type built on top of shared_ptr, for managing lifecycle
This commit is contained in:
parent
aa7fe2591c
commit
8419534f49
1 changed files with 136 additions and 0 deletions
136
src/lib/handle.hpp
Normal file
136
src/lib/handle.hpp
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
HANDLE.hpp - opaque handle to an implementation entity, automatically managing lifecycle
|
||||||
|
|
||||||
|
Copyright (C) Lumiera.org
|
||||||
|
2009, Hermann Vosseler <Ichthyostega@web.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file handle.hpp
|
||||||
|
** A generic opaque handle to an implementation entity, including lifecycle management.
|
||||||
|
** The intended use is for some public interface to return such a handle to track the
|
||||||
|
** lifecycle or registration of a dedicated service created for this call. The handle
|
||||||
|
** is implemented as refcounting smart-ptr on top of shared_ptr, which especially
|
||||||
|
** means for the client code that the handle has value semantics, can be copied and
|
||||||
|
** stored, while the referred service will stay alive as long as there is still an
|
||||||
|
** handle in use. A handle may be empty ("null handle") or closed; the latter
|
||||||
|
** also decreases the ref count and can be used to close a service explicitly.
|
||||||
|
**
|
||||||
|
** Possibly a service may use an extension of the handle template carrying dedicated
|
||||||
|
** API functions. In this case, the handle acts like a PImpl; the actual definition
|
||||||
|
** of the implementation class the handle points at is necessary only in the
|
||||||
|
** translation unit implementing such an extended handle.
|
||||||
|
**
|
||||||
|
** @see proc::DummyPlayer::Process usage example
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LIB_HANDLE_H
|
||||||
|
#define LIB_HANDLE_H
|
||||||
|
|
||||||
|
#include "lib/nobug-init.hpp"
|
||||||
|
#include "lib/sync.hpp"
|
||||||
|
|
||||||
|
#include <tr1/memory>
|
||||||
|
|
||||||
|
|
||||||
|
namespace lib {
|
||||||
|
|
||||||
|
using std::tr1::shared_ptr;
|
||||||
|
using std::tr1::weak_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic opaque reference counting handle, for accessing a service
|
||||||
|
* and managing its lifecycle. Usually such a handle is created by
|
||||||
|
* an service interface and \link #activate activated \endlink by
|
||||||
|
* setting up the link to some internal implementation object.
|
||||||
|
* This setup can only be done by a friend or derived class,
|
||||||
|
* while client code is free to copy and store handle objects.
|
||||||
|
* Finally, any handle can be closed, thereby decrementing
|
||||||
|
* the use count.
|
||||||
|
*/
|
||||||
|
template<class IMP>
|
||||||
|
class Handle
|
||||||
|
: protected std::tr1::shared_ptr<IMP>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::tr1::shared_ptr<IMP> SmP;
|
||||||
|
|
||||||
|
/** by default create an Null handle.
|
||||||
|
* Typically this is followed by activating
|
||||||
|
* the handle by the managing service.
|
||||||
|
*/
|
||||||
|
Handle ( )
|
||||||
|
: SmP()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Handle (Handle const& r) : SmP(r) {}
|
||||||
|
template<class Y> Handle (shared_ptr<Y> const& r) : SmP(r) {}
|
||||||
|
template<class Y> explicit Handle (weak_ptr<Y> const& wr) : SmP(wr) {}
|
||||||
|
template<class Y> explicit Handle (std::auto_ptr<Y> & ar) : SmP(ar) {}
|
||||||
|
|
||||||
|
Handle& operator= (Handle const& r) { SmP::operator= (r); return *this; }
|
||||||
|
template<class Y> Handle& operator=(shared_ptr<Y> const& sr) { SmP::operator= (sr); return *this; }
|
||||||
|
template<class Y> Handle& operator=(std::auto_ptr<Y> & ar) { SmP::operator= (ar); return *this; }
|
||||||
|
|
||||||
|
|
||||||
|
/** deactivate this handle, so it isn't tied any longer
|
||||||
|
* to the associated implementation or service object.
|
||||||
|
* When all handles have either been deactivated or
|
||||||
|
* went out of scope, the associated implementation
|
||||||
|
* reaches end-of-life.
|
||||||
|
*/
|
||||||
|
void close () { SmP::reset(); }
|
||||||
|
|
||||||
|
|
||||||
|
typedef IMP* SmP::*__unspecified_bool_type;
|
||||||
|
|
||||||
|
/** implicit conversion to "bool" */
|
||||||
|
operator __unspecified_bool_type() const { return *this; } // never throws
|
||||||
|
bool operator! () const { return !SmP::get(); } // dito
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Activation of the handle by the managing service.
|
||||||
|
* @param impl the implementation object this handle is tied to
|
||||||
|
* @param whenDead functor to be invoked when reaching end-of-life
|
||||||
|
*/
|
||||||
|
template<typename DEL>
|
||||||
|
Handle&
|
||||||
|
activate (IMP* impl, DEL whenDead)
|
||||||
|
{
|
||||||
|
SmP::reset (impl, whenDead);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMP&
|
||||||
|
impl()
|
||||||
|
{
|
||||||
|
REQUIRE (SmP::get(), "Lifecycle-Error");
|
||||||
|
return *(SmP::get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace lib
|
||||||
|
#endif
|
||||||
Loading…
Reference in a new issue