Stub.h

// Stub.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2020

@import "cxRpc.h"
@import "Ceda/cxObject/Object.h"
#include "Ceda/cxUtils/Archive.h"

namespace ceda
{
class Stub;

///////////////////////////////////////////////////////////////////////////////////////////////////
// IStubFactory

struct IStubFactory
{
    virtual Stub* CreateStub() = 0;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// Stub factory registry

// The StubFactoryRegistry is a transient registry indexed by fully qualified name of the
// interface.
// This allows the system to automatically generate a suitable stub object for a given interface

// The following three functions can be called by different threads - they are fully threadsafe.

// Returns false if stub factory has already been registered
@api bool RegisterStub(ConstStringZ qualifiedInterfaceName, IStubFactory* factory);

@api void UnregisterStub(ConstStringZ qualifiedInterfaceName);

// Create a stub for the given interface for which a stub factory has previously been 
// registered.
// Returns nullptr if no stub factory for the given interface has been registered.
@api Stub* CreateStub(ConstStringZ qualifiedInterfaceName);

///////////////////////////////////////////////////////////////////////////////////////////////////
// Stub

/*
Base class for a stub.  More specifically, for a stub for a single implemented interface on a 
single object.
*/

class @api Stub : public BaseMixin<Stub,EmptyBase>
{
    cxNotCloneable(Stub)
public:
    Stub(AnyInterface stub, ssize_t numMethods) : 
        m_ar(nullptr),
        m_stub(stub), 
        numMethods(numMethods) 
    {
        // We assume there are no more than 256 methods, allowing the method index to be
        // serialised with a single octet.
        // todo:  Xcpp should allow for an alternative Stub to be used which uses two octets for the
        // index when the number of methods exceeds 256
        cxAssert(numMethods <= 256);
    }
    
    inline Archive& StubBegin(ssize_t index) const
    {
        cxAssert(0 <= index && index <= numMethods);
        *m_ar << (octet_t) index;
        return *m_ar;    // Return the archive used to push the arguments
    }

public:
    Archive* m_ar;
    AnyInterface m_stub;      // It is assumed this can be reinterpret cast to the interface provided by the stub
    ssize_t numMethods;
};

} // namespace ceda