GithubHelp home page GithubHelp logo

lkmsg's Introduction

lk::msg

a message/signal libary for modern C++.

Requires C++ 17.

lk::msg has three different parts: A Listener, a Message and a Channel.

The concept is clear by the pure english meaning of these terms: A listener listens for a message on a channel. A message in this case is any object, wrapped within std::any, it could even be a lambda.

A listener has to register to a channel in order to start getting messages. This is handled in an RAII way, as a Listener has to be created with a Channel as an argument, and will automatically register / unregister when created / destroyed respectively. When a message is received, each listener passes the message on to its handler, which is a std::function object, assigned on construction. Channels are enforced to be created as std::shared_ptr, so that all listeners keep it alive, and a Listener will never listen on a channel that doesn't exist. A Channel can, however, be deactivated by being closed.

How to use

Building

Universal guide

For specific Linux / Windows instructions, see below.

This project uses CMake.

  1. Configure CMake. Useful options are:
  • CMAKE_BUILD_TYPE, which can either be Debug or Release.
  • LK_MESSAGES_STATIC, which should be ON for a static library build, and OFF (default) for a dynamic library build.
  1. Build. The output folder is referred to as $bin in this guide.
  2. Add the include folder to the include directories of your compiler/build system of choice, and $bin to your link directories.
  3. Include lk/messages.h and link against lkmsg.

Linux / Unix

This guide assumes you have basic knowledge of the terminal and assumes a shell like sh.

  1. Run cmake with -DCMAKE_BUILD_TYPE=Release. You can specify -DLK_MESSAGES_STATIC=ON to build lk::msg as a static library. by default a dynamic library is built.
  2. Run make.
  3. You now have liblkmsg.so or liblkmsg.a, depending on whether LK_MESSAGES_STATIC was set in cmake.
  4. Add include to your build systems include paths
  5. Add folder in which make was run to link paths.
  6. Link against lkmsg, for example with -llkmsg.

Windows

Use Visual Studio, CLion or other IDE that supports CMake projects.

  1. Open / Import this project.
  2. Configure CMake. Useful options are:
  • CMAKE_BUILD_TYPE, which can either be Debug or Release.
  • LK_MESSAGES_STATIC, which should be ON for a static library build, and OFF (default) for a dynamic library build.
  1. Build.
  2. The output folder now has the library .dll or .lib file, which you can link to. include should be added to include paths.

Using lk::msg in your own project

In general, it is recommended that you using namespace lk, if msg does not conflict with other namespaces in your project.

lk::msg uses the following concepts:

  • Channel: Connects listeners to messages. This is the base of all communication in lk::msg. A Channel is instantiated like so:
lk::msg::Channel::Ptr my_channel = lk::msg::Channel::create();

This creates a shared (refcounted) pointer to a channel. This is the only way to construct a Channel.

  • Listener: Connects to a Channel to listen to new messages. Invokes a callback/handler on message receive.
lk::msg::Listener my_listener(my_channel, my_handler);

Note that the constructor takes a lk::msg::Channel::Ptr by value. This ensures that the Channel is kept alive (through refcounting) as long as listeners exist. my_handler is a function of signature void(const lk::msg::Message&). You may pass nullptr for this and set the handler later via my_listener.set_handler(my_handler);.

  • Message: A lightweight object encoding the type of message (as an int), and the message data with std::any.
lk::msg::Message my_message(1, std::string("Hello, World!"));
bool success = my_channel.send(std::move(my_message));

Note that the message is moved into Channel::send() - this design clarifies that the channel now owns the message, and once its been sent to every listener, it will be destroyed.

The first argument, 1 in this case, is of type int. This is to be used, with an enum instead of a raw int for example, to identify what type of message it is, i.e. what its purpose is. Note that, to identify which type is held by the std::any member data, std::any::type can be compared to typeid(xyz) to find out whether a cast from data to type xyz is valid. This purpose member of Message is useful because two different messages (like a hello and a goodbye message) could both have a string as data (i.e. std::any::type), yet be different kinds of messages which are to be handled differently. In this case, the std::any::type is the same, but the Message::purpose is not.

  • MultiListener: A single object managing multiple listeners to multiple channels, receiving all messages in a single handler. Can be used like a normal Listener, but will listen to multiple channels at the same time. If this finds frequent use, then Channels likely have not been used properly, and multiple channels can probably be merged into one. A MultiListener is useful for logging all ongoing messages in the program, but if its used for other things, there is likely an inefficient use of Channels.

What is a good pattern for Message data?

My favourite way to use this library is to use classes & structs as the data of the Message. Example struct you could pass in a message:

enum MyMessageType {
    Hello,
    Update,
    Goodbye
};

struct SimpleMessage {
    Object sender;
    Object receiver;
    std::string message;
};
// ...
using namespace lk;

SimpleMessage msg { ... };
msg::Message hello_message(MessageType::Hello, msg);
channel->send(std::move(hello_message));

This way, on the receiving end, you can std::any_cast it back to a SimpleMessage, and thus pass as complex a message as you want.

lkmsg's People

Contributors

lionkor avatar

Watchers

James Cloos avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.