hmbdc
simplify-high-performance-messaging-programming
Public Member Functions | List of all members
hmbdc::app::Client< CcClient, Messages > Class Template Reference

A Client represents a thread of execution/a task. The execution is managed by a Context. a Client object could participate in message dispatching as the receiver of specifed message types. More...

#include <Client.hpp>

Inheritance diagram for hmbdc::app::Client< CcClient, Messages >:
hmbdc::app::MessageHandler< CcClient, Messages ... >

Public Member Functions

char const * hmbdcName () const
 return the name of thread that runs this client, override if necessary More...
 
std::tuple< char const *, int > schedSpec () const
 an overrideable method. returns the schedule policy and priority, override if necessary priority is only used when policy is "SCHED_RR", or "SCHED_FIFO" More...
 
size_t maxBatchMessageCount () const
 an overridable method. client receives events in batches and the max batch size is controllable when running in direct mode Context. Here is to specify the max size. More...
 
virtual void messageDispatchingStartedCb (uint16_t threadSerialNumber)
 called before any messages got dispatched - only once More...
 
virtual void stoppedCb (std::exception const &e)
 callback called when this Client is taken out of message dispatching More...
 
virtual bool droppedCb ()
 callback called after the Client is safely taken out of the Context More...
 
virtual void invokedCb (uint16_t threadSerialNumber)
 this callback is called all the time (frequently) - the exact timing is after a batch of messages are dispatched. After this call returns, the previously dispatched message's addresses are no longer valid, which means if you cache the event addresses in the previous handleMessageCb()s, you cannot use those after the return of the next invokeCb function. More...
 
virtual ~Client ()
 trivial
 
void stopped (std::exception const &e) noexcept
 internal use, don't change or override
 

Detailed Description

template<typename CcClient, typename ... Messages>
class hmbdc::app::Client< CcClient, Messages >

A Client represents a thread of execution/a task. The execution is managed by a Context. a Client object could participate in message dispatching as the receiver of specifed message types.

message is dispatched thru callbacks in the loose form of void handleMessageCb(Message const& m) or void handleMessageCb(Message& m). some callbacks have default implementations. however, all callbacks are overridable to provide desired effects; When running in a Context, all callbacks (*Cb methods) for a hmbdc Client instance are garanteed to be called from a single OS thread, ie. no 2 callabacks of an Client instance are called concurrently, so the Client programmer can assume a single thread programming model callback-wise. The above also holds true for timer firing callbacks when a concrete Client deriving from TimerManager that manages the timers

See in example hmbdc.cpp

/**
* @brief A MyClient does two things:
* - it sends out a Request and listen to Responses to the Request and send the next Request out
* - it also listens to other peer MyClient's Requests and send out Responses for each one of them
* - including the one sent out by itself
*
* @details When a specified (workload) number of Requests are sent and get back Responses
* from each peer MyClient it takes itself out of message dispatching by throwing an exception
*
*/
struct MyClient
: Client<MyClient, Request, Response> {
/**
* @brief Ctor
*
* @param myCtx the Context
* @param workLoad How many Request to send out before consider done
* @param clientCount how many MyClient instances are participating in this test
* @param srcId each TestCLient has an id
*/
MyClient(MyContext* myCtx, uint64_t workLoad, uint64_t clientCount, uint16_t srcId)
: myCtx(myCtx)
, srcId(srcId)
, requestId(0u)
, workLoad(workLoad)
, clientCount(clientCount)
, respCount(0u){
}
/**
* @brief this callback is called once and only once
* before first ever message is dispatched
* to the Client. we send out the first message
*/
void messageDispatchingStartedCb(uint16_t) override {
if (workLoad) {
myCtx->send(Request(srcId, requestId));
}
}
/**
* @brief callback
* @details all callbacks for a hmbdc Client is garanteed to be called in
* a single OS thread each time, so the programmer can assume a single thread programming model
* callback-wise
*
* @param r received Message
*/
void handleMessageCb(Request const& r) {
//got a Request - send a Response
//use sendInPlace to avoid a Reponse copy in memory
myCtx->template sendInPlace<Response>(r);
}
/**
* @brief another callback
* @details it is allowed to change the signature to be
* void handleMessageCb(Response& clients) in case clients needs to be changed (like locked)
*
* @param resp received Response message
*/
void handleMessageCb(Response const& resp) {
//got a Repsonse - check if it was triggered by the Request sent by me
if (resp.srcId == srcId &&
resp.respToId == requestId) {
if (++respCount == clientCount) {
workLoad--;
respCount = 0u;
++requestId;
//ready to send the next Request if needed
if (workLoad) {
myCtx->send(Request(srcId, requestId));
} else {
//all done, declare it by sending a Finish out
Finish fin(srcId);
myCtx->send(fin);
}
}
}
}
/**
* @brief callback called when this Client is taken out of message dispatching
* @details any exception thrown here is ignored
*
* @param e The exception that caused the Client to be taken out of message dispatching
* e could be thrown by the Client itself in a callback function
* to voluntarily take itself out
*/
void stoppedCb(std::exception const& e) override {
std::cout << e.what() << std::endl;
};
MyContext* myCtx;
uint16_t srcId;
uint64_t requestId;
uint64_t workLoad;
uint64_t clientCount;
uint64_t respCount;
};
Template Parameters
CcClientthe concrete Client type
typename... Messages message types that the Client interested if the type of JustBytes is declared, a special callback
void handleJustBytesCb(uint16_t tag, uint8_t* bytes){...}

is expected see ConsoleClient.hpp

Examples:
chat.cpp, client-server-netmap.cpp, hello-world.cpp, hmbdc-log.cpp, hmbdc.cpp, ipc-market-data-propagate.cpp, and server-cluster.cpp.

Member Function Documentation

◆ droppedCb()

template<typename CcClient, typename ... Messages>
virtual bool hmbdc::app::Client< CcClient, Messages >::droppedCb ( )
inlinevirtual

callback called after the Client is safely taken out of the Context

exception thrown here is ignored and return true is assumed

Returns
if false, this Client is added back to the Context to process messages otherwise, no more callback. You could even safely "delete this; return true;"

Reimplemented in hmbdc::app::udpcast::sendtransportengine_detail::SendTransportEngine, hmbdc::app::tcpcast::send_detail::SendTransportEngine, and hmbdc::app::netmap::sendtransportengine_detail::SendTransportEngine.

◆ hmbdcName()

template<typename CcClient, typename ... Messages>
char const* hmbdc::app::Client< CcClient, Messages >::hmbdcName ( ) const
inline

return the name of thread that runs this client, override if necessary

this only used when the Client is running in direct mode

Returns
thread name - default to be hmbdc0, hmbdc1 ...

◆ invokedCb()

template<typename CcClient, typename ... Messages>
virtual void hmbdc::app::Client< CcClient, Messages >::invokedCb ( uint16_t  threadSerialNumber)
inlinevirtual

this callback is called all the time (frequently) - the exact timing is after a batch of messages are dispatched. After this call returns, the previously dispatched message's addresses are no longer valid, which means if you cache the event addresses in the previous handleMessageCb()s, you cannot use those after the return of the next invokeCb function.

you can collectively process the messages received/cached so far here, or do something needs to be done all the time like powering another message loop

Parameters
threadSerialNumberthe number indicating which thread is in action

Reimplemented in hmbdc::app::udpcast::recvtransportengine_detail::RecvTransportEngineImpl< OutputBuffer, MsgArbitrator >, hmbdc::app::tcpcast::recvtransportengine_detail::RecvTransportEngine< OutputBuffer, MsgArbitrator >, hmbdc::app::netmap::RecvTransportEngine< OutBuffer, MsgArbitrator >, hmbdc::app::udpcast::sendtransportengine_detail::SendTransportEngine, hmbdc::app::tcpcast::send_detail::SendTransportEngine, hmbdc::app::utils::netperf_detail::SenderClient, hmbdc::app::utils::pingpong_detail::Pinger< Sender >, hmbdc::app::netmap::sendtransportengine_detail::SendTransportEngine, and hmbdc::app::StuckClientPurger< Buffer >.

◆ maxBatchMessageCount()

template<typename CcClient, typename ... Messages>
size_t hmbdc::app::Client< CcClient, Messages >::maxBatchMessageCount ( ) const
inline

an overridable method. client receives events in batches and the max batch size is controllable when running in direct mode Context. Here is to specify the max size.

a message could only be reaching one client when using partition Context. In this case, reduce the size (reduce the greediness) might be useful

Returns
the max number of messages when grabbing messages to process

◆ messageDispatchingStartedCb()

template<typename CcClient, typename ... Messages>
virtual void hmbdc::app::Client< CcClient, Messages >::messageDispatchingStartedCb ( uint16_t  threadSerialNumber)
inlinevirtual

called before any messages got dispatched - only once

this is the place some preparation code goes to

Parameters
threadSerialNumbernormally the number indicating which thread is in action, except when REGISTERED_MESSAGE_SIZE == 0 it is another undefined value

Reimplemented in hmbdc::app::udpcast::recvtransportengine_detail::RecvTransportEngineImpl< OutputBuffer, MsgArbitrator >, hmbdc::app::tcpcast::recvtransportengine_detail::RecvTransportEngine< OutputBuffer, MsgArbitrator >, hmbdc::app::utils::pingpong_detail::Ponger< Sender >, and hmbdc::app::utils::pingpong_detail::Pinger< Sender >.

◆ schedSpec()

template<typename CcClient, typename ... Messages>
std::tuple<char const*, int> hmbdc::app::Client< CcClient, Messages >::schedSpec ( ) const
inline

an overrideable method. returns the schedule policy and priority, override if necessary priority is only used when policy is "SCHED_RR", or "SCHED_FIFO"

this is only used when the Client is running in direct mode supported policy are "SCHED_OTHER"(=nullptr), "SCHED_RR", "SCHED_FIFO"

Returns
a tuple made of schedule policy and priority, default to be SCHED_OTHER

◆ stoppedCb()

template<typename CcClient, typename ... Messages>
virtual void hmbdc::app::Client< CcClient, Messages >::stoppedCb ( std::exception const &  e)
inlinevirtual

callback called when this Client is taken out of message dispatching

after this call the Client is still at hook from the Context point of view (until droppedCb is called), so don't delete this Client yet or add it back to the Context. any exception thrown here is ignored,

Parameters
ethe exception that caused the Client to be taken out of message dispatching e could be thrown by the Client itself in a callback function to voluntarily take itself out

Reimplemented in hmbdc::app::udpcast::recvtransportengine_detail::RecvTransportEngineImpl< OutputBuffer, MsgArbitrator >, hmbdc::app::utils::netperf_detail::ReceiverClient, hmbdc::app::netmap::RecvTransportEngine< OutBuffer, MsgArbitrator >, hmbdc::app::tcpcast::recvtransportengine_detail::RecvTransportEngine< OutputBuffer, MsgArbitrator >, hmbdc::app::utils::netperf_detail::SenderClient, hmbdc::app::utils::pingpong_detail::Ponger< Sender >, hmbdc::app::netmap::sendtransportengine_detail::SendTransportEngine, hmbdc::app::utils::pingpong_detail::Pinger< Sender >, and hmbdc::app::StuckClientPurger< Buffer >.


The documentation for this class was generated from the following file: