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
/*
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
}
401