Branch data Line data Source code
1 : : /* Copyright 2009 Savarese Software Research Corporation
2 : : *
3 : : * Licensed under the Apache License, Version 2.0 (the "License");
4 : : * you may not use this file except in compliance with the License.
5 : : * You may obtain a copy of the License at
6 : : *
7 : : * http://www.savarese.com/software/ApacheLicense-2.0
8 : : *
9 : : * Unless required by applicable law or agreed to in writing, software
10 : : * distributed under the License is distributed on an "AS IS" BASIS,
11 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : * See the License for the specific language governing permissions and
13 : : * limitations under the License.
14 : : */
15 : :
16 : : #include <ssrc/wisp/service/detail/FreeBSDEventPort.h>
17 : :
18 : : #include <cerrno>
19 : : #include <cstring>
20 : : #include <unistd.h>
21 : :
22 : : #include <sys/time.h>
23 : :
24 : : __BEGIN_NS_SSRC_WISP_SERVICE
25 : :
26 : : namespace detail {
27 : :
28 : 3 : FreeBSDEventPort::FreeBSDEventPort() SSRC_DECL_THROW(std::runtime_error) :
29 : 3 : _kqueue_fd(::kqueue())
30 : : {
31 [ - + ]: 3 : if(_kqueue_fd < 0) {
32 [ # # # # : 0 : throw std::runtime_error(std::strerror(errno));
# # ]
33 : : }
34 : 3 : }
35 : :
36 : 6 : FreeBSDEventPort::~FreeBSDEventPort() {
37 : 3 : ::close(_kqueue_fd);
38 : 3 : }
39 : :
40 : : // Note: the EventPort abstraction defeats some of the efficiencies
41 : : // of kqueue by forcing event handlers to be registered one at a time.
42 : : // Also it doesn't map nicely onto kqueue, so it's rather klugey and
43 : : // limited in function. A redesign of the EventPort concept should be
44 : : // performed, taking into account the kqueue idiosyncracies.
45 : :
46 : : // returns false only on EACCES
47 : 3 : bool FreeBSDEventPort::add(int fd,
48 : : const events_type events,
49 : : void *user_data,
50 : : const bool once)
51 : : SSRC_DECL_THROW(std::runtime_error)
52 : : {
53 : : event_type event;
54 : :
55 : 3 : EV_SET(&event, fd, EVFILT_READ, EV_ADD, 0, 0, user_data);
56 : :
57 [ - + ]: 3 : if(events & Write) {
58 : 0 : event.filter = EVFILT_WRITE;
59 : : }
60 : :
61 [ - + ]: 3 : if(once) {
62 : 0 : event.flags |= EV_ONESHOT;
63 : : }
64 : :
65 [ + - ]: 3 : int err = ::kevent(_kqueue_fd, &event, 1, 0, 0, 0);
66 : :
67 [ + - ]: 3 : if(err == 0) {
68 : 3 : return true;
69 [ # # # # ]: 0 : } else if(errno != EACCES) {
70 [ # # # # : 0 : throw std::runtime_error(std::strerror(errno));
# # ]
71 : : }
72 : :
73 : 0 : return false;
74 : : }
75 : :
76 : 3 : bool FreeBSDEventPort::remove(int fd, events_type events)
77 : : SSRC_DECL_THROW(std::runtime_error)
78 : : {
79 : 3 : int err = 0;
80 : : event_type event;
81 : :
82 : 3 : EV_SET(&event, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
83 : :
84 [ + - ]: 3 : if(events & Read) {
85 [ + - ]: 3 : err = ::kevent(_kqueue_fd, &event, 1, 0, 0, 0);
86 : : }
87 : :
88 [ - + ]: 3 : if(events & Write) {
89 : 0 : event.filter = EVFILT_WRITE;
90 [ # # ]: 0 : err |= ::kevent(_kqueue_fd, &event, 1, 0, 0, 0);
91 : : }
92 : :
93 [ + - ]: 3 : if(err == 0) {
94 : 3 : return true;
95 [ # # # # ]: 0 : } else if(errno != ENOENT) {
96 [ # # # # : 0 : throw std::runtime_error(std::strerror(errno));
# # ]
97 : : }
98 : :
99 : 0 : return false;
100 : : }
101 : :
102 : 6 : int FreeBSDEventPort::wait(event_type *events, int max_events, int timeout) {
103 : : // For some reason we can't pick up timespec if we include <sys/time.h>
104 : : // in FreeBSD namespace, so we have to use this kluge with a cast.
105 : : ::timespec to;
106 : 6 : ::timespec *pto = &to;
107 : :
108 [ + - ]: 6 : if(timeout > 0) {
109 : 6 : to.tv_sec = timeout / 1000;
110 : 6 : to.tv_nsec = (timeout % 1000)*1000000;
111 [ # # ]: 0 : } else if(timeout == 0) {
112 : 0 : to.tv_sec = 0;
113 : 0 : to.tv_nsec = 0;
114 : : } else
115 : 0 : pto = 0;
116 : :
117 [ + - ]: 6 : return kevent(_kqueue_fd, 0, 0, events, max_events, pto);
118 : : }
119 : :
120 : : }
121 : :
122 [ + - + - ]: 6 : __END_NS_SSRC_WISP_SERVICE
|