hmbdc
simplify-high-performance-messaging-programming
hello-world.cpp
///
/// A first example to show inter-thread messaging using hmbdc-free lib
///
///to build: (newer compilers might require -faligned-new compile flag)
///g++ hello-world.cpp -g -std=c++1y -Wall -Werror -pthread -I /opt/hmbdc/include/ /opt/hmbdc/lib/libhmbdc.a -lrt -o hw
///or
///clang++ hello-world.cpp stdlib=libstdc++ hello_ctx.cpp -g -std=c++1y -Wall -Werror -pthread -I /opt/hmbdc/include/ /opt/hmbdc/lib/libhmbdc-clang.a -lrt -o hw
///
///output:
///-------------------------------------------
/// [host]$ ./hw
/// anyone saying hello? - waiting...
/// I am going to work for a second...
/// I am going to work for a second...
/// I am going to work for a second...
/// someone just said hello
/// I am going to work for a second...
/// I am going to work for a second...
/// 500 years winter is coming - exiting
#include "hmbdc/app/Base.hpp"
using namespace hmbdc::app;
using namespace std;
///
/// user defined messages
/// the tag number starting from 0 - 1000 is reserved for internal usage
///
struct Hello
: hasTag<1001> {
};
struct WinterComing
: hasTag<1002> {
WinterComing(int y)
: years(y)
{}
int years;
};
///
/// a Client is like a task or a thread of execution, it is also a collection of
/// callbacks that are called by hmbdc as the execution proceeds.
/// For a particuclar Client, its callbacks are called in sequential (non-concurrently).
///
struct Kingslanding
: Client<Kingslanding, Hello, WinterComing> { ///the Client(Kingslanding) is interested in Hello and WinterComing messages
///
/// optional callback called ONCE by hmbdc framework before starting dispatching any messages
///
void messageDispatchingStartedCb(uint16_t) override {
cout << "anyone saying hello? - waiting..." << endl;
}
///
/// optional callback in which you can execute anything, return when you are ready to
/// process messages, and don't worry, this callback will be called repeatedly
///
void invokedCb(uint16_t) override {
cout << "I am going to work for a second..." << endl;
sleep(1); //actually sleeping, but could be doing some work like fighting the insurgents here
}
///
/// nonoptional message handling callback - won't compile if this function is missing since
/// this Client (Kingslanding) has shown interest in Hello
///
void handleMessageCb(Hello const&) {
cout << "someone just said hello" << endl;
}
///
/// although nonoptional, a message handling callback could take slightly different
/// forms, by value vs by reference ...
///
void handleMessageCb(WinterComing w) const {
cout << w.years << " years winter is coming - exiting" << endl;
throw(0); //any exception in callback will exit the Client
}
};
int main() {
Kingslanding kingslanding;
//! [broadcast as default]
/// declare Context in the default broadcast type
/// - a message is broadcasted to every Client in this Context
/// - the maximum message size this context can handle is sizeof(WinterComing)
/// would not compile if size is too small.
/// Use 0 if the max message size is not known at compile time
using MyContext = Context<sizeof(WinterComing)>;
MyContext ctx; /// this the communication media object - message dispatcher
//! [broadcast as default]
//starting kingslanding as a direct mode Client(a thread), pin it on 1st core
//user could append more direct mode Clients in the same call to start them in 'ctx', or
//use the more flexible thread pool to run Clients in the pool mode (vs direct mode)
ctx.start(kingslanding, 0x01);
sleep(3); /// let kingslanding work for 3 seconds
ctx.send(Hello()); ///say hello now, every (interested) Client in ctx (only kingslanding for now) will get it
sleep(2); /// let kingslanding work for another 2 seconds
ctx.sendInPlace<WinterComing>(500); ///in place construct WinterComing and send it out
//wait for kingslanding to exit
ctx.join();
}