Toshihiro Shimizu 890ddd
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