hmbdc
simplify-high-performance-messaging-programming
Public Member Functions | Private Member Functions | List of all members
hmbdc::app::Context< MaxMessageSize, ContextProperties > Class Template Reference

A Context is like a media object that facilitates the communications for the Clients that it is holding. a Client can only be added to (or started within) once to a single Context, undefined behavior otherwise. the communication model is determined by the context_property by default it is in the nature of broadcast fashion within local process indicating by broadcast<> More...

#include <Context.hpp>

Inheritance diagram for hmbdc::app::Context< MaxMessageSize, ContextProperties >:
hmbdc::app::context_detail::ThreadCommBase< MaxMessageSize, ContextProperties... > hmbdc::app::context_detail::context_property_aggregator< ContextProperties... >

Public Member Functions

 Context (uint32_t messageQueueSizePower2Num=MaxMessageSize?20:2, size_t maxPoolClientCount=MaxMessageSize?128:0, size_t maxMessageSizeRuntime=MaxMessageSize)
 ctor for construct local non-ipc Context More...
 
template<typename BoolRvOrLv , std::enable_if_t< std::is_same< bool, typename std::decay< BoolRvOrLv >::type >::value > * = nullptr>
 Context (BoolRvOrLv &&tryOwn, char const *ipcTransportName, uint32_t messageQueueSizePower2Num=MaxMessageSize?20:0, size_t maxPoolClientCount=MaxMessageSize?128:0, size_t maxMessageSizeRuntime=MaxMessageSize, uint64_t purgerCpuAffinityMask=0xfffffffffffffffful, size_t ipcTransportDeviceOffset=0, size_t ipcShmForAttPoolSize=0)
 ctor for construct local ipc Context More...
 
 ~Context ()
 dtor More...
 
template<typename Client >
void addToPool (Client &client, uint64_t poolThreadAffinityIn=0xfffffffffffffffful)
 add a client to Context's pool - the Client is run in pool mode More...
 
template<typename Client , typename ... Args>
void addToPool (Client &client, uint64_t poolThreadAffinityIn, Args &&...args)
 add a bunch of clients to Context's pool - the Clients are run in pool mode More...
 
template<typename Client , typename Client2 , typename ... Args, typename Enabled = typename std::enable_if<!std::is_integral<Client2>::value, void>::type>
void addToPool (Client &client, Client2 &client2, Args &&...args)
 add a bunch of clients to Context's pool - the Clients are run in pool mode More...
 
size_t clientCountInPool () const
 return the numebr of clients added into pool More...
 
size_t parallelConsumerAlive () const
 how many parallel consummers are started More...
 
template<typename ... Args>
void start (Args &&... args)
 start the context by specifying what are in it (Pool and/or direct Clients) and their paired up cpu affinities. More...
 
template<typename ... Args>
void registerToRun (Args &&... args)
 similarly to the start call for the usage and parameters except the Client thread is not started by this call and the user is expected to use runOnce() to manually power the Client externally More...
 
void stop ()
 stop the message dispatching - asynchronously More...
 
void join ()
 wait until all threads (Pool threads too if apply) of the Context exit More...
 
void setSecondsBetweenPurge (uint32_t s)
 ipc_creator Context runs a StcuClientPurger to purge crashed (or slow, stuck ...) Clients from the ipc transport to make the ipc trasnport healthy (avoiding buffer full). It periodically looks for things to purge. This is to set the period (default is 60 seconds). More...
 
void runOnce (uint16_t threadSerialNumberInPool)
 normally not used until you want to run your own message loop More...
 
template<typename Client >
bool runOnce (Client &&c)
 normally not used until you want to run your own message loop More...
 
- Public Member Functions inherited from hmbdc::app::context_detail::ThreadCommBase< MaxMessageSize, ContextProperties... >
void send (M0 &&m0, M1 &&m1, Messages &&... msgs)
 try send a batch of messages to the Context or attached ipc Contexts More...
 
void send (ForwardIt begin, size_t n)
 send a range of messages to the Context or attached ipc Contexts More...
 
void send (Message &&m)
 send a message including hasMortAttachment message to the Context or attached ipc Contexts More...
 
bool trySend (M0 &&m0, M1 &&m1, Messages &&... msgs)
 try to send a batch of message to the Context or attached ipc Contexts More...
 
bool trySend (ForwardIt begin, size_t n)
 try send a range of messages to the Context or attached ipc Contexts More...
 
bool trySend (Message &&m)
 try to send a message including hasMortAttachment message to the Context or attached ipc Contexts if it wouldn't block More...
 
auto allocateForSend (size_t n)
 preallocate consecutive buffers so they can be send out later More...
 
void commitForSend (IteratorAdaptor itA)
 commit all the filled up buffers allocated by allocateForSend and send them out More...
 
void sendInPlace (Args &&... args)
 send a message to all Clients in the Context or attached ipc Contexts More...
 
bool trySendInPlace (Args &&... args)
 try send a message to all Clients in the Context or attached ipc Contexts if it wouldn't block More...
 
Buffer & buffer ()
 accessor - mostly used internally More...
 

Private Member Functions

template<typename Client >
auto kickOffClientThread (Client &c, uint64_t mask, uint16_t hmbdcNumber, uint16_t threadSerialNumber)
 

Detailed Description

template<size_t MaxMessageSize = 0, typename... ContextProperties>
class hmbdc::app::Context< MaxMessageSize, ContextProperties >

A Context is like a media object that facilitates the communications for the Clients that it is holding. a Client can only be added to (or started within) once to a single Context, undefined behavior otherwise. the communication model is determined by the context_property by default it is in the nature of broadcast fashion within local process indicating by broadcast<>

a broadcast Context contains a thread Pool powered by a number of OS threads. a Client running in such a Context can either run in the pool mode or a direct mode (which means the Client has its own dedicated OS thread) direct mode provides faster responses, and pool mode provides more flexibility. It is recommended that the total number of threads (pool threads + direct threads) not exceeding the number of available CPUs.

Template Parameters
MaxMessageSizeWhat is the max message size if known at compile time(compile time sized); if the value can only be determined at runtime (run time sized), set this to 0. Things can still work but will lost some compile time checking advantages, see maxMessageSizeRuntime below
ContextPropertiessee context_property namespace

Constructor & Destructor Documentation

◆ Context() [1/2]

template<size_t MaxMessageSize = 0, typename... ContextProperties>
hmbdc::app::Context< MaxMessageSize, ContextProperties >::Context ( uint32_t  messageQueueSizePower2Num = MaxMessageSize?20:2,
size_t  maxPoolClientCount = MaxMessageSize?128:0,
size_t  maxMessageSizeRuntime = MaxMessageSize 
)
inline

ctor for construct local non-ipc Context

won't compile if calling it for ipc Context

Parameters
messageQueueSizePower2Numvalue of 10 gives message queue if size of 1024 (messages, not bytes)
maxPoolClientCountup to how many Clients the pool is suppose to support, only used when pool supported in the Context with broadcast property
maxMessageSizeRuntimeif MaxMessageSize == 0, this value is used the context can manage

◆ Context() [2/2]

template<size_t MaxMessageSize = 0, typename... ContextProperties>
template<typename BoolRvOrLv , std::enable_if_t< std::is_same< bool, typename std::decay< BoolRvOrLv >::type >::value > * = nullptr>
hmbdc::app::Context< MaxMessageSize, ContextProperties >::Context ( BoolRvOrLv &&  tryOwn,
char const *  ipcTransportName,
uint32_t  messageQueueSizePower2Num = MaxMessageSize?20:0,
size_t  maxPoolClientCount = MaxMessageSize?128:0,
size_t  maxMessageSizeRuntime = MaxMessageSize,
uint64_t  purgerCpuAffinityMask = 0xfffffffffffffffful,
size_t  ipcTransportDeviceOffset = 0,
size_t  ipcShmForAttPoolSize = 0 
)
inline

ctor for construct local ipc Context

won't compile if calling it for local non-ipc Context

Parameters
tryOwninput/output flag - if the caller tries to be the owner of this IPC Context - mean ctor called on it and when exiting, remove the IPC shm file. if true, try create if created successful, set tryOwn to true if already there, attach to it set tryOwn to false; if false, just attach to existing portal;
ipcTransportNamethe id to identify an ipc transport that supports a group of attached together Contexts and their Clients
messageQueueSizePower2Numvalue of 10 gives message queue if size of 1024 (messages, not bytes)
maxPoolClientCountup to how many Clients the pool is suppose to support, only used when pool supported in the Context with broadcast property
maxMessageSizeRuntimeif MaxMessageSize == 0, this value is used
purgerCpuAffinityMaskwhich CPUs to run the low profile (sleep mostly) thread in charge of purging crashed Clients. Used only for ipc_creator Contexts.
ipcTransportDeviceOffsetthe offset in the ipcTransport dev for the use region the context can manage

◆ ~Context()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
hmbdc::app::Context< MaxMessageSize, ContextProperties >::~Context ( )
inline

dtor

if this Context owns ipc transport, notify all attached processes that read from it that this tranport is dead

Member Function Documentation

◆ addToPool() [1/3]

template<size_t MaxMessageSize = 0, typename... ContextProperties>
template<typename Client >
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::addToPool ( Client client,
uint64_t  poolThreadAffinityIn = 0xfffffffffffffffful 
)
inline

add a client to Context's pool - the Client is run in pool mode

if pool is already started, the client is to get current Messages immediatly

  • might miss older messages. if the pool not started yet, the Client does not get messages or other callbacks until the Pool starts. This function is threadsafe, which means you can call it anywhere in the code
    Template Parameters
    Clientclient type
    Parameters
    clientto be added into the Pool
    poolThreadAffinityInpool is powered by a number of threads (thread in the pool is identified (by a number) in the mask starting from bit 0) it is possible to have a Client to use just some of the threads in the Pool

default to use all.

◆ addToPool() [2/3]

template<size_t MaxMessageSize = 0, typename... ContextProperties>
template<typename Client , typename ... Args>
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::addToPool ( Client client,
uint64_t  poolThreadAffinityIn,
Args &&...  args 
)
inline

add a bunch of clients to Context's pool - the Clients are run in pool mode

if pool is already started, the client is to get current Messages immediatly

  • might miss older messages. if the pool not started yet, the Client does not get messages or other callbacks until the Pool starts. This function is threadsafe, which means you can call it anywhere in the code
    Template Parameters
    Clientclient type
    Parameters
    clientto be added into the Pool
    poolThreadAffinityInpool is powered by a number of threads (thread in the pool is identified (by a number) in the mask starting from bit 0) it is possible to have a Client to use just some of the threads in the Pool

default to use all.

Parameters
argsmore client and poolThreadAffinityIn pairs can follow

◆ addToPool() [3/3]

template<size_t MaxMessageSize = 0, typename... ContextProperties>
template<typename Client , typename Client2 , typename ... Args, typename Enabled = typename std::enable_if<!std::is_integral<Client2>::value, void>::type>
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::addToPool ( Client client,
Client2 &  client2,
Args &&...  args 
)
inline

add a bunch of clients to Context's pool - the Clients are run in pool mode

the implementatiotn tells all if the pool not started yet, the Client does not get messages or other callbacks until the Pool starts. This function is threadsafe, which means you can call it anywhere in the code

Template Parameters
Clientclient type
Client2client2 type
Parameters
clientto be added into the Pool using default poolThreadAffinity
client2to be added into the Pool
argsmore client (and/or poolThreadAffinityIn pairs can follow

◆ clientCountInPool()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
size_t hmbdc::app::Context< MaxMessageSize, ContextProperties >::clientCountInPool ( ) const
inline

return the numebr of clients added into pool

the number could change since the clients could be added in another thread

Returns
client count

◆ join()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::join ( )
inline

wait until all threads (Pool threads too if apply) of the Context exit

blocking call

◆ kickOffClientThread()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
template<typename Client >
auto hmbdc::app::Context< MaxMessageSize, ContextProperties >::kickOffClientThread ( Client c,
uint64_t  mask,
uint16_t  hmbdcNumber,
uint16_t  threadSerialNumber 
)
inlineprivate

drain all to release sending party

◆ parallelConsumerAlive()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
size_t hmbdc::app::Context< MaxMessageSize, ContextProperties >::parallelConsumerAlive ( ) const
inline

how many parallel consummers are started

the dynamic value could change after the call returns see max_parallel_consumer Context property

Returns
how many parallel consummers are started

◆ registerToRun()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
template<typename ... Args>
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::registerToRun ( Args &&...  args)
inline

similarly to the start call for the usage and parameters except the Client thread is not started by this call and the user is expected to use runOnce() to manually power the Client externally

Template Parameters
Argssee start above
Parameters
argssee start above

◆ runOnce() [1/2]

template<size_t MaxMessageSize = 0, typename... ContextProperties>
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::runOnce ( uint16_t  threadSerialNumberInPool)
inline

normally not used until you want to run your own message loop

call this function frequently to pump hmbdc message loop in its pool

Parameters
threadSerialNumberstarting from 0, indicate which thread in the pool is powering the loop

◆ runOnce() [2/2]

template<size_t MaxMessageSize = 0, typename... ContextProperties>
template<typename Client >
bool hmbdc::app::Context< MaxMessageSize, ContextProperties >::runOnce ( Client &&  c)
inline

normally not used until you want to run your own message loop

call this function frequently to pump hmbdc message loop for a direct mode Client

Parameters
threadSerialNumberindicate which thread is powering the loop
cthe Client
Returns
true when the Client did not terminate itself by throwing an exeption
false otherwise

◆ setSecondsBetweenPurge()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::setSecondsBetweenPurge ( uint32_t  s)
inline

ipc_creator Context runs a StcuClientPurger to purge crashed (or slow, stuck ...) Clients from the ipc transport to make the ipc trasnport healthy (avoiding buffer full). It periodically looks for things to purge. This is to set the period (default is 60 seconds).

If some Client are known to take long to process messages, increase it. If you need to remove slow Clients quickly reduce it. Only effective for ipc_creator Context.

Parameters
sseconds - if set zero, purger is disabled

◆ start()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
template<typename ... Args>
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::start ( Args &&...  args)
inline

start the context by specifying what are in it (Pool and/or direct Clients) and their paired up cpu affinities.

All direct mode or clients in a pool started by a single start statement are dispatched with starting from the same event (subjected to event filtering of each client). many compile time and runtime check is done, for example: won't compile if start a pool in a Context does not support one; exception throw if the Context capacity is reached or try to start a second pool, etc.

Usage example:

// the following starts the pool powered by 3 threads that are affinitied to
// the lower 8 CPUs; client0 affinitied to 4th CPU and client1 affinitied to 5th CPU
ctx.start(3, 0xfful, client0, 0x8ul, client1, 0x10ul);
// the following starts the pool powered by 3 threads that are affinitied to
// all exisiting CPUs; client0 affinitied to a rotating CPU and
// client1 affinitied to 5th CPU
ctx.start(3, 0, client0, 0, client1, 0x10ul);
// the following starts 2 direct mode Clients (client2 and client3)
ctx.start(client2, 0x3ul, client3, 0xful);
Template Parameters
typename...Args types
Parameters
argspaired up args in the form of (pool-thread-count|client, cpuAffinity)*. see examples above. If a cpuAffinity is 0, each thread's affinity rotates to one of the CPUs in the system.

◆ stop()

template<size_t MaxMessageSize = 0, typename... ContextProperties>
void hmbdc::app::Context< MaxMessageSize, ContextProperties >::stop ( )
inline

stop the message dispatching - asynchronously

asynchronously means not garanteed message dispatching stops immidiately after this non-blocking call


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