/*****************************************************************************/
+static void (*syserr_cb)(void);
+
+void ev_set_syserr_cb (void (*cb)(void))
+{
+ syserr_cb = cb;
+}
+
+static void
+syserr (void)
+{
+ if (syserr_cb)
+ syserr_cb ();
+ else
+ {
+ perror ("libev");
+ abort ();
+ }
+}
+
+static void *(*alloc)(void *ptr, long size);
+
+void ev_set_allocator (void *(*cb)(void *ptr, long size))
+{
+ alloc = cb;
+}
+
+static void *
+ev_realloc (void *ptr, long size)
+{
+ ptr = alloc ? alloc (ptr, size) : realloc (ptr, size);
+
+ if (!ptr && size)
+ {
+ fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
+ abort ();
+ }
+
+ return ptr;
+}
+
+#define ev_malloc(size) ev_realloc (0, (size))
+#define ev_free(ptr) ev_realloc ((ptr), 0)
+
+/*****************************************************************************/
+
typedef struct
{
WL head;
#define array_roundsize(base,n) ((n) | 4 & ~3)
-#define array_needsize(base,cur,cnt,init) \
- if (expect_false ((cnt) > cur)) \
- { \
- int newcnt = cur; \
- do \
- { \
- newcnt = array_roundsize (base, newcnt << 1); \
- } \
- while ((cnt) > newcnt); \
- \
- base = realloc (base, sizeof (*base) * (newcnt)); \
- init (base + cur, newcnt - cur); \
- cur = newcnt; \
+#define array_needsize(base,cur,cnt,init) \
+ if (expect_false ((cnt) > cur)) \
+ { \
+ int newcnt = cur; \
+ do \
+ { \
+ newcnt = array_roundsize (base, newcnt << 1); \
+ } \
+ while ((cnt) > newcnt); \
+ \
+ base = ev_realloc (base, sizeof (*base) * (newcnt)); \
+ init (base + cur, newcnt - cur); \
+ cur = newcnt; \
}
#define array_slim(stem) \
if (stem ## max < array_roundsize (stem ## cnt >> 2)) \
{ \
stem ## max = array_roundsize (stem ## cnt >> 1); \
- base = realloc (base, sizeof (*base) * (stem ## max)); \
+ base = ev_realloc (base, sizeof (*base) * (stem ## max)); \
fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\
}
#define array_free(stem, idx) \
- free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0;
+ ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0;
/*****************************************************************************/
struct ev_loop *
ev_loop_new (int methods)
{
- struct ev_loop *loop = (struct ev_loop *)calloc (1, sizeof (struct ev_loop));
+ struct ev_loop *loop = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
+
+ memset (loop, 0, sizeof (struct ev_loop));
loop_init (EV_A_ methods);
ev_loop_destroy (EV_P)
{
loop_destroy (EV_A);
- free (loop);
+ ev_free (loop);
}
void
ev_io_stop (EV_A_ &once->io);
ev_timer_stop (EV_A_ &once->to);
- free (once);
+ ev_free (once);
cb (revents, arg);
}
void
ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
{
- struct ev_once *once = malloc (sizeof (struct ev_once));
+ struct ev_once *once = ev_malloc (sizeof (struct ev_once));
if (!once)
cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMEOUT, arg);
ev_tstamp ev_time (void);
+/* Sets the allocation function to use, works like realloc.
+ * It is used to allocate and free memory.
+ * If it returns zero when memory needs to be allocated, the library might abort
+ * or take some potentially destructive action.
+ * The default is your system realloc function.
+ */
+void ev_set_allocator (void *(*cb)(void *ptr, long size));
+
+/* set the callback function to call on a
+ * retryable syscall error
+ * (such as failed select, poll, epoll_wait)
+ */
+void ev_set_syserr_cb (void (*cb)(void));
+
# if EV_MULTIPLICITY
/* the default loop is the only one that handles signals and child watchers */
/* you can call this as often as you like */
static void
epoll_poll (EV_P_ ev_tstamp timeout)
{
- int eventcnt = epoll_wait (epoll_fd, epoll_events, epoll_eventmax, ceil (timeout * 1000.));
int i;
+ int eventcnt = epoll_wait (epoll_fd, epoll_events, epoll_eventmax, ceil (timeout * 1000.));
if (eventcnt < 0)
- return;
+ {
+ if (errno != EINTR)
+ syserr ();
+
+ return;
+ }
for (i = 0; i < eventcnt; ++i)
fd_event (
/* if the receive array was full, increase its size */
if (expect_false (eventcnt == epoll_eventmax))
{
- free (epoll_events);
+ ev_free (epoll_events);
epoll_eventmax = array_roundsize (epoll_events, epoll_eventmax << 1);
- epoll_events = malloc (sizeof (struct epoll_event) * epoll_eventmax);
+ epoll_events = ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
}
}
method_poll = epoll_poll;
epoll_eventmax = 64; /* intiial number of events receivable per poll */
- epoll_events = malloc (sizeof (struct epoll_event) * epoll_eventmax);
+ epoll_events = ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
return EVMETHOD_EPOLL;
}
{
close (epoll_fd);
- free (epoll_events);
+ ev_free (epoll_events);
}
static void
kqueue_changecnt = 0;
if (res < 0)
- return;
+ {
+ if (errno != EINTR)
+ syserr ();
+
+ return;
+ }
for (i = 0; i < res; ++i)
{
if (expect_false (res == kqueue_eventmax))
{
- free (kqueue_events);
+ ev_free (kqueue_events);
kqueue_eventmax = array_roundsize (kqueue_events, kqueue_eventmax << 1);
- kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax);
+ kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
}
}
method_poll = kqueue_poll;
kqueue_eventmax = 64; /* intiial number of events receivable per poll */
- kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax);
+ kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
kqueue_changes = 0;
kqueue_changemax = 0;
{
close (kqueue_fd);
- free (kqueue_events);
- free (kqueue_changes);
+ ev_free (kqueue_events);
+ ev_free (kqueue_changes);
}
static void
static void
poll_poll (EV_P_ ev_tstamp timeout)
{
+ int i;
int res = poll (polls, pollcnt, ceil (timeout * 1000.));
- if (res > 0)
- {
- int i;
-
- for (i = 0; i < pollcnt; ++i)
- fd_event (
- EV_A_
- polls [i].fd,
- (polls [i].revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
- | (polls [i].revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
- );
- }
- else if (res < 0)
+ if (res < 0)
{
if (errno == EBADF)
fd_ebadf (EV_A);
- else if (errno == ENOMEM)
+ else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
+ else if (errno != EINTR)
+ syserr ();
+
+ return;
}
+
+ for (i = 0; i < pollcnt; ++i)
+ fd_event (
+ EV_A_
+ polls [i].fd,
+ (polls [i].revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
+ | (polls [i].revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
+ );
}
static int
static void
poll_destroy (EV_P)
{
- free (pollidxs);
- free (polls);
+ ev_free (pollidxs);
+ ev_free (polls);
}
{
int new_max = (fd >> 5) + 1;
- vec_ri = (unsigned char *)realloc (vec_ri, new_max * 4);
- vec_ro = (unsigned char *)realloc (vec_ro, new_max * 4); /* could free/malloc */
- vec_wi = (unsigned char *)realloc (vec_wi, new_max * 4);
- vec_wo = (unsigned char *)realloc (vec_wo, new_max * 4); /* could free/malloc */
+ vec_ri = (unsigned char *)ev_realloc (vec_ri, new_max * 4);
+ vec_ro = (unsigned char *)ev_realloc (vec_ro, new_max * 4); /* could free/malloc */
+ vec_wi = (unsigned char *)ev_realloc (vec_wi, new_max * 4);
+ vec_wo = (unsigned char *)ev_realloc (vec_wo, new_max * 4); /* could free/malloc */
for (; vec_max < new_max; ++vec_max)
((uint32_t *)vec_ri)[vec_max] =
static void
select_poll (EV_P_ ev_tstamp timeout)
{
+ int word, offs;
struct timeval tv;
int res;
res = select (vec_max * 32, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
- if (res > 0)
- {
- int word, offs;
-
- for (word = vec_max; word--; )
- {
- if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word])
- for (offs = 4; offs--; )
- {
- int idx = word * 4 + offs;
- unsigned char byte_r = vec_ro [idx];
- unsigned char byte_w = vec_wo [idx];
- int bit;
-
- if (byte_r | byte_w)
- for (bit = 8; bit--; )
- {
- int events = 0;
- events |= byte_r & (1 << bit) ? EV_READ : 0;
- events |= byte_w & (1 << bit) ? EV_WRITE : 0;
-
- if (events)
- fd_event (EV_A_ idx * 8 + bit, events);
- }
- }
- }
- }
- else if (res < 0)
+ if (res < 0)
{
if (errno == EBADF)
fd_ebadf (EV_A);
- else if (errno == ENOMEM)
+ else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
+ else if (errno != EINTR)
+ syserr ();
+
+ return;
+ }
+
+ for (word = vec_max; word--; )
+ {
+ if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word])
+ for (offs = 4; offs--; )
+ {
+ int idx = word * 4 + offs;
+ unsigned char byte_r = vec_ro [idx];
+ unsigned char byte_w = vec_wo [idx];
+ int bit;
+
+ if (byte_r | byte_w)
+ for (bit = 8; bit--; )
+ {
+ int events = 0;
+ events |= byte_r & (1 << bit) ? EV_READ : 0;
+ events |= byte_w & (1 << bit) ? EV_WRITE : 0;
+
+ if (events)
+ fd_event (EV_A_ idx * 8 + bit, events);
+ }
+ }
}
}
static void
select_destroy (EV_P)
{
- free (vec_ri);
- free (vec_ro);
- free (vec_wi);
- free (vec_wo);
+ ev_free (vec_ri);
+ ev_free (vec_ro);
+ ev_free (vec_wi);
+ ev_free (vec_wo);
}