15 \$cache functions using DGSyncDepNode
Parameterless $cache functions are treated specially because there is no need for a cache map. Instead they are more like a $dep variable.
Consider the following example:
@import "Ceda/cxObject/DGNode.h"
$struct X isa ceda::IObject
{
$cache int y() const { return 7; }
};
Xcpp generates the following C++ code:
struct X : public ceda::IObjectBaseMixin<X,ceda::EmptyBase>
{
typedef ceda::IObjectBaseMixin<X,ceda::EmptyBase> BaseClass;
int _calc_y() const
{
return 7;
}
struct _depnode_y : public ceda::DGSyncDepNode<_depnode_y,X,int>
{
typedef ceda::DGSyncDepNode<_depnode_y,X,int> base;
using typename base::output_type;
virtual bool RecalcCache() const
{
int _prev = _output;
_output = _GetSelf()->_calc_y();
if (ceda::TypeHasAdditionalSize<output_type>()) UpdateByteSize();
return _prev != _output;
}
X const* _GetSelf() const { return CONST_ATTRIB_CAST(X,_dn_y); }
X const* _GetFinalSelf() const { return _GetSelf(); }
virtual ceda::xstring Name() const { return "X::y()"; }
} _dn_y;
int const& y() const
{
return _dn_y.read();
}
void EvictDgsNodes() const
{
BaseClass::EvictDgsNodes();
_dn_y.TryEvict(false);
}
};
There is a nested struct named _depnode_y which represents a synchronous $dep variable.
_depnode_y is a subclass of ceda::DGSyncDepNode which is defined in DGNode.h
DGSyncDepNode
template <typename FinalClass, typename Self, typename Output>
class DGSyncDepNode : public DGDepNode
{
public:
typedef Output output_type;
DGSyncDepNode() : DGDepNode(DF_SYNC_DEP) {}
virtual ssize_t ByteSize() const
{
// This is the *overhead* of caching the output, it is assumed when OnEvict() calls
// ClearCacheValue(_output), CacheValueAdditionalSize() gives the number of bytes that is recovered.
return CacheValueAdditionalSize(_output);
}
virtual void VisitContainingObject(IObjectVisitor& _v) const
{
_v << _output << static_cast<const FinalClass*>(this)->_GetFinalSelf();
}
virtual void OnEvict() const
{
OnEvictCacheValue(_output);
ClearCacheValue(_output);
}
virtual bool IsEvictable() const
{
return CacheValueIsEvictable(_output);
}
const output_type& read() const
{
ReadBarrier();
return _output;
}
output_type& RawCache() { return _output; }
const output_type& RawCache() const { return _output; }
protected:
mutable output_type _output; // Protected by a CSpace lock
};
Clearing the cache value to recover memory when the node is evicted
In this example the $cache function returns an int. The memory for this cached value is
not recovered when the DGS node is evicted because the cached value is stored in the member
_output of DGSyncDepNode which is in turned stored in the member
_dn_y of X.
For that reason, in this case ByteSize() for the DGS node returns 0. The effective size of the DGS node is zero since nothing is recovered when it is evicted.
However when a $cache function returns a dynamically sized type (such as a variant, optional, string, vector, deque, list, map or set), the call to ClearCacheValue in the generated OnEvict() function may indeed recover memory.
virtual void OnEvict() const
{
...
ClearCacheValue(_output); // May recover memory
}
In that case it is assumed that CacheValueAdditionalSize(output_) gives the number of bytes that is recovered.
virtual ssize_t ByteSize() const
{
// This is the *overhead* of caching the output, it is assumed when OnEvict() calls
// ClearCacheValue(_output), CacheValueAdditionalSize() gives the number of bytes that is recovered.
return CacheValueAdditionalSize(_output);
}