diff --git a/single_include/3rd_include/polym/Msg.hpp b/single_include/3rd_include/polym/Msg.hpp new file mode 100644 index 0000000..86e531b --- /dev/null +++ b/single_include/3rd_include/polym/Msg.hpp @@ -0,0 +1,108 @@ +#pragma once +#include +#include + +namespace PolyM { + +/** Type for Msg unique identifiers */ +using MsgUID = unsigned long long; + +/** + * Msg represents a simple message that doesn't have any payload data. + * Msg ID identifies the type of the message. Msg ID can be queried with getMsgId(). + */ +class Msg +{ +public: + /** + * Construct a Msg. + * + * @param msgId Msg ID of this Msg. + */ + Msg(int msgId); + + virtual ~Msg() = default; + Msg(const Msg&) = delete; + Msg& operator=(const Msg&) = delete; + + /** "Virtual move constructor" */ + virtual std::unique_ptr move(); + + /** + * Get Msg ID. + * Msg ID identifies message type. + * Multiple Msg instances can have the same Msg ID. + */ + int getMsgId() const; + + /** + * Get Msg UID. + * Msg UID is the unique ID associated with this message. + * All Msg instances have a unique Msg UID. + */ + MsgUID getUniqueId() const; + + /** Get the raw payload data */ + [[nodiscard]] virtual void* getRawPayLoad() const { + return nullptr; + } + +protected: + Msg(Msg&&) = default; + Msg& operator=(Msg&&) = default; + +private: + int msgId_; + MsgUID uniqueId_; +}; + +/** + * DataMsg is a Msg with payload of type PayloadType. + * Payload is constructed when DataMsg is created and the DataMsg instance owns the payload data. + */ +template +class DataMsg : public Msg +{ +public: + /** + * Construct DataMsg + * @param msgId Msg ID + * @param args Arguments for PayloadType ctor + */ + template + DataMsg(int msgId, Args&& ... args) + : Msg(msgId), + pl_(new PayloadType(std::forward(args) ...)) + { + } + + virtual ~DataMsg() = default; + DataMsg(const DataMsg&) = delete; + DataMsg& operator=(const DataMsg&) = delete; + + /** "Virtual move constructor" */ + virtual std::unique_ptr move() override + { + return std::unique_ptr(new DataMsg(std::move(*this))); + } + + /** Get the payload data */ + PayloadType& getPayload() const + { + return *pl_; + } + + /** Get the raw payload data */ + [[nodiscard]] void* getRawPayLoad() const override { + return reinterpret_cast(pl_.get()); + } + +protected: + DataMsg(DataMsg&&) = default; + DataMsg& operator=(DataMsg&&) = default; + +private: + std::unique_ptr pl_; +}; + +} diff --git a/single_include/3rd_include/polym/Queue.hpp b/single_include/3rd_include/polym/Queue.hpp new file mode 100644 index 0000000..8696093 --- /dev/null +++ b/single_include/3rd_include/polym/Queue.hpp @@ -0,0 +1,77 @@ +#pragma once +#include "Msg.hpp" +#include + +namespace PolyM { + +/** + * Queue is a thread-safe message queue. + * It supports one-way messaging and request-response pattern. + */ +class Queue +{ +public: + Queue(); + + ~Queue(); + + /** + * Put Msg to the end of the queue. + * + * @param msg Msg to put to the queue. + */ + void put(Msg&& msg); + + /** + * Get message from the head of the queue. + * Blocks until at least one message is available in the queue, or until timeout happens. + * If get() returns due to timeout, returns a nullptr. + * + * @param timeoutMillis How many ms to wait for message until timeout happens. + * 0 = wait indefinitely. + */ + std::unique_ptr get(int timeoutMillis = 0); + + /** + * Get message from the head of the queue. + * Returns an empty pointer if no message is available. + */ + std::unique_ptr tryGet(); + + /** + * Make a request. + * Call will block until response is given with respondTo(). + * If request() returns due to timeout, returns a nullptr. + * + * @param msg Request message. Is put to the queue so it can be retrieved from it with get(). + * @param timeoutMillis How many ms to wait for response until timeout happens. + * 0 = wait indefinitely. + */ + std::unique_ptr request(Msg&& msg, int timeoutMillis = 0, void (*on_put_callback)() = nullptr); + + /** + * Respond to a request previously made with request(). + * If the requestID has been found, return true. + * + * @param reqUid Msg UID of the request message. + * @param responseMsg Response message. The requester will receive it as the return value of + * request(). + */ + bool respondTo(MsgUID reqUid, Msg&& responseMsg); + + /** + * Get the size of the queue + */ + size_t size(); + + /** + * Clear all messages in queue + */ + void clear(); + +private: + class Impl; + std::unique_ptr impl_; +}; + +}