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