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 <unistd.h>
43 #include <sys/epoll.h>
44 
45 #include "exception.hpp"
46 #include "socket.hpp"
47 
48 using std::vector;
49 
50 namespace libsocket {
69 template <typename SocketT>
70 class epollset {
71  public:
72  typedef std::pair<std::vector<SocketT*>, std::vector<SocketT*> >
73  ready_socks;
74 
75  epollset(unsigned int maxevents = 128);
76  epollset(const epollset&) = delete;
77  epollset(epollset&&);
78  ~epollset(void);
79 
80  void add_fd(SocketT& sock, int method);
81  void del_fd(const SocketT& sock);
82  ready_socks wait(int timeout = -1);
83 
84  private:
86  unsigned int maxevents;
88  int epollfd;
90  struct epoll_event* events;
91 };
92 
102 template <typename SocketT>
103 epollset<SocketT>::epollset(unsigned int maxevs)
104  : maxevents(maxevs), events(new struct epoll_event[maxevs]) {
105  epollfd = epoll_create1(0);
106 
107  if (epollfd < 0)
108  throw socket_exception(
109  __FILE__, __LINE__,
110  string("epoll_create1 failed: ") + strerror(errno));
111 }
112 
116 template <typename SocketT>
118  maxevents = new_epollset.maxevents;
119  epollfd = new_epollset.epollfd;
120  events = new_epollset.events;
121 
122  new_epollset.epollfd = -1;
123  new_epollset.events = nullptr;
124 }
125 
126 template <typename SocketT>
128  close(epollfd);
129  delete[] events;
130 }
131 
138 template <typename SocketT>
139 void epollset<SocketT>::add_fd(SocketT& sock, int method) {
140  struct epoll_event new_event;
141 
142  new_event.data.ptr = 0; // ptr is the largest field (8 bytes on 64bit)
143  new_event.events = 0;
144 
145  if (method & LIBSOCKET_READ) new_event.events |= EPOLLIN;
146  if (method & LIBSOCKET_WRITE) new_event.events |= EPOLLOUT;
147 
148  new_event.data.ptr = &sock;
149 
150  if (0 > epoll_ctl(epollfd, EPOLL_CTL_ADD, sock.getfd(), &new_event))
151  throw socket_exception(__FILE__, __LINE__,
152  string("epoll_ctl failed: ") + strerror(errno));
153 }
154 
160 template <typename SocketT>
161 void epollset<SocketT>::del_fd(const SocketT& sock) {
162  if (0 > epoll_ctl(epollfd, EPOLL_CTL_DEL, sock.getfd(), nullptr))
163  throw socket_exception(__FILE__, __LINE__,
164  string("epoll_ctl failed: ") + strerror(errno));
165 }
166 
188 template <typename SocketT>
189 typename epollset<SocketT>::ready_socks epollset<SocketT>::wait(int timeout) {
190  int nfds;
191  ready_socks ready;
192 
193  if (0 > (nfds = epoll_wait(epollfd, events, maxevents, timeout)))
194  throw socket_exception(__FILE__, __LINE__,
195  string("epoll_wait failed: ") + strerror(errno));
196 
197  for (int i = 0; i < nfds; i++) {
198  if (events[i].events == EPOLLIN)
199  ready.first.push_back(static_cast<SocketT*>(events[i].data.ptr));
200  if (events[i].events == EPOLLOUT)
201  ready.second.push_back(static_cast<SocketT*>(events[i].data.ptr));
202  }
203 
204  return ready;
205 }
206 
207 } // namespace libsocket
208 #endif
Class abstracting calls to the epoll API of Linux.
Definition: epoll.hpp:70
unsigned int maxevents
maxevents is passed to epoll_wait.
Definition: epoll.hpp:86
void del_fd(const SocketT &sock)
Remove a file descriptor from an epoll set.
Definition: epoll.hpp:161
int epollfd
The file descriptor used by the epoll API.
Definition: epoll.hpp:88
ready_socks wait(int timeout=-1)
Wait for an event on any file descriptor.
Definition: epoll.hpp:189
struct epoll_event * events
Array of structures, filled on the return of epoll_wait.
Definition: epoll.hpp:90
void add_fd(SocketT &sock, int method)
Add a socket to an epollset.
Definition: epoll.hpp:139
epollset(unsigned int maxevents=128)
Construct a new epollset.
Definition: epoll.hpp:103
Contains libsocket elements.
Definition: dgramclient.hpp:41
This class is instantiated and thrown when an error occurs. If there's an error somewhere in libsocke...
Definition: exception.hpp:52