libsocket
epoll.hpp
Go to the documentation of this file.
1 #ifndef LIBSOCKET_EPOLL_H_E58EF2DF7057FA0C7A95D6E753414229
2 #define LIBSOCKET_EPOLL_H_E58EF2DF7057FA0C7A95D6E753414229
3 
4 /*
5  The committers of the libsocket project, all rights reserved
6  (c) 2014, dermesser <lbo@spheniscida.de>
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10 
11  1. Redistributions of source code must retain the above copyright notice,
12  this list of conditions and the following disclaimer.
13  2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY
18  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
21  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 */
29 
38 #include <cstring>
39 #include <memory>
40 #include <vector>
41 
42 #include <sys/epoll.h>
43 
44 #include "exception.hpp"
45 #include "socket.hpp"
46 
47 using std::vector;
48 
49 namespace libsocket {
68 template <typename SocketT>
69 class epollset {
70  public:
71  typedef std::pair<std::vector<SocketT*>, std::vector<SocketT*> >
72  ready_socks;
73 
74  epollset(unsigned int maxevents = 128);
75  epollset(const epollset&) = delete;
76  epollset(epollset&&);
77  ~epollset(void);
78 
79  void add_fd(SocketT& sock, int method);
80  void del_fd(const SocketT& sock);
81  ready_socks wait(int timeout = -1);
82 
83  private:
85  unsigned int maxevents;
87  int epollfd;
89  struct epoll_event* events;
90 };
91 
101 template <typename SocketT>
102 epollset<SocketT>::epollset(unsigned int maxevs)
103  : maxevents(maxevs), events(new struct epoll_event[maxevs]) {
104  epollfd = epoll_create1(0);
105 
106  if (epollfd < 0)
107  throw socket_exception(
108  __FILE__, __LINE__,
109  string("epoll_create1 failed: ") + strerror(errno));
110 }
111 
115 template <typename SocketT>
117  maxevents = new_epollset.maxevents;
118  epollfd = new_epollset.epollfd;
119  events = new_epollset.events;
120 
121  new_epollset.epollfd = -1;
122  new_epollset.events = nullptr;
123 }
124 
125 template <typename SocketT>
127  close(epollfd);
128  delete[] events;
129 }
130 
137 template <typename SocketT>
138 void epollset<SocketT>::add_fd(SocketT& sock, int method) {
139  struct epoll_event new_event;
140 
141  new_event.data.ptr = 0; // ptr is the largest field (8 bytes on 64bit)
142  new_event.events = 0;
143 
144  if (method & LIBSOCKET_READ) new_event.events |= EPOLLIN;
145  if (method & LIBSOCKET_WRITE) new_event.events |= EPOLLOUT;
146 
147  new_event.data.ptr = &sock;
148 
149  if (0 > epoll_ctl(epollfd, EPOLL_CTL_ADD, sock.getfd(), &new_event))
150  throw socket_exception(__FILE__, __LINE__,
151  string("epoll_ctl failed: ") + strerror(errno));
152 }
153 
159 template <typename SocketT>
160 void epollset<SocketT>::del_fd(const SocketT& sock) {
161  if (0 > epoll_ctl(epollfd, EPOLL_CTL_DEL, sock.getfd(), nullptr))
162  throw socket_exception(__FILE__, __LINE__,
163  string("epoll_ctl failed: ") + strerror(errno));
164 }
165 
187 template <typename SocketT>
188 typename epollset<SocketT>::ready_socks epollset<SocketT>::wait(int timeout) {
189  int nfds;
190  ready_socks ready;
191 
192  if (0 > (nfds = epoll_wait(epollfd, events, maxevents, timeout)))
193  throw socket_exception(__FILE__, __LINE__,
194  string("epoll_wait failed: ") + strerror(errno));
195 
196  for (int i = 0; i < nfds; i++) {
197  if (events[i].events == EPOLLIN)
198  ready.first.push_back(static_cast<SocketT*>(events[i].data.ptr));
199  if (events[i].events == EPOLLOUT)
200  ready.second.push_back(static_cast<SocketT*>(events[i].data.ptr));
201  }
202 
203  return ready;
204 }
205 
206 } // namespace libsocket
207 #endif
Class abstracting calls to the epoll API of Linux.
Definition: epoll.hpp:69
Contains libsocket elements.
Definition: dgramclient.hpp:41
void add_fd(SocketT &sock, int method)
Add a socket to an epollset.
Definition: epoll.hpp:138
This class is instantiated and thrown when an error occurs. If there's an error somewhere in libsocke...
Definition: exception.hpp:52
ready_socks wait(int timeout=-1)
Wait for an event on any file descriptor.
Definition: epoll.hpp:188
epollset(unsigned int maxevents=128)
Construct a new epollset.
Definition: epoll.hpp:102
unsigned int maxevents
maxevents is passed to epoll_wait.
Definition: epoll.hpp:85
int epollfd
The file descriptor used by the epoll API.
Definition: epoll.hpp:87
void del_fd(const SocketT &sock)
Remove a file descriptor from an epoll set.
Definition: epoll.hpp:160
struct epoll_event * events
Array of structures, filled on the return of epoll_wait.
Definition: epoll.hpp:89