RmiBounce.cpp
// RmiBounce.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2011
@import "Ceda/cxRmi/RmiConnection.h"
#include "Ceda/cxUtils/Tracer.h"
#include "Ceda/cxUtils/TestTimer.h"
#include "Ceda/cxUtils/Event.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
// IBounce
$interface rmi IBounce
{
// Asynchronous method
void Bounce([in] ceda::int32 x);
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// BounceSession
/*
warning W1003 : $interface IBounce doesn't inherit from IObject
warning W1003 : See 'isa' used on $struct BounceSession
warning W1013 : $interface IBounce not reflected
warning W1013 : See 'isa' used on $struct BounceSession
*/
$warning(push; disable: 1003 1013)
$struct BounceSession isa IBounce :
mixin
[
ceda::RmiSessionMixin2<IBounce,IBounce>
]
{
cxNotCloneable(BounceSession)
public:
BounceSession() {}
// Implementation of IBounce
void Bounce(ceda::int32 x)
{
Tracer() << " Bounce() called with x= " << x << '\n';
if (x > 0)
{
GetStub()->Bounce(x-1);
Flush(); // Flush the message straightaway
}
else
{
m_done.Signal();
}
}
ceda::ManualResetEvent m_done;
};
$warning(pop)
///////////////////////////////////////////////////////////////////////////////////////////////////
// RmiBounce
/*
Output is as follows:
Rmi Bounce
Bounce() called with x= 11
Bounce() called with x= 10
Bounce() called with x= 9
Bounce() called with x= 8
Bounce() called with x= 7
Bounce() called with x= 6
Bounce() called with x= 5
Bounce() called with x= 4
Bounce() called with x= 3
Bounce() called with x= 2
Bounce() called with x= 1
Bounce() called with x= 0
Bounce async messages 0.00181 s 7.54 kHz
Test completed
Note that the reported rate is constrained by the tracing for each call to Bounce(). Without the
tracing the rate is about 35 kHz in release on Q9400 2.66GHz machine, x64.
It would appear that Bounce() calls itself recursively and therefore might run out of stack. But
actually the calls are asychrononous - i.e. each call can return before or after the recursive call.
Therefore running out of stack space isn't an issue. Performance is constrained by the various
overheads of separate I/O for each message.
*/
void RmiBounce()
{
Tracer() << "Rmi Bounce\n";
ceda::TraceIndenter indent;
ceda::Iocp* iocp = ceda::CreateIocp();
for (int count = 0 ; count < 1 ; ++count)
{
ceda::SOCKET_PORT port = 3001;
ceda::BlockingSingleSessionCreator<BounceSession>* ccClient = new ceda::BlockingSingleSessionCreator<BounceSession>();
ceda::MServer* server = ceda::CreateMServer(iocp, new ceda::SessionCreator<BounceSession>(), port);
ceda::MClient* client = ceda::CreateMClient(iocp, ccClient, "127.0.0.1", port);
BounceSession* bsClient = ccClient->GetSession();
ceda::ptr<IBounce> stubClient = bsClient->GetStub();
// Bound messages back and forth decrementing a counter as we go until counter reaches 0
// and a manual-reset event is signalled
{
const int N = 10;
ceda::RateTimer t("Bounce async messages", N);
cxAssert(N % 2 == 0); // We assume client will signal m_done
stubClient->Bounce(N+1);
bsClient->Flush();
bsClient->m_done.Wait();
}
Close(client);
Close(server);
}
Close(iocp);
Tracer() << "Test completed\n";
}