TDME2  1.9.200
KernelEventMechanism.cpp
Go to the documentation of this file.
1 #include <tdme/tdme.h>
2 
3 #if defined(_WIN32)
4  #include <winsock2.h>
5 #else
6  #include <sys/select.h>
7  #include <sys/time.h>
8 #endif
9 
10 #include <unordered_map>
11 #include <vector>
12 
18 
20 
21 using std::unordered_map;
22 using std::vector;
23 
26 
27 KernelEventMechanism::KernelEventMechanism() : initialized(false), _psd(nullptr) {
28  // allocate platform specific data
29  _psd = static_cast<void*>(new KernelEventMechanismPSD());
30 
31  //
32  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
33 
34  // clear fd sets
35  FD_ZERO(&psd->rfds);
36  FD_ZERO(&psd->wfds);
37 }
38 
39 KernelEventMechanism::~KernelEventMechanism() {
40  // delete platform specific data
41  delete static_cast<KernelEventMechanismPSD*>(_psd);
42 }
43 
44 void KernelEventMechanism::setSocketInterest(NetworkSocket* socket, const NIOInterest lastInterest, const NIOInterest interest, const void* cookie) {
45  // exit if not initialized
46  if (initialized == false) return;
47 
48  //
49  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
50 
51  // synchronize fd set access
52  psd->fdsMutex.lock();
53 
54  // remove fd from fds
55  psd->fds.erase(socket->descriptor);
56 
57  // remove last read interest
58  if ((lastInterest & NIO_INTEREST_READ) == NIO_INTEREST_READ) {
59  FD_CLR(socket->descriptor, &psd->rfds);
60  }
61  // remove last write interest
62  if ((lastInterest & NIO_INTEREST_WRITE) == NIO_INTEREST_WRITE) {
63  FD_CLR(socket->descriptor, &psd->wfds);
64  }
65 
66  // have interest?
67  auto haveInterest = false;
68 
69  // add read interest
70  if ((interest & NIO_INTEREST_READ) == NIO_INTEREST_READ) {
71  FD_SET(socket->descriptor, &psd->rfds);
72  haveInterest = true;
73  }
74  // add write interest
75  if ((interest & NIO_INTEREST_WRITE) == NIO_INTEREST_WRITE) {
76  FD_SET(socket->descriptor, &psd->wfds);
77  haveInterest = true;
78  }
79 
80  // add fd to fds
81  if (haveInterest == true) {
82  if (socket->descriptor > psd->maxFd) psd->maxFd = socket->descriptor;
83  psd->fds[socket->descriptor] = (void*)cookie;
84  }
85 
86  // done synchronize fd set access
87  psd->fdsMutex.unlock();
88 }
89 
91  // exit if not initialized
92  if (initialized == false) return;
93 
94  //
95  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
96 
97  // synchronize fd set access
98  psd->fdsMutex.lock();
99 
100  // remove fd from fds
101  psd->fds.erase(socket->descriptor);
102 
103  // remove last read interest
104  FD_CLR(socket->descriptor, &psd->rfds);
105  FD_CLR(socket->descriptor, &psd->wfds);
106 
107  // done synchronize fd set access
108  psd->fdsMutex.unlock();
109 }
110 
111 void KernelEventMechanism::initKernelEventMechanism(const unsigned int maxSockets) {
112  // exit if initialized
113  if (initialized == true) return;
114  //
115  initialized = true;
116 }
117 
119  // exit if not initialized
120  if (initialized == false) return;
121  //
122  initialized = false;
123 }
124 
126  // exit if not initialized
127  if (initialized == false) return -1;
128 
129  // platform specific data
130  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
131 
132  // have a timeout of 1ms
133  // as we only can delegate interest changes to the kernel by
134  // select
135  struct timeval timeout = {0, 1L * 1000L};
136 
137  // clone fd sets
138  psd->fdsMutex.lock();
139  fd_set rfds = psd->rfds;
140  fd_set wfds = psd->wfds;
141  psd->fdsMutex.unlock();
142 
143  // run select
144  auto result = select(psd->maxFd + 1, &rfds, &wfds, NULL, &timeout);
145  if (result == -1) {
146  throw NetworkKEMException("select failed");
147  }
148 
149  // compile list of events
150  psd->fdsMutex.lock();
151  psd->events.clear();
152  for (const auto& [fd, cookie]: psd->fds) {
153  if (FD_ISSET(fd, &rfds) != 0) {
154  psd->events.emplace_back(
155  fd,
157  cookie
158  );
159  }
160  if (FD_ISSET(fd, &wfds) != 0) {
161  psd->events.emplace_back(
162  fd,
164  cookie
165  );
166  }
167  }
168  psd->fdsMutex.unlock();
169 
170  //
171  return psd->events.size();
172 }
173 
174 void KernelEventMechanism::decodeKernelEvent(const unsigned int index, NIOInterest &interest, void*& cookie) {
175  // exit if not initialized
176  if (initialized == false) return;
177 
178  // platform specific data
179  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
180 
181  // read interest and cookie from event
182  const auto& event = psd->events[index];
183  interest = event.interest;
184  cookie = event.cookie;
185 }
Interface to kernel event mechanismns.
void shutdownKernelEventMechanism()
Shutdowns the kernel event mechanism.
void removeSocket(NetworkSocket *socket)
Removes a socket.
void setSocketInterest(NetworkSocket *socket, const NIOInterest lastInterest, const NIOInterest interest, const void *cookie)
Sets a non blocked socket io interest.
int doKernelEventMechanism()
Do the kernel event mechanism.
void initKernelEventMechanism(const unsigned int maxSockets)
Initializes the kernel event mechanism.
void decodeKernelEvent(const unsigned int index, NIOInterest &interest, void *&cookie)
Decodes a kernel event.
Kernel event mechanism exception class.
Base class of network sockets.
Definition: NetworkSocket.h:17
Fallback/select kernel event mechanism platform specific data.
void lock()
Locks the mutex, additionally mutex locks will block until other locks have been unlocked.
Definition: Mutex.h:47
const NIOInterest NIO_INTEREST_READ
Definition: NIOInterest.h:12
uint8_t NIOInterest
type definition for network IO interest
Definition: NIOInterest.h:10
const NIOInterest NIO_INTEREST_WRITE
Definition: NIOInterest.h:13