Setting member variables can require additional checks. Some of these checks can be modelled through
the static type system (a temperature below
To support the enforcement of pre and post-conditions the user may configure pre and post operations for member setters
(which default to no-ops):
template<class ReflectedClass, class AttributeTag, class ValueType> void preSet(ReflectedClass& rec, AttributeTag tag, ValueType val) { /* whatever needs to be done */}
the same for static member variables:
template<class ReflectedClass, class AttributeTag, class ValueType> void preSet(AttributeTag tag, ValueType val) { /* whatever needs to be done */}
template<class ReflectedClass, class AttributeTag> void postSet(ReflectedClass& rec, AttributeTag) { /* whatever needs to be done */}
template<class ReflectedClass, class AttributeTag> void postSet(AttributeTag) { /* whatever needs to be done */}
Note that the generative algorithms defined in the library operate on references to member variables and hence pre and post operations are not applied when member variables are changed through a generative algorithm. One application of generative algorithms is to read / write reflected state from / to persistent storage (database, file). Usually it is assumed that when dumping an object, this object's state is consistent. As a consequence deserialization can assume that no invariants were violated and hence no checks are needed before the state of a member variable is restored. This may improve the performance (and it definitely makes the implementation of the generative algorithms easier).
Nonetheless flat and deep attribute traversions on non-const reflected classes try to acquire a lock for the traversion.
struct YourAttributeFunction { /* item functions as needed for deep traversions */ }; YourAttributeFunction attributeFunction;
YourReflectedClass nonConstReflectedObject;
depthFirstForeachIncAllBaseClasses(nonConstReflectedObject, attributeFunction, InstanceVariableTag());
Here nonConstReflectedObject.getMutex() will be used to acquire a lock for the deep
traversion of non-static members of YourReflectedClass.
The locktype is userconfig::LockType< YourReflectedClass, userconfig::ThreadingModel>::type
(As specified in userconfig.h).
const YourReflectedClass constReflectedObject = nonConstReflectedObject;
depthFirstForeachIncAllBaseClasses(constReflectedObject, attributeFunction, InstanceVariableTag());
Here the traversion will not try to acquire any lock.
depthFirstForeachIncAllBaseClasses<YourReflectedClass>(attributeFunction);
Here userconfig::MutexInstance<ReflectedClass, userconfig::ThreadingModel>::get() will be used to acquire a lock for the
deep traversion of static members of YourReflectedClass.
The locktype is userconfig::LockType<ReflectedClass, userconfig::ThreadingModel>::type.
depthFirstForeachIncAllBaseClasses<const
YourReflectedClass>(attributeFunction);
Here the traversion of the static members of YourReflectedClass will not try to acquire any lock.
Last revised: September 13, 2004 | Copyright © 2004 Arne Adams |