1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2017-2021, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17#pragma once
18
19#include "StdScheduler.h"
20#include "StdSync.h"
21
22#include <any>
23#include <functional>
24
25// Event types
26enum C4InteractiveEventType
27{
28 Ev_None = 0,
29
30 Ev_FileChange,
31
32 Ev_HTTP_Response,
33
34 Ev_IRC_Message,
35
36 Ev_Net_Conn,
37 Ev_Net_Disconn,
38 Ev_Net_Packet,
39
40 Ev_ExecuteInMainThread,
41
42 Ev_Last = Ev_ExecuteInMainThread,
43};
44
45// Collects StdSchedulerProc objects and executes them in a separate thread
46// Provides an event queue for the procs to communicate with the main thread
47class C4InteractiveThread
48{
49public:
50 C4InteractiveThread();
51 ~C4InteractiveThread();
52
53 // Event callback interface
54 class Callback
55 {
56 public:
57 virtual void OnThreadEvent(C4InteractiveEventType eEvent, const std::any &eventData) = 0;
58 virtual ~Callback() {}
59 };
60
61private:
62 // the thread itself
63 StdSchedulerThread Scheduler;
64
65 // event queue (signals to main thread)
66 struct Event
67 {
68 C4InteractiveEventType Type;
69 std::any Data;
70#ifndef NDEBUG
71 int Time;
72#endif
73 Event *Next;
74 };
75 Event *pFirstEvent, *pLastEvent;
76 CStdCSec EventPushCSec, EventPopCSec;
77
78 // callback objects for events of special types
79 Callback *pCallbacks[Ev_Last + 1];
80
81public:
82 // process management
83 bool AddProc(StdSchedulerProc *pProc);
84 void RemoveProc(StdSchedulerProc *pProc);
85
86 // event queue
87 bool PushEvent(C4InteractiveEventType eEventType, std::any data);
88 void ProcessEvents(); // by main thread
89
90 // special events
91 bool ExecuteInMainThread(std::function<void()> function)
92 {
93 // send to main thread
94 return PushEvent(eEventType: Ev_ExecuteInMainThread, data: std::move(function));
95 }
96
97 // event handlers
98 void SetCallback(C4InteractiveEventType eEvent, Callback *pnNetworkCallback)
99 {
100 pCallbacks[eEvent] = pnNetworkCallback;
101 }
102
103 void ClearCallback(C4InteractiveEventType eEvent, Callback *pnNetworkCallback)
104 {
105 if (pCallbacks[eEvent] == pnNetworkCallback) pCallbacks[eEvent] = nullptr;
106 }
107
108private:
109 bool PopEvent(C4InteractiveEventType *pEventType, std::any *data); // by main thread
110};
111