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
};