The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / libev / event.c @ 90fc8d36

History | View | Annotate | Download (9.31 KB)

1 c5183738 Ryan
/*
2
 * libevent compatibility layer
3
 *
4
 * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de>
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without modifica-
8
 * tion, are permitted provided that the following conditions are met:
9
 * 
10
 *   1.  Redistributions of source code must retain the above copyright notice,
11
 *       this list of conditions and the following disclaimer.
12
 * 
13
 *   2.  Redistributions in binary form must reproduce the above copyright
14
 *       notice, this list of conditions and the following disclaimer in the
15
 *       documentation and/or other materials provided with the distribution.
16
 * 
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
 * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
20
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21
 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25
 * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26
 * OF THE POSSIBILITY OF SUCH DAMAGE.
27
 *
28
 * Alternatively, the contents of this file may be used under the terms of
29
 * the GNU General Public License ("GPL") version 2 or any later version,
30
 * in which case the provisions of the GPL are applicable instead of
31
 * the above. If you wish to allow the use of your version of this file
32
 * only under the terms of the GPL and not to allow others to use your
33
 * version of this file under the BSD license, indicate your decision
34
 * by deleting the provisions above and replace them with the notice
35
 * and other provisions required by the GPL. If you do not delete the
36
 * provisions above, a recipient may use your version of this file under
37
 * either the BSD or the GPL.
38
 */
39
40
#include <stddef.h>
41
#include <stdlib.h>
42
#include <assert.h>
43
44
#ifdef EV_EVENT_H
45
# include EV_EVENT_H
46
#else
47
# include "event.h"
48
#endif
49
50
#if EV_MULTIPLICITY
51
# define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base
52
# define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base
53
#else
54
# define dLOOPev
55
# define dLOOPbase
56
#endif
57
58
/* never accessed, will always be cast from/to ev_loop */
59
struct event_base
60
{
61
  int dummy;
62
};
63
64
static struct event_base *ev_x_cur;
65
66
static void
67
ev_tv_set (struct timeval *tv, ev_tstamp at)
68
{
69
  tv->tv_sec  = (long)at;
70
  tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
71
}
72
73
static ev_tstamp
74
ev_tv_get (struct timeval *tv)
75
{
76
  if (tv)
77
    return tv->tv_sec + tv->tv_usec * 1e-6;
78
  else
79
    return -1.;
80
}
81
82
#define EVENT_STRINGIFY(s) # s
83
#define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b)
84
85
const char *event_get_version (void)
86
{
87
  /* returns ABI, not API or library, version */
88
  return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
89
}
90
91
const char *event_get_method (void)
92
{
93
  return "libev";
94
}
95
96
void *event_init (void)
97
{
98
#if EV_MULTIPLICITY
99
  if (ev_x_cur)
100
    ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);
101
  else
102
    ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);
103
#else
104
  assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur));
105
106
  ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);
107
#endif
108
109
  return ev_x_cur;
110
}
111
112
void event_base_free (struct event_base *base)
113
{
114
  dLOOPbase;
115
116
#if EV_MULTIPLICITY
117
  if (ev_default_loop (EVFLAG_AUTO) != loop)
118
    ev_loop_destroy (loop);
119
#endif
120
}
121
122
int event_dispatch (void)
123
{
124
  return event_base_dispatch (ev_x_cur);
125
}
126
127
#ifdef EV_STANDALONE
128
void event_set_log_callback (event_log_cb cb)
129
{
130
  /* nop */
131
}
132
#endif
133
134
int event_loop (int flags)
135
{
136
  return event_base_loop (ev_x_cur, flags);
137
}
138
139
int event_loopexit (struct timeval *tv)
140
{
141
  return event_base_loopexit (ev_x_cur, tv);
142
}
143
144
static void
145
ev_x_cb (struct event *ev, int revents)
146
{
147
  revents &= EV_READ | EV_WRITE | EV_TIMEOUT | EV_SIGNAL;
148
149
  ev->ev_res = revents;
150
  ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
151
}
152
153
static void
154
ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents)
155
{
156
  struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));
157
158
  if (revents & EV_ERROR)
159
    event_del (ev);
160
161
  ev_x_cb (ev, revents);
162
}
163
164
static void
165
ev_x_cb_io (EV_P_ struct ev_io *w, int revents)
166
{
167
  struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
168
169
  if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))
170
    event_del (ev);
171
172
  ev_x_cb (ev, revents);
173
}
174
175
static void
176
ev_x_cb_to (EV_P_ struct ev_timer *w, int revents)
177
{
178
  struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));
179
180
  event_del (ev);
181
182
  ev_x_cb (ev, revents);
183
}
184
185
void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
186
{
187
  if (events & EV_SIGNAL)
188
    ev_init (&ev->iosig.sig, ev_x_cb_sig);
189
  else
190
    ev_init (&ev->iosig.io, ev_x_cb_io);
191
192
  ev_init (&ev->to, ev_x_cb_to);
193
194
  ev->ev_base     = ev_x_cur; /* not threadsafe, but it's how libevent works */
195
  ev->ev_fd       = fd;
196
  ev->ev_events   = events;
197
  ev->ev_pri      = 0;
198
  ev->ev_callback = cb;
199
  ev->ev_arg      = arg;
200
  ev->ev_res      = 0;
201
  ev->ev_flags    = EVLIST_INIT;
202
}
203
204
int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
205
{
206
  return event_base_once (ev_x_cur, fd, events, cb, arg, tv);
207
}
208
209
int event_add (struct event *ev, struct timeval *tv)
210
{
211
  dLOOPev;
212
213
  if (ev->ev_events & EV_SIGNAL)
214
    {
215
      if (!ev_is_active (&ev->iosig.sig))
216
        {
217
          ev_signal_set (&ev->iosig.sig, ev->ev_fd);
218
          ev_signal_start (EV_A_ &ev->iosig.sig);
219
220
          ev->ev_flags |= EVLIST_SIGNAL;
221
        }
222
    }
223
  else if (ev->ev_events & (EV_READ | EV_WRITE))
224
    {
225
      if (!ev_is_active (&ev->iosig.io))
226
        {
227
          ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));
228
          ev_io_start (EV_A_ &ev->iosig.io);
229
230
          ev->ev_flags |= EVLIST_INSERTED;
231
        }
232
    }
233
234
  if (tv)
235
    {
236
      ev->to.repeat = ev_tv_get (tv);
237
      ev_timer_again (EV_A_ &ev->to);
238
      ev->ev_flags |= EVLIST_TIMEOUT;
239
    }
240
  else
241
    {
242
      ev_timer_stop (EV_A_ &ev->to);
243
      ev->ev_flags &= ~EVLIST_TIMEOUT;
244
    }
245
246
  ev->ev_flags |= EVLIST_ACTIVE;
247
248
  return 0;
249
}
250
251
int event_del (struct event *ev)
252
{
253
  dLOOPev;
254
255
  if (ev->ev_events & EV_SIGNAL)
256
    ev_signal_stop (EV_A_ &ev->iosig.sig);
257
  else if (ev->ev_events & (EV_READ | EV_WRITE))
258
    ev_io_stop (EV_A_ &ev->iosig.io);
259
260
  if (ev_is_active (&ev->to))
261
    ev_timer_stop (EV_A_ &ev->to);
262
263
  ev->ev_flags = EVLIST_INIT;
264
265
  return 0;
266
}
267
268
void event_active (struct event *ev, int res, short ncalls)
269
{
270
  dLOOPev;
271
272
  if (res & EV_TIMEOUT)
273
    ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);
274
275
  if (res & EV_SIGNAL)
276
    ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);
277
278
  if (res & (EV_READ | EV_WRITE))
279
    ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));
280
}
281
282
int event_pending (struct event *ev, short events, struct timeval *tv)
283
{
284
  short revents = 0;
285
  dLOOPev;
286
287
  if (ev->ev_events & EV_SIGNAL)
288
    {
289
      /* sig */
290
      if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))
291
        revents |= EV_SIGNAL;
292
    }
293
  else if (ev->ev_events & (EV_READ | EV_WRITE))
294
    {
295
      /* io */
296
      if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))
297
        revents |= ev->ev_events & (EV_READ | EV_WRITE);
298
    }
299
300
  if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))
301
    {
302
      revents |= EV_TIMEOUT;
303
304
      if (tv)
305
        ev_tv_set (tv, ev_now (EV_A)); /* not sure if this is right :) */
306
    }
307
308
  return events & revents;
309
}
310
311
int event_priority_init (int npri)
312
{
313
  return event_base_priority_init (ev_x_cur, npri);
314
}
315
316
int event_priority_set (struct event *ev, int pri)
317
{
318
  ev->ev_pri = pri;
319
320
  return 0;
321
}
322
323
int event_base_set (struct event_base *base, struct event *ev)
324
{
325
  ev->ev_base = base;
326
327
  return 0;
328
}
329
330
int event_base_loop (struct event_base *base, int flags)
331
{
332
  dLOOPbase;
333
334
  ev_loop (EV_A_ flags);
335
336
  return 0;
337
}
338
339
int event_base_dispatch (struct event_base *base)
340
{
341
  return event_base_loop (base, 0);
342
}
343
344
static void
345
ev_x_loopexit_cb (int revents, void *base)
346
{
347
  dLOOPbase;
348
349
  ev_unloop (EV_A_ EVUNLOOP_ONE);
350
}
351
352
int event_base_loopexit (struct event_base *base, struct timeval *tv)
353
{
354
  ev_tstamp after = ev_tv_get (tv);
355
  dLOOPbase;
356
357
  ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base);
358
359
  return 0;
360
}
361
362
struct ev_x_once
363
{
364
  int fd;
365
  void (*cb)(int, short, void *);
366
  void *arg;
367
};
368
369
static void
370
ev_x_once_cb (int revents, void *arg)
371
{
372
  struct ev_x_once *once = (struct ev_x_once *)arg;
373
374
  once->cb (once->fd, (short)revents, once->arg);
375
  free (once);
376
}
377
378
int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
379
{
380
  struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once));
381
  dLOOPbase;
382
383
  if (!once)
384
    return -1;
385
386
  once->fd  = fd;
387
  once->cb  = cb;
388
  once->arg = arg;
389
390
  ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once);
391
392
  return 0;
393
}
394
395
int event_base_priority_init (struct event_base *base, int npri)
396
{
397
  /*dLOOPbase;*/
398
399
  return 0;
400
}