openclonk/src/network/C4InteractiveThread.h

131 lines
3.2 KiB
C++

/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2009-2016, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
#ifndef C4INTERACTIVETHREAD_H
#define C4INTERACTIVETHREAD_H
#include "platform/StdScheduler.h"
#include "platform/StdSync.h"
// Event types
enum C4InteractiveEventType
{
Ev_None = 0,
Ev_Function,
Ev_Log,
Ev_LogSilent,
Ev_LogFatal,
Ev_LogDebug,
Ev_FileChange,
Ev_HTTP_Response,
Ev_UPNP_Response,
Ev_IRC_Message,
Ev_Net_Conn,
Ev_Net_Disconn,
Ev_Net_Packet,
Ev_Last = Ev_Net_Packet
};
class C4InteractiveThreadNotifyProc : public CStdNotifyProc
{
private:
class C4InteractiveThread *pNotify;
public:
void SetNotify(class C4InteractiveThread *pnNotify) { pNotify = pnNotify; }
bool Execute(int iTimeout, pollfd * readyfds) override;
};
// Collects StdSchedulerProc objects and executes them in a separate thread
// Provides an event queue for the procs to communicate with the main thread
class C4InteractiveThread
{
public:
C4InteractiveThread();
~C4InteractiveThread();
// Event callback interface
class Callback
{
public:
virtual void OnThreadEvent(C4InteractiveEventType eEvent, void *pEventData) = 0;
virtual ~Callback() = default;
};
private:
// the thread itself
StdSchedulerThread Scheduler;
// event queue (signals to main thread)
struct Event
{
C4InteractiveEventType Type;
void *Data;
#ifdef _DEBUG
C4TimeMilliseconds Time;
#endif
Event *Next;
};
Event *pFirstEvent, *pLastEvent;
CStdCSec EventPushCSec, EventPopCSec;
// callback objects for events of special types
Callback *pCallbacks[Ev_Last + 1];
// proc that is added to the main thread to receive messages from our thread
C4InteractiveThreadNotifyProc NotifyProc;
public:
// process management
bool AddProc(StdSchedulerProc *pProc);
void RemoveProc(StdSchedulerProc *pProc);
// event queue
bool PushEvent(C4InteractiveEventType eEventType, void *pData = nullptr);
void ProcessEvents(); // by main thread
// special events
bool ThreadLog(const char *szMessage, ...) GNUC_FORMAT_ATTRIBUTE_O;
bool ThreadLogFatal(const char *szMessage, ...) GNUC_FORMAT_ATTRIBUTE_O;
bool ThreadLogS(const char *szMessage, ...) GNUC_FORMAT_ATTRIBUTE_O;
bool ThreadLogDebug(const char *szMessage, ...) GNUC_FORMAT_ATTRIBUTE_O;
template<typename RType = void, typename Functor>
bool ThreadPostAsync(Functor function)
{
return PushEvent(Ev_Function, new std::function<RType()>(function));
}
// event handlers
void SetCallback(C4InteractiveEventType eEvent, Callback *pnNetworkCallback)
{ pCallbacks[eEvent] = pnNetworkCallback; }
void ClearCallback(C4InteractiveEventType eEvent, Callback *pnNetworkCallback)
{ if (pCallbacks[eEvent] == pnNetworkCallback) pCallbacks[eEvent] = nullptr; }
private:
bool PopEvent(C4InteractiveEventType *pEventType, void **ppData); // by main thread
};
#endif // C4INTERACTIVETHREAD_H