/* HANDLE.hpp - opaque handle to an implementation entity, automatically managing lifecycle Copyright (C) Lumiera.org 2009, Hermann Vosseler 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 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 Handle { protected: std::tr1::shared_ptr smPtr_; public: /** by default create an Null handle. * Typically this is followed by activating * the handle by the managing service. */ Handle ( ) : smPtr_() { } Handle (Handle const& r) : smPtr_(r.smPtr_) { } template Handle (shared_ptr const& r) : smPtr_(r) { } template explicit Handle (weak_ptr const& wr) : smPtr_(wr) { } template explicit Handle (std::auto_ptr & ar) : smPtr_(ar) { } Handle& operator=(Handle const& r) { smPtr_ = r.smPtr_; return *this; } template Handle& operator=(shared_ptr const& sr) { smPtr_ = sr; return *this; } template Handle& operator=(std::auto_ptr & ar) { smPtr_ = ar; return *this; } /** 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 Handle& activate (IMP* impl, DEL whenDead) { smPtr_.reset (impl, whenDead); 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 () { smPtr_.reset(); } typedef std::tr1::shared_ptr Handle::*__unspecified_bool_type; /** implicit conversion to "bool" */ operator __unspecified_bool_type() const { return &Handle::smPtr_; } // never throws bool operator! () const { return !bool(smPtr_); } // dito protected: IMP& impl() { REQUIRE (smPtr_.get(), "Lifecycle-Error"); return *(smPtr_.get()); } }; } // namespace lib #endif