tahoma2d/toonz/sources/include/tcg/controlled_access.h

219 lines
6.2 KiB
C
Raw Normal View History

2016-05-17 03:04:11 +12:00
#pragma once
2016-03-19 06:57:51 +13:00
#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.
2016-06-15 18:43:10 +12:00
Some notable cases for this idiom include the "frequent notifier /
lazy update"
scenario, where an object is frequently notified for status updates,
but
2016-03-19 06:57:51 +13:00
many updates can be spared until the data is finally accessed.
*/
2016-06-15 18:43:10 +12:00
namespace tcg {
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
enum DirectAccess { direct_access }; //!< Enum used to access variables with
//! controlled output directly.
2016-03-19 06:57:51 +13:00
//*************************************************************************
// 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
2016-06-15 18:43:10 +12:00
or supplying it during access. In case the accessor type is
specified,
2016-03-19 06:57:51 +13:00
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>
2016-06-15 18:43:10 +12:00
class controlled_access : tcg::noncopyable<> {
Obj m_obj; //!< Stored object.
Func m_func; //!< Functor to be invoked upon access.
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
typedef Obj obj_type;
typedef Func func_type;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
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;
}
2016-03-19 06:57:51 +13:00
};
//------------------------------------------------------------------------------
/*!
2016-06-15 18:43:10 +12:00
\brief Explicit specialization advocating no explicit accessor functor -
the
2016-03-19 06:57:51 +13:00
accessor must be supplied upon access.
*/
template <typename Obj>
2016-06-15 18:43:10 +12:00
class controlled_access<Obj, tcg::empty_type> : tcg::noncopyable<> {
Obj m_obj; //!< Stored object.
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
typedef Obj obj_type;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
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;
}
2016-03-19 06:57:51 +13:00
};
//==============================================================================
/*!
2016-06-15 18:43:10 +12:00
\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
2016-03-19 06:57:51 +13:00
allowed.
2016-06-15 18:43:10 +12:00
\details An invalidable instance wraps a \a mutable object and adds a boolean
to
2016-03-19 06:57:51 +13:00
signal its current validity state.
2016-06-15 18:43:10 +12:00
The initial validity of the object can be specified at construction,
and
2016-03-19 06:57:51 +13:00
explicitly set to the invalid state through the invalidate() method.
2016-06-15 18:43:10 +12:00
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.
2016-03-19 06:57:51 +13:00
*/
template <typename Obj, typename Func = tcg::empty_type>
2016-06-15 18:43:10 +12:00
class invalidable : tcg::noncopyable<> {
mutable Obj m_obj; //!< Stored object.
mutable bool m_invalid; //!< Data validity status.
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
Func m_func; //!< Functor to be invoked upon access.
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
typedef Obj obj_type;
typedef Func func_type;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
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) {}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void invalidate() { m_invalid = true; }
bool isInvalid() const { return m_invalid; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const obj_type &operator()(DirectAccess) const { return m_obj; }
obj_type &operator()(DirectAccess) { return m_obj; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const obj_type &operator()() const {
if (m_invalid) m_func(m_obj), m_invalid = false;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
return m_obj;
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
obj_type &operator()() {
if (m_invalid) m_func(m_obj), m_invalid = false;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
return m_obj;
}
2016-03-19 06:57:51 +13:00
};
//------------------------------------------------------------------------------
/*!
2016-06-15 18:43:10 +12:00
\brief Explicit specialization advocating no explicit validator functor -
the
2016-03-19 06:57:51 +13:00
accessor must be supplied upon access.
*/
template <typename Obj>
2016-06-15 18:43:10 +12:00
class invalidable<Obj, tcg::empty_type> : tcg::noncopyable<> {
mutable Obj m_obj; //!< Stored object
mutable bool m_invalid; //!< Data validity status
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
typedef Obj obj_type;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
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;
}
2016-03-19 06:57:51 +13:00
};
2016-06-15 18:43:10 +12:00
} // namespace tcg
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
#endif // TCG_CONTROLLED_ACCESS_H