|
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 |
|
|
Shinya Kitaoka |
120a6e |
Some notable cases for this idiom include the "frequent notifier /
|
|
Shinya Kitaoka |
120a6e |
lazy update"
|
|
Shinya Kitaoka |
120a6e |
scenario, where an object is frequently notified for status updates,
|
|
Shinya Kitaoka |
120a6e |
but
|
|
Toshihiro Shimizu |
890ddd |
many updates can be spared until the data is finally accessed.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace tcg {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
enum DirectAccess { direct_access }; //!< Enum used to access variables with
|
|
Shinya Kitaoka |
120a6e |
//! 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
|
|
Shinya Kitaoka |
120a6e |
or supplying it during access. In case the accessor type is
|
|
Shinya Kitaoka |
120a6e |
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>
|
|
Shinya Kitaoka |
120a6e |
class controlled_access : tcg::noncopyable<> {
|
|
Shinya Kitaoka |
120a6e |
Obj m_obj; //!< Stored object.
|
|
Shinya Kitaoka |
120a6e |
Func m_func; //!< Functor to be invoked upon access.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef Obj obj_type;
|
|
Shinya Kitaoka |
120a6e |
typedef Func func_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
controlled_access(const func_type &func) : m_obj(), m_func(func) {}
|
|
Shinya Kitaoka |
120a6e |
controlled_access(const obj_type &obj, const func_type &func)
|
|
Shinya Kitaoka |
120a6e |
: m_obj(obj), m_func(func) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const obj_type &operator()(DirectAccess) const { return m_obj; }
|
|
Shinya Kitaoka |
120a6e |
obj_type &operator()(DirectAccess) { return m_obj; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const obj_type &operator()() const {
|
|
Shinya Kitaoka |
120a6e |
m_func(m_obj);
|
|
Shinya Kitaoka |
120a6e |
return m_obj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
obj_type &operator()() {
|
|
Shinya Kitaoka |
120a6e |
m_func(m_obj);
|
|
Shinya Kitaoka |
120a6e |
return m_obj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Shinya Kitaoka |
120a6e |
\brief Explicit specialization advocating no explicit accessor functor -
|
|
Shinya Kitaoka |
120a6e |
the
|
|
Toshihiro Shimizu |
890ddd |
accessor must be supplied upon access.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename obj=""></typename>
|
|
Shinya Kitaoka |
120a6e |
class controlled_access<obj, tcg::empty_type=""> : tcg::noncopyable<> {</obj,>
|
|
Shinya Kitaoka |
120a6e |
Obj m_obj; //!< Stored object.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef Obj obj_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
controlled_access() : m_obj() {}
|
|
Shinya Kitaoka |
120a6e |
controlled_access(const obj_type &obj) : m_obj(obj) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const obj_type &operator()(DirectAccess) const { return m_obj; }
|
|
Shinya Kitaoka |
120a6e |
obj_type &operator()(DirectAccess) { return m_obj; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
template <typename func=""></typename>
|
|
Shinya Kitaoka |
120a6e |
const obj_type &operator()(Func func) const {
|
|
Shinya Kitaoka |
120a6e |
func(m_obj);
|
|
Shinya Kitaoka |
120a6e |
return m_obj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
template <typename func=""></typename>
|
|
Shinya Kitaoka |
120a6e |
obj_type &operator()(Func func) {
|
|
Shinya Kitaoka |
120a6e |
func(m_obj);
|
|
Shinya Kitaoka |
120a6e |
return m_obj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Shinya Kitaoka |
120a6e |
\brief The invalidable template class is a common case of controlled
|
|
Shinya Kitaoka |
120a6e |
variable
|
|
Shinya Kitaoka |
120a6e |
access for objects which can be \a invalidated, and thus require a
|
|
Shinya Kitaoka |
120a6e |
validator
|
|
Shinya Kitaoka |
120a6e |
procedure to be invoked strictly before a user access to the object
|
|
Shinya Kitaoka |
120a6e |
can be
|
|
Toshihiro Shimizu |
890ddd |
allowed.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
\details An invalidable instance wraps a \a mutable object and adds a boolean
|
|
Shinya Kitaoka |
120a6e |
to
|
|
Toshihiro Shimizu |
890ddd |
signal its current validity state.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
The initial validity of the object can be specified at construction,
|
|
Shinya Kitaoka |
120a6e |
and
|
|
Toshihiro Shimizu |
890ddd |
explicitly set to the invalid state through the invalidate() method.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Access to the wrapped object requires either the invocation a
|
|
Shinya Kitaoka |
120a6e |
validator
|
|
Shinya Kitaoka |
120a6e |
functor through the various operator() overloads, or that the access
|
|
Shinya Kitaoka |
120a6e |
is
|
|
Shinya Kitaoka |
120a6e |
explicitly marked as \a direct by supplying the \p
|
|
Shinya Kitaoka |
120a6e |
tcg::direct_access tag.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename func="tcg::empty_type" obj,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
class invalidable : tcg::noncopyable<> {
|
|
Shinya Kitaoka |
120a6e |
mutable Obj m_obj; //!< Stored object.
|
|
Shinya Kitaoka |
120a6e |
mutable bool m_invalid; //!< Data validity status.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Func m_func; //!< Functor to be invoked upon access.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef Obj obj_type;
|
|
Shinya Kitaoka |
120a6e |
typedef Func func_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
invalidable(const func_type &func, bool invalid = false)
|
|
Shinya Kitaoka |
120a6e |
: m_obj(), m_func(func), m_invalid(invalid) {}
|
|
Shinya Kitaoka |
120a6e |
invalidable(const obj_type &obj, const func_type &func, bool invalid = false)
|
|
Shinya Kitaoka |
120a6e |
: m_obj(obj), m_func(func), m_invalid(invalid) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void invalidate() { m_invalid = true; }
|
|
Shinya Kitaoka |
120a6e |
bool isInvalid() const { return m_invalid; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const obj_type &operator()(DirectAccess) const { return m_obj; }
|
|
Shinya Kitaoka |
120a6e |
obj_type &operator()(DirectAccess) { return m_obj; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const obj_type &operator()() const {
|
|
Shinya Kitaoka |
120a6e |
if (m_invalid) m_func(m_obj), m_invalid = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return m_obj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
obj_type &operator()() {
|
|
Shinya Kitaoka |
120a6e |
if (m_invalid) m_func(m_obj), m_invalid = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return m_obj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Shinya Kitaoka |
120a6e |
\brief Explicit specialization advocating no explicit validator functor -
|
|
Shinya Kitaoka |
120a6e |
the
|
|
Toshihiro Shimizu |
890ddd |
accessor must be supplied upon access.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename obj=""></typename>
|
|
Shinya Kitaoka |
120a6e |
class invalidable<obj, tcg::empty_type=""> : tcg::noncopyable<> {</obj,>
|
|
Shinya Kitaoka |
120a6e |
mutable Obj m_obj; //!< Stored object
|
|
Shinya Kitaoka |
120a6e |
mutable bool m_invalid; //!< Data validity status
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef Obj obj_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
invalidable(bool invalid = false) : m_obj(), m_invalid(invalid) {}
|
|
Shinya Kitaoka |
120a6e |
invalidable(const obj_type &obj, bool invalid = false)
|
|
Shinya Kitaoka |
120a6e |
: m_obj(obj), m_invalid(invalid) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void invalidate() { m_invalid = true; }
|
|
Shinya Kitaoka |
120a6e |
bool isInvalid() const { return m_invalid; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const obj_type &operator()(DirectAccess) const { return m_obj; }
|
|
Shinya Kitaoka |
120a6e |
obj_type &operator()(DirectAccess) { return m_obj; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
template <typename func=""></typename>
|
|
Shinya Kitaoka |
120a6e |
const obj_type &operator()(Func func) const {
|
|
Shinya Kitaoka |
120a6e |
if (m_invalid) func(m_obj), m_invalid = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return m_obj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
template <typename func=""></typename>
|
|
Shinya Kitaoka |
120a6e |
obj_type &operator()(Func func) {
|
|
Shinya Kitaoka |
120a6e |
if (m_invalid) func(m_obj), m_invalid = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return m_obj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace tcg
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#endif // TCG_CONTROLLED_ACCESS_H
|