TDME2  1.9.200
KernelEventMechanism.cpp
Go to the documentation of this file.
1 #include <errno.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/epoll.h>
5 #include <unistd.h>
6 
7 #include <vector>
8 
9 #include <tdme/tdme.h>
15 
16 using std::vector;
17 
21 
22 KernelEventMechanism::KernelEventMechanism() : initialized(false), _psd(nullptr) {
23  // allocate platform specific data
24  _psd = static_cast<void*>(new KernelEventMechanismPSD());
25 }
26 
27 KernelEventMechanism::~KernelEventMechanism() {
28  // delete platform specific data
29  delete static_cast<KernelEventMechanismPSD*>(_psd);
30 }
31 
32 void KernelEventMechanism::setSocketInterest(NetworkSocket* socket, const NIOInterest lastInterest, const NIOInterest interest, const void* cookie) {
33  // exit if not initialized
34  if (initialized == false) return;
35 
36  // platform specific data
37  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
38 
39  // setup new event
40  epoll_event event;
41  event.events = EPOLLET;
42  event.data.ptr = (void*)cookie;
43 
44  // handle read interest
45  if ((interest & NIO_INTEREST_READ) == NIO_INTEREST_READ) {
46  event.events|= EPOLLIN;
47  }
48  // handle write interest
49  if ((interest & NIO_INTEREST_WRITE) == NIO_INTEREST_WRITE) {
50  event.events|= EPOLLOUT;
51  }
52 
53  //
54  if (epoll_ctl(
55  psd->ep,
56  lastInterest == NIO_INTEREST_NONE?EPOLL_CTL_ADD:EPOLL_CTL_MOD,
57  socket->descriptor,
58  &event) == -1) {
59  //
60  std::string msg = "Could not add epoll event: ";
61  msg+= strerror(errno);
62  throw NetworkKEMException(msg);
63  }
64 }
65 
67  // exit if not initialized
68  if (initialized == false) return;
69 
70  // platform specific data
71  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
72 
73  //
74  if (epoll_ctl(
75  psd->ep,
76  EPOLL_CTL_DEL,
77  socket->descriptor,
78  nullptr) == -1) {
79  //
80  std::string msg = "Could not remove socket: ";
81  msg+= strerror(errno);
82  throw NetworkKEMException(msg);
83  }
84 }
85 
86 void KernelEventMechanism::initKernelEventMechanism(const unsigned int maxSockets) {
87  // exit if initialized
88  if (initialized == true) return;
89 
90  // platform specific data
91  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
92 
93  // epoll event list, max sockets
94  psd->epEventListMax = maxSockets;
95  psd->epEventList.resize(psd->epEventListMax);
96 
97  // start epoll and get the descriptor
98  psd->ep = epoll_create1(0);
99  if (psd->ep == -1) {
100  std::string msg = "Could not create epoll: ";
101  msg+= strerror(errno);
102  throw NetworkKEMException(msg);
103  }
104 
105  //
106  initialized = true;
107 }
108 
110  // exit if not initialized
111  if (initialized == false) return;
112 
113  // platform specific data
114  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
115 
116  //
117  close(psd->ep);
118 }
119 
121  // exit if not initialized
122  if (initialized == false) return -1;
123 
124  // platform specific data
125  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
126 
127  while (true == true) {
128  //
129  auto events = epoll_wait(psd->ep, psd->epEventList.data(), psd->epEventListMax, 5);
130 
131  // check for error
132  if (events == -1) {
133  if (errno == EINTR) {
134  // epoll_wait was interrupted by system call, so ignore this and restart
135  } else {
136  std::string msg = "epoll_wait failed: ";
137  msg+= strerror(errno);
138  throw NetworkKEMException(msg);
139  }
140  } else {
141  //
142  return events;
143  }
144  }
145 }
146 
147 void KernelEventMechanism::decodeKernelEvent(const unsigned int index, NIOInterest &interest, void*& cookie) {
148  // exit if not initialized
149  if (initialized == false) return;
150 
151  // platform specific data
152  auto psd = static_cast<KernelEventMechanismPSD*>(_psd);
153 
154  //
155  const auto& event = psd->epEventList[index];
156 
157  // we only support user data
158  cookie = (void*)event.data.ptr;
159 
160  // set up interest
161  interest = NIO_INTEREST_NONE;
162  if ((event.events & EPOLLIN) == EPOLLIN) {
163  interest|= NIO_INTEREST_READ;
164  }
165  if ((event.events & EPOLLOUT) == EPOLLOUT) {
166  interest|= NIO_INTEREST_WRITE;
167  }
168 }
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
Linux kernel event mechanism platform specific data.
const NIOInterest NIO_INTEREST_NONE
Definition: NIOInterest.h:11
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