]> granicus.if.org Git - icinga2/blob - lib/base/socketevents.hpp
Merge pull request #7185 from Icinga/bugfix/gelfwriter-wrong-log-facility
[icinga2] / lib / base / socketevents.hpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #ifndef SOCKETEVENTS_H
4 #define SOCKETEVENTS_H
5
6 #include "base/i2-base.hpp"
7 #include "base/socket.hpp"
8 #include "base/stream.hpp"
9 #include <boost/thread/condition_variable.hpp>
10 #include <thread>
11
12 #ifndef _WIN32
13 #       include <poll.h>
14 #endif /* _WIN32 */
15
16 namespace icinga
17 {
18
19 /**
20  * Socket event interface
21  *
22  * @ingroup base
23  */
24 class SocketEvents : public Stream
25 {
26 public:
27         DECLARE_PTR_TYPEDEFS(SocketEvents);
28
29         ~SocketEvents();
30
31         virtual void OnEvent(int revents);
32
33         void Unregister();
34
35         void ChangeEvents(int events);
36
37         bool IsHandlingEvents() const;
38
39         void *GetEnginePrivate() const;
40         void SetEnginePrivate(void *priv);
41
42 protected:
43         SocketEvents(const Socket::Ptr& socket);
44
45 private:
46         int m_ID;
47         SOCKET m_FD;
48         bool m_Events;
49         void *m_EnginePrivate;
50
51         static int m_NextID;
52
53         static void InitializeEngine();
54
55         void WakeUpThread(bool wait = false);
56
57         void Register();
58
59         friend class SocketEventEnginePoll;
60         friend class SocketEventEngineEpoll;
61 };
62
63 #define SOCKET_IOTHREADS 8
64
65 struct SocketEventDescriptor
66 {
67         int Events{POLLIN};
68         SocketEvents::Ptr EventInterface;
69 };
70
71 struct EventDescription
72 {
73         int REvents;
74         SocketEventDescriptor Descriptor;
75 };
76
77 class SocketEventEngine
78 {
79 public:
80         void Start();
81
82         void WakeUpThread(int sid, bool wait);
83
84         boost::mutex& GetMutex(int tid);
85
86 protected:
87         virtual void InitializeThread(int tid) = 0;
88         virtual void ThreadProc(int tid) = 0;
89         virtual void Register(SocketEvents *se) = 0;
90         virtual void Unregister(SocketEvents *se) = 0;
91         virtual void ChangeEvents(SocketEvents *se, int events) = 0;
92
93         std::thread m_Threads[SOCKET_IOTHREADS];
94         SOCKET m_EventFDs[SOCKET_IOTHREADS][2];
95         bool m_FDChanged[SOCKET_IOTHREADS];
96         boost::mutex m_EventMutex[SOCKET_IOTHREADS];
97         boost::condition_variable m_CV[SOCKET_IOTHREADS];
98         std::map<SOCKET, SocketEventDescriptor> m_Sockets[SOCKET_IOTHREADS];
99
100         friend class SocketEvents;
101 };
102
103 class SocketEventEnginePoll final : public SocketEventEngine
104 {
105 public:
106         void Register(SocketEvents *se) override;
107         void Unregister(SocketEvents *se) override;
108         void ChangeEvents(SocketEvents *se, int events) override;
109
110 protected:
111         void InitializeThread(int tid) override;
112         void ThreadProc(int tid) override;
113 };
114
115 #ifdef __linux__
116 class SocketEventEngineEpoll : public SocketEventEngine
117 {
118 public:
119         virtual void Register(SocketEvents *se);
120         virtual void Unregister(SocketEvents *se);
121         virtual void ChangeEvents(SocketEvents *se, int events);
122
123 protected:
124         virtual void InitializeThread(int tid);
125         virtual void ThreadProc(int tid);
126
127 private:
128         SOCKET m_PollFDs[SOCKET_IOTHREADS];
129
130         static int PollToEpoll(int events);
131         static int EpollToPoll(int events);
132 };
133 #endif /* __linux__ */
134
135 }
136
137 #endif /* SOCKETEVENTS_H */