1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
/*
* Copyright (C) 2005-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: LGPL-2.1-or-later
* See LICENSES/README.md for more information.
*/
#pragma once
#include "threads/CriticalSection.h"
#include <cstddef>
#include <memory>
#include <queue>
#include <string>
#include <utility>
class CEvent;
namespace Actor
{
class CPayloadWrapBase
{
public:
virtual ~CPayloadWrapBase() = default;
};
template<typename Payload>
class CPayloadWrap : public CPayloadWrapBase
{
public:
~CPayloadWrap() override = default;
CPayloadWrap(Payload* data) { m_pPayload.reset(data); }
CPayloadWrap(Payload& data) { m_pPayload.reset(new Payload(data)); }
Payload* GetPlayload() { return m_pPayload.get(); }
protected:
std::unique_ptr<Payload> m_pPayload;
};
class Protocol;
class Message
{
friend class Protocol;
static constexpr size_t MSG_INTERNAL_BUFFER_SIZE = 32;
public:
int signal;
bool isSync = false;
bool isSyncFini;
bool isOut;
bool isSyncTimeout;
size_t payloadSize;
uint8_t buffer[MSG_INTERNAL_BUFFER_SIZE];
uint8_t *data = nullptr;
std::unique_ptr<CPayloadWrapBase> payloadObj;
Message *replyMessage = nullptr;
Protocol &origin;
CEvent *event = nullptr;
void Release();
bool Reply(int sig, void *data = nullptr, size_t size = 0);
private:
explicit Message(Protocol &_origin) noexcept
:origin(_origin) {}
};
class Protocol
{
public:
Protocol(std::string name, CEvent* inEvent, CEvent* outEvent)
: portName(std::move(name)), containerInEvent(inEvent), containerOutEvent(outEvent)
{
}
Protocol(std::string name) : Protocol(std::move(name), nullptr, nullptr) {}
~Protocol();
Message *GetMessage();
void ReturnMessage(Message *msg);
bool SendOutMessage(int signal,
const void* data = nullptr,
size_t size = 0,
Message* outMsg = nullptr);
bool SendOutMessage(int signal, CPayloadWrapBase *payload, Message *outMsg = nullptr);
bool SendInMessage(int signal,
const void* data = nullptr,
size_t size = 0,
Message* outMsg = nullptr);
bool SendInMessage(int signal, CPayloadWrapBase *payload, Message *outMsg = nullptr);
bool SendOutMessageSync(int signal,
Message** retMsg,
std::chrono::milliseconds timeout,
const void* data = nullptr,
size_t size = 0);
bool SendOutMessageSync(int signal,
Message** retMsg,
std::chrono::milliseconds timeout,
CPayloadWrapBase* payload);
bool ReceiveOutMessage(Message **msg);
bool ReceiveInMessage(Message **msg);
void Purge();
void PurgeIn(int signal);
void PurgeOut(int signal);
void DeferIn(bool value) { inDefered = value; }
void DeferOut(bool value) { outDefered = value; }
void Lock() { criticalSection.lock(); }
void Unlock() { criticalSection.unlock(); }
std::string portName;
protected:
CEvent *containerInEvent, *containerOutEvent;
CCriticalSection criticalSection;
std::queue<Message*> outMessages;
std::queue<Message*> inMessages;
std::queue<Message*> freeMessageQueue;
bool inDefered = false, outDefered = false;
};
}
|