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