Integration with InstanceHandle
This commit is contained in:
parent
635b9441f4
commit
4ffa60161b
3 changed files with 86 additions and 32 deletions
|
|
@ -31,7 +31,9 @@
|
|||
**
|
||||
** @see gui::GuiFacade usage example
|
||||
** @see interface.h
|
||||
** @see interfaceproxy.cpp
|
||||
** @see interfaceproxy.hpp (more explanations)
|
||||
** @see interfaceproxy.cpp (Implementation of the proxies)
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -41,6 +43,7 @@
|
|||
|
||||
#include "include/nobugcfg.h"
|
||||
#include "lib/error.hpp"
|
||||
#include "include/interfaceproxy.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "common/interface.h"
|
||||
|
|
@ -48,7 +51,6 @@ extern "C" {
|
|||
}
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
//#include <boost/scoped_ptr.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
|
@ -57,6 +59,10 @@ namespace lumiera {
|
|||
|
||||
using std::string;
|
||||
|
||||
template<class I, class FA>
|
||||
class InstanceHandle;
|
||||
|
||||
|
||||
namespace { // implementation details
|
||||
|
||||
void
|
||||
|
|
@ -96,16 +102,69 @@ namespace lumiera {
|
|||
ifa->name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal Helper/Adapter for establishing a link
|
||||
* between an InstanceHandle and a facade interface,
|
||||
* which is going to be implemented through the given
|
||||
* interface/plugin. This way, creating the InstanceHandle
|
||||
* automatically creates a lumiera::facade::Proxy, to route
|
||||
* any facade calls through the interface/plugin. Similarly,
|
||||
* when destroying the InstanceHandle, the proxy will be closed.
|
||||
*/
|
||||
template<class I, class FA>
|
||||
struct FacadeLink
|
||||
: boost::noncopyable
|
||||
{
|
||||
typedef InstanceHandle<I,FA> IH;
|
||||
|
||||
FacadeLink (IH const& iha) { facade::openProxy(iha); }
|
||||
~FacadeLink() { facade::closeProxy<IH>(); }
|
||||
|
||||
FA&
|
||||
operator() (IH const&) const
|
||||
{
|
||||
return facade::Accessor<FA>()();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @internal when the InstanceHandle isn't associated with a
|
||||
* facade interface, then this specialisation switches
|
||||
* the FacadeLink into "NOP" mode.
|
||||
*/
|
||||
template<class I>
|
||||
struct FacadeLink<I,I>
|
||||
: boost::noncopyable
|
||||
{
|
||||
typedef InstanceHandle<I,I> IH;
|
||||
|
||||
FacadeLink (IH const&) { /* NOP */ }
|
||||
~FacadeLink() { /* NOP */ }
|
||||
|
||||
I&
|
||||
operator() (IH const& handle) const
|
||||
{
|
||||
return handle.get();
|
||||
}
|
||||
};
|
||||
|
||||
} // (End) impl details
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Handle tracking the registration of an interface, deregistering it on deletion.
|
||||
* Depending on which flavour of the ctor is used, either (bulk) registration of interfaces
|
||||
* or plugin loading is triggered. The interface type is defined by type parameter.
|
||||
* @todo when provided with the type of an facade interface class, care for enabling/disabling
|
||||
* access through the facade proxy singleton when opening/closing the registration.
|
||||
* Additionally, choosing a facade interface as second type parameter causes installation
|
||||
* of a proxy, which implements the facade by routing calls through the basic interface
|
||||
* represented by this handle. This proxy will be "closed" automatically when this
|
||||
* InstanceHandle goes out of scope. Of course, the proxy needs to be implemented
|
||||
* somewhere, typically in interfaceproxy.cpp
|
||||
*/
|
||||
template< class I ///< fully mangled name of the interface type
|
||||
, class FA = I ///< facade interface type to be used by clients
|
||||
|
|
@ -115,6 +174,7 @@ namespace lumiera {
|
|||
{
|
||||
LumieraInterface* desc_;
|
||||
I* instance_;
|
||||
FacadeLink<I,FA> facadeLink_;
|
||||
|
||||
typedef InstanceHandle<I,FA> _ThisType;
|
||||
|
||||
|
|
@ -127,9 +187,10 @@ namespace lumiera {
|
|||
* @param impName unmangled name of the instance (implementation)
|
||||
*/
|
||||
InstanceHandle (string const& iName, uint version, size_t minminor, string const& impName)
|
||||
: desc_(0),
|
||||
instance_(reinterpret_cast<I*>
|
||||
: desc_(0)
|
||||
, instance_(reinterpret_cast<I*>
|
||||
(lumiera_interface_open (iName.c_str(), version, minminor, impName.c_str())))
|
||||
, facadeLink_(*this)
|
||||
{
|
||||
throwIfError();
|
||||
}
|
||||
|
|
@ -141,8 +202,9 @@ namespace lumiera {
|
|||
* usually available through lumiera_plugin_interfaces()
|
||||
*/
|
||||
InstanceHandle (LumieraInterface* descriptors)
|
||||
: desc_(descriptors),
|
||||
instance_(reinterpret_cast<I*> (register_and_open (desc_)))
|
||||
: desc_(descriptors)
|
||||
, instance_(reinterpret_cast<I*> (register_and_open (desc_)))
|
||||
, facadeLink_(*this)
|
||||
{
|
||||
throwIfError();
|
||||
}
|
||||
|
|
@ -157,9 +219,8 @@ namespace lumiera {
|
|||
|
||||
|
||||
/** act as smart pointer providing access through the facade.
|
||||
* @todo implement the case where the Facade differs from I
|
||||
* @note we don't provide operator* */
|
||||
FA * operator-> () const { return accessFacade(); }
|
||||
FA * operator-> () const { return &(facadeLink_(*this)); }
|
||||
|
||||
/** directly access the instance via the CL interface */
|
||||
I& get () const { ENSURE(instance_); return *instance_; }
|
||||
|
|
@ -176,13 +237,6 @@ namespace lumiera {
|
|||
|
||||
|
||||
private:
|
||||
FA *
|
||||
accessFacade() const
|
||||
{
|
||||
ENSURE (instance_);
|
||||
return static_cast<FA *> (instance_); /////////////////TODO: actually handle the case when the facade differs from the interface by using the proxy
|
||||
}
|
||||
|
||||
bool
|
||||
isValid() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,12 +61,12 @@ namespace lumiera {
|
|||
|
||||
I& _i_;
|
||||
|
||||
Holder (IHandle& iha)
|
||||
Holder (IHandle const& iha)
|
||||
: _i_(iha.get())
|
||||
{ }
|
||||
|
||||
public:
|
||||
static Proxy& open(IHandle& iha)
|
||||
static Proxy& open(IHandle const& iha)
|
||||
{
|
||||
static char buff[sizeof(Proxy)];
|
||||
Proxy* p = new(buff) Proxy(iha);
|
||||
|
|
@ -90,14 +90,14 @@ namespace lumiera {
|
|||
|
||||
template<class IHA>
|
||||
void
|
||||
openProxy (IHA& iha)
|
||||
openProxy (IHA const& iha)
|
||||
{
|
||||
Proxy<IHA>::open(iha);
|
||||
}
|
||||
|
||||
template<class IHA>
|
||||
void
|
||||
closeProxy (IHA&)
|
||||
closeProxy ()
|
||||
{
|
||||
Proxy<IHA>::close();
|
||||
}
|
||||
|
|
@ -120,14 +120,14 @@ namespace lumiera {
|
|||
|
||||
|
||||
public:
|
||||
Proxy (IHandle& iha) : THolder(iha) {}
|
||||
Proxy (IHandle const& iha) : THolder(iha) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template void openProxy<Handle_GuiNotification> (Handle_GuiNotification&);
|
||||
template void closeProxy<Handle_GuiNotification> (Handle_GuiNotification&);
|
||||
template void openProxy<Handle_GuiNotification> (Handle_GuiNotification const&);
|
||||
template void closeProxy<Handle_GuiNotification> (void);
|
||||
|
||||
|
||||
} // namespace facade
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@
|
|||
** with the help of the Interface/Plugin system. But in order to be able to actually
|
||||
** access a service via this Facade, you need an instance of the interface.
|
||||
**
|
||||
** InterfaceProxy and InstanceHandle together are used to create such an concrete
|
||||
** lumiera::facade::Proxy and InstanceHandle together are used to create such an concrete
|
||||
** instance of the Facade interface. It is implemented such as to route each call
|
||||
** through the corresponding C Language function defined in the Interface/Plugin system.
|
||||
** Typically there is another subclass of the Facade interfaces sitting "on the other side"
|
||||
** of the interface barrier and actually implementing the functionality. The template
|
||||
** InterfaceProxy can be thought of as a factory creating such a proxy instance of the
|
||||
** facade::Accessor can be thought of as a factory creating such a proxy instance of the
|
||||
** facade interface for the client code to use. Typically, in instance of the \em factory
|
||||
** is embedded (as a static functor member object) right within the otherwise abstract
|
||||
** facade interface, this way allowing the client code to write e.g. \c XYZInterface::facade()
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
** isn't accessible all the time, rather it comes up at a defined point in the application
|
||||
** lifecycle and similarly will be shut down deliberately at some point. Beyond this time
|
||||
** window of availability, any access through the proxy factory throws an lumiera::error::State.
|
||||
** Any sort of dependency management is outside the scope of the InterfaceProxy (for the core
|
||||
** Any sort of dependency management is outside the scope of the InstanceHandle (for the core
|
||||
** services, it is handled by the dependency of subsystems, while the plugin loader cares
|
||||
** for dependency issues regarding loadable modules, thereby building on the deployment
|
||||
** descriptors.
|
||||
|
|
@ -53,11 +53,11 @@
|
|||
** For the Layer separation interfaces, the process of loading and opening is abstracted as
|
||||
** an InstanceHandle object. When creating such an InstanceHandle using the appropriate
|
||||
** template and ctor parameters, in addition to the registration with the Interface/Plugin
|
||||
** system, the corresponding InterfaceProxy factory is addressed and "opened" by creating
|
||||
** system, the corresponding facade::Proxy factory is addressed and "opened" by creating
|
||||
** the right proxy object instance. Similarly, when the InstanceHandle object goes out
|
||||
** of scope, prior to detaching from the Interface/Proxy system, the corresponding
|
||||
** InterfaceProxy factory is "closed", which means destroying the proxy object instance
|
||||
** and switching any further access to throwing and exception.
|
||||
** lumiera::facade::Accessor factory is "closed", which additionally means destroying
|
||||
** the proxy object instance and switching any further access to throwing and exception.
|
||||
**
|
||||
** While client code just includes the interface header (including interfaceproxy.hpp
|
||||
** in turn), there needs to be an actual implementation of each proxy object located in
|
||||
|
|
@ -107,10 +107,10 @@ namespace lumiera {
|
|||
};
|
||||
|
||||
template<class IHA>
|
||||
void openProxy (IHA& iha);
|
||||
void openProxy (IHA const&);
|
||||
|
||||
template<class IHA>
|
||||
void closeProxy (IHA& iha);
|
||||
void closeProxy ();
|
||||
|
||||
template<class IHA>
|
||||
class Proxy;
|
||||
|
|
|
|||
Loading…
Reference in a new issue