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