16 \$cache functions using DGKeyedSyncDepNode
$cache functions with input parameters involve a cache map keyed by the input parameters. In effect there is a $dep variable of the function return type for each input.
Consider the following example:
@import "Ceda/cxObject/DGNode.h"
$struct X isa ceda::IObject
{
$cache int y(int a, int b) const
{
return a+b;
}
};
Xcpp generates the following C++ code:
struct X : public ceda::IObjectBaseMixin<X,ceda::EmptyBase>
{
typedef ceda::IObjectBaseMixin<X,ceda::EmptyBase> BaseClass;
int _calc_y(int a,int b) const
{
return a+b;
}
struct _depnode_y : public ceda::DGKeyedSyncDepNode<_depnode_y,X,std::pair<int,int>,int>
{
typedef ceda::DGKeyedSyncDepNode<_depnode_y,X,std::pair<int,int>,int> base;
using typename base::key_type;
using typename base::output_type;
using typename base::map_type;
virtual bool RecalcCache() const
{
auto _prev = _output;
std::pair<int,int> const& _key = _GetKey();
_output = _self->_calc_y(_key.first,_key.second);
if (ceda::TypeHasAdditionalSize<output_type>()) UpdateByteSize();
return _prev != _output;
}
virtual ceda::xstring Name() const
{
std::pair<int,int> const& _key = _GetKey();
return cxMakeString("X::y(" << _key.first << ',' << _key.second << ')');
}
map_type& _GetMap() const { return _self->_map_y; }
X const* _GetFinalSelf() const { return _self; }
};
mutable typename _depnode_y::map_type _map_y;
int const& y(int a,int b) const
{
return _map_y[std::make_pair(a,b)].read(this);
}
void EvictDgsNodes() const
{
BaseClass::EvictDgsNodes();
ceda::TryEvict(_map_y);
}
};
There is a nested struct named _depnode_y which represents a synchronous $dep variable. X has a member _map_y which is map from a pair of ints to _depnode_y.
_depnode_y is a subclass of ceda::DGKeyedSyncDepNode which is defined in DGNode.h
DGKeyedSyncDepNode
template <typename FinalClass, typename Self, typename Key, typename Output>
class DGKeyedSyncDepNode : public DGDepNode
{
public:
typedef Key key_type;
typedef Output output_type;
typedef std::map<key_type,FinalClass> map_type;
DGKeyedSyncDepNode() : DGDepNode(DF_SYNC_DEP) {}
key_type const& _GetKey() const
{
return GetKeyFromValueInPair<key_type,FinalClass>(static_cast<const FinalClass*>(this));
}
virtual ssize_t ByteSize() const
{
const ssize_t MapElementSize = sizeof(typename map_type::value_type);
return StdMapElementOverhead + MapElementSize + CacheValueAdditionalSize(_output);
}
virtual void VisitContainingObject(IObjectVisitor& _v) const
{
_v << _output << static_cast<const FinalClass*>(this)->_GetFinalSelf();
}
virtual void OnEvict() const
{
OnEvictCacheValue(_output);
auto& m = static_cast<const FinalClass*>(this)->_GetMap();
cxVerify(m.erase(_GetKey()) == 1);
}
virtual bool IsEvictable() const
{
return CacheValueIsEvictable(_output);
}
const output_type& read(Self const* self) const
{
_self = self;
ReadBarrier();
return _output;
}
output_type& RawCache() { return _output; }
const output_type& RawCache() const { return _output; }
protected:
mutable const Self* _self;
mutable output_type _output; // Protected by a CSpace lock
};