218 lines
6.2 KiB
C++
218 lines
6.2 KiB
C++
#pragma once
|
|
|
|
#ifndef TCG_CONTROLLED_ACCESS_H
|
|
#define TCG_CONTROLLED_ACCESS_H
|
|
|
|
// tcg includes
|
|
#include "base.h"
|
|
|
|
/*!
|
|
\file controlled_access.h
|
|
|
|
\brief This file contains the description of a C++ idiom that can be used
|
|
to perform controlled access on an object.
|
|
|
|
\details Controlled access forces users to invoke a function every time an
|
|
object is accessed, at compile-time.
|
|
|
|
Some notable cases for this idiom include the "frequent notifier /
|
|
lazy update"
|
|
scenario, where an object is frequently notified for status updates,
|
|
but
|
|
many updates can be spared until the data is finally accessed.
|
|
*/
|
|
|
|
namespace tcg {
|
|
|
|
enum DirectAccess { direct_access }; //!< Enum used to access variables with
|
|
//! controlled output directly.
|
|
|
|
//*************************************************************************
|
|
// tcg::controlled_access definition
|
|
//*************************************************************************
|
|
|
|
/*!
|
|
\brief The controlled_access template class encapsulate an object that
|
|
can be accessed \b only after a functor has been invoked, enforcing
|
|
access tracking at compile time.
|
|
|
|
\details The accessor functor can be specified by explicit template argument
|
|
or supplying it during access. In case the accessor type is
|
|
specified,
|
|
an instance of the functor will be stored together with the accessed
|
|
variable.
|
|
|
|
\todo Move functor to base class to enable empty class optimization for
|
|
stateless functors.
|
|
*/
|
|
|
|
template <typename Obj, typename Func = tcg::empty_type>
|
|
class controlled_access : tcg::noncopyable<> {
|
|
Obj m_obj; //!< Stored object.
|
|
Func m_func; //!< Functor to be invoked upon access.
|
|
|
|
public:
|
|
typedef Obj obj_type;
|
|
typedef Func func_type;
|
|
|
|
public:
|
|
controlled_access(const func_type &func) : m_obj(), m_func(func) {}
|
|
controlled_access(const obj_type &obj, const func_type &func)
|
|
: m_obj(obj), m_func(func) {}
|
|
|
|
const obj_type &operator()(DirectAccess) const { return m_obj; }
|
|
obj_type &operator()(DirectAccess) { return m_obj; }
|
|
|
|
const obj_type &operator()() const {
|
|
m_func(m_obj);
|
|
return m_obj;
|
|
}
|
|
obj_type &operator()() {
|
|
m_func(m_obj);
|
|
return m_obj;
|
|
}
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*!
|
|
\brief Explicit specialization advocating no explicit accessor functor -
|
|
the
|
|
accessor must be supplied upon access.
|
|
*/
|
|
|
|
template <typename Obj>
|
|
class controlled_access<Obj, tcg::empty_type> : tcg::noncopyable<> {
|
|
Obj m_obj; //!< Stored object.
|
|
|
|
public:
|
|
typedef Obj obj_type;
|
|
|
|
public:
|
|
controlled_access() : m_obj() {}
|
|
controlled_access(const obj_type &obj) : m_obj(obj) {}
|
|
|
|
const obj_type &operator()(DirectAccess) const { return m_obj; }
|
|
obj_type &operator()(DirectAccess) { return m_obj; }
|
|
|
|
template <typename Func>
|
|
const obj_type &operator()(Func func) const {
|
|
func(m_obj);
|
|
return m_obj;
|
|
}
|
|
|
|
template <typename Func>
|
|
obj_type &operator()(Func func) {
|
|
func(m_obj);
|
|
return m_obj;
|
|
}
|
|
};
|
|
|
|
//==============================================================================
|
|
|
|
/*!
|
|
\brief The invalidable template class is a common case of controlled
|
|
variable
|
|
access for objects which can be \a invalidated, and thus require a
|
|
validator
|
|
procedure to be invoked strictly before a user access to the object
|
|
can be
|
|
allowed.
|
|
|
|
\details An invalidable instance wraps a \a mutable object and adds a boolean
|
|
to
|
|
signal its current validity state.
|
|
|
|
The initial validity of the object can be specified at construction,
|
|
and
|
|
explicitly set to the invalid state through the invalidate() method.
|
|
|
|
Access to the wrapped object requires either the invocation a
|
|
validator
|
|
functor through the various operator() overloads, or that the access
|
|
is
|
|
explicitly marked as \a direct by supplying the \p
|
|
tcg::direct_access tag.
|
|
*/
|
|
|
|
template <typename Obj, typename Func = tcg::empty_type>
|
|
class invalidable : tcg::noncopyable<> {
|
|
mutable Obj m_obj; //!< Stored object.
|
|
mutable bool m_invalid; //!< Data validity status.
|
|
|
|
Func m_func; //!< Functor to be invoked upon access.
|
|
|
|
public:
|
|
typedef Obj obj_type;
|
|
typedef Func func_type;
|
|
|
|
public:
|
|
invalidable(const func_type &func, bool invalid = false)
|
|
: m_obj(), m_func(func), m_invalid(invalid) {}
|
|
invalidable(const obj_type &obj, const func_type &func, bool invalid = false)
|
|
: m_obj(obj), m_func(func), m_invalid(invalid) {}
|
|
|
|
void invalidate() { m_invalid = true; }
|
|
bool isInvalid() const { return m_invalid; }
|
|
|
|
const obj_type &operator()(DirectAccess) const { return m_obj; }
|
|
obj_type &operator()(DirectAccess) { return m_obj; }
|
|
|
|
const obj_type &operator()() const {
|
|
if (m_invalid) m_func(m_obj), m_invalid = false;
|
|
|
|
return m_obj;
|
|
}
|
|
|
|
obj_type &operator()() {
|
|
if (m_invalid) m_func(m_obj), m_invalid = false;
|
|
|
|
return m_obj;
|
|
}
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*!
|
|
\brief Explicit specialization advocating no explicit validator functor -
|
|
the
|
|
accessor must be supplied upon access.
|
|
*/
|
|
|
|
template <typename Obj>
|
|
class invalidable<Obj, tcg::empty_type> : tcg::noncopyable<> {
|
|
mutable Obj m_obj; //!< Stored object
|
|
mutable bool m_invalid; //!< Data validity status
|
|
|
|
public:
|
|
typedef Obj obj_type;
|
|
|
|
public:
|
|
invalidable(bool invalid = false) : m_obj(), m_invalid(invalid) {}
|
|
invalidable(const obj_type &obj, bool invalid = false)
|
|
: m_obj(obj), m_invalid(invalid) {}
|
|
|
|
void invalidate() { m_invalid = true; }
|
|
bool isInvalid() const { return m_invalid; }
|
|
|
|
const obj_type &operator()(DirectAccess) const { return m_obj; }
|
|
obj_type &operator()(DirectAccess) { return m_obj; }
|
|
|
|
template <typename Func>
|
|
const obj_type &operator()(Func func) const {
|
|
if (m_invalid) func(m_obj), m_invalid = false;
|
|
|
|
return m_obj;
|
|
}
|
|
|
|
template <typename Func>
|
|
obj_type &operator()(Func func) {
|
|
if (m_invalid) func(m_obj), m_invalid = false;
|
|
|
|
return m_obj;
|
|
}
|
|
};
|
|
|
|
} // namespace tcg
|
|
|
|
#endif // TCG_CONTROLLED_ACCESS_H
|