141 lines
5.6 KiB
C++
141 lines
5.6 KiB
C++
/*
|
|
SESSION-SERVICES.hpp - accessing Proc-Layer internal session implementation services
|
|
|
|
Copyright (C) Lumiera.org
|
|
2008, 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 session-services.hpp
|
|
** A mechanism for exposing and accessing implementation level
|
|
** services of the session. While any client code should always
|
|
** use the public Session API, some implementation level facilities
|
|
** within Proc-Layer need to cooperate with a wider SessionImpl API.
|
|
** On the other hand, we don't want to create coupling between the
|
|
** mentioned Proc internals and the session implementation. Another
|
|
** concern addressed by this mechanism is to assure consistency
|
|
** across all those implementation APIs. New APIs can be added
|
|
** just by extending a template definition and will automatically
|
|
** participate in the session management mechanisms, because any
|
|
** access is routed through the top level Session PImpl.
|
|
**
|
|
** \par structure of session implementation-level services
|
|
**
|
|
** Assumed any part of the Proc implementation needs to cooperate
|
|
** with the session implementation; the necessary link has to be
|
|
** abstracted into an implementation level API. Typically, this
|
|
** API provides an static access function, which is to be implemented
|
|
** "somewhere else", so the Proc implementation isn't required to
|
|
** include anything of the session implementation level
|
|
**
|
|
** In order to actually provide such a service, an specialisation of
|
|
** the ServiceAccessPoint template has to be defined, which may mix in
|
|
** the service API and implement it directly on top of SessionImpl.
|
|
** Note, mixing in the API isn't required -- alternatively the API might
|
|
** be completely bridged through the mentioned static access functions
|
|
** (i.e. such would be kind of an generic API, relying on convention
|
|
** rather than on a vtable)
|
|
**
|
|
** When the SessManagerImpl creates the concrete session object,
|
|
** it doesn't use the bare SessionImpl class; rather, an inheritance
|
|
** chain is formed, starting with SessionImpl and stacking any of the
|
|
** configured ServiceAccessPoint instantiations on top of it. Thus,
|
|
** the public session access gets the concrete implementation of the
|
|
** Session API (through the vtable), while any service level access
|
|
** can use the corresponding service API directly. Service APIs have
|
|
** to care to avoid name clashes though.
|
|
**
|
|
** The implementation of all the service API access functions is
|
|
** bundled within session-service.cpp -- where the full compound
|
|
** of SessionImpl and the ServiceAccessPoint specialisations has
|
|
** to be visible.
|
|
**
|
|
** @see session-service-access-test.cpp simplified inline demo definition of this setup
|
|
** @see session.hpp public session API
|
|
** @see session-impl.hpp definition of ServiceAccessPoint specialisations
|
|
** @see session-impl.cpp session implementation internals
|
|
**
|
|
*/
|
|
|
|
|
|
#ifndef MOBJECT_SESSION_SESSION_SERVICES_H
|
|
#define MOBJECT_SESSION_SESSION_SERVICES_H
|
|
|
|
#include "proc/mobject/session.hpp"
|
|
#include "lib/meta/generator.hpp"
|
|
|
|
|
|
|
|
|
|
namespace proc {
|
|
namespace mobject {
|
|
namespace session {
|
|
|
|
using lib::meta::InstantiateChained;
|
|
using lib::meta::Types;
|
|
|
|
|
|
/**
|
|
* Access point to a single implementation-level API.
|
|
* For each concrete service to provide, an specialisation
|
|
* of this template is assumed to exist which inherits from
|
|
* IMPL; it will be used in an inheritance-chain on top of
|
|
* SessionImpl and thus can access the latter (= session
|
|
* implementation API) just through its parent class IMPL
|
|
*/
|
|
template<class API, class IMPL>
|
|
struct ServiceAccessPoint;
|
|
|
|
|
|
/**
|
|
* Collection of configured implementation-level services
|
|
* to provide by the Session. An instance of this template
|
|
* is created on top of SessionImpl, configured such as
|
|
* to inherit from all the concrete services to be
|
|
* exposed for use by Proc-Lyer's internals.
|
|
*
|
|
* @param APIS sequence of API types to implement
|
|
* @param FRONT type of the frontend used for access
|
|
* @param SESS the basic session implementation
|
|
*/
|
|
template< typename APIS
|
|
, class FRONT
|
|
, class SESS
|
|
>
|
|
class SessionServices
|
|
: public InstantiateChained< typename APIS::List // for each of the API types...
|
|
, ServiceAccessPoint // instantiate a service implementation
|
|
, SESS // and stack all these on top of SessionImpl
|
|
>
|
|
{
|
|
public:
|
|
static FRONT& current; ///< intended to be hard-wired to SessManagerImpl singleton
|
|
|
|
/** access an service by explicit downcast.
|
|
* @warning this function is dangerous; never store the
|
|
* returned reference, as the referred object
|
|
* might go away due to session close/reset/load
|
|
*/
|
|
template<class API>
|
|
API& get() { return *this; }
|
|
};
|
|
|
|
|
|
|
|
}}} // namespace proc::mobject::session
|
|
#endif
|