Skip to content

Instantly share code, notes, and snippets.

@DamonHao
Last active November 27, 2023 12:35
Show Gist options
  • Save DamonHao/df87e727a0299c07fce3 to your computer and use it in GitHub Desktop.
Save DamonHao/df87e727a0299c07fce3 to your computer and use it in GitHub Desktop.
libev example
/*
* test_libv.c
*
* Created on: May 30, 2014
* Author: damonhao
*/
// a single header file is required
#include <ev.h>
#include <stdio.h> // for puts
// every watcher type has its own typedef'd struct
// with the name ev_TYPE
ev_io stdin_watcher;
ev_timer timeout_watcher;
// all watcher callbacks have a similar signature
// this callback is called when data is readable on stdin
static void
stdin_cb (EV_P_ ev_io *w, int revents)
{
puts ("stdin ready");
// for one-shot events, one must manually stop the watcher
// with its corresponding stop function.
ev_io_stop (EV_A_ w);
// this causes all nested ev_run's to stop iterating
ev_break (EV_A_ EVBREAK_ALL);
}
// another callback, this time for a time-out
static void
timeout_cb (EV_P_ ev_timer *w, int revents)
{
puts ("timeout");
// this causes the innermost ev_run to stop iterating
ev_break (EV_A_ EVBREAK_ONE);
}
int
main (void)
{
// use the default event loop unless you have special needs
struct ev_loop *loop = EV_DEFAULT;
// initialise an io watcher, then start it
// this one will watch for stdin to become readable
ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
ev_io_start (loop, &stdin_watcher);
// initialise a timer watcher, then start it
// simple non-repeating 5.5 second timeout
ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
ev_timer_start (loop, &timeout_watcher);
// now wait for events to arrive
ev_run (loop, 0);
// break was called, so exit
return 0;
}
/*
* test_ev_child.c
*
* Created on: Jun 2, 2014
* Author: damonhao
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h> // for puts
#include <ev.h>
ev_child cw;
static void child_cb(EV_P_ ev_child *w, int revents)
{
ev_child_stop(EV_A_ w);
printf("process %d exited with status %x\n", w->rpid, w->rstatus);
}
int main()
{
pid_t pid = fork();
if (pid < 0)
{
// error
puts("fork error");
return 0;
}
else if (pid == 0)
{
// the forked child executes here
exit(1);
}
else
{
puts("in parent");
struct ev_loop *loop = EV_DEFAULT;
ev_child_init(&cw, child_cb, pid, 0);
ev_child_start(loop, &cw);
ev_run(loop, 0);
}
return 0;
}
/*output:
in parent
process 4472 exited with status 100
*/
/*
* test_ev_once.c
*
* Created on: Jun 2, 2014
* Author: damonhao
*/
/* receive io event or timeout. They may happen at the same time,
you probably should give io events precedence.*/
#include <unistd.h>
#include <stdio.h> // for puts
#include <ev.h>
static void stdin_ready(int revents, void *arg)
{
if (revents & EV_READ)
{
/* stdin might have data for us, joy! */
puts("stdin io event");
}
else if (revents & EV_TIMER)
{
/* doh, nothing entered */
puts("timeout");
}
}
int main()
{
puts("in main");
struct ev_loop *loop = EV_DEFAULT;
ev_once (loop, STDIN_FILENO, EV_READ, 5., stdin_ready, NULL);
ev_run(loop, 0);
return 0;
}
/*
* test_libev_withthread.c
*
* Created on: Jun 4, 2014
* Author: damonhao
*/
#include <ev.h>
#include <pthread.h>
typedef struct
{
pthread_mutex_t lock; /* global loop lock */
ev_async async_w;
pthread_t tid;
pthread_cond_t invoke_cv;
} userdata;
static void async_cb(EV_P_ ev_async *w, int revents)
{
// just used for the side effects
}
static void l_release(EV_P)
{
userdata *u = ev_userdata(EV_A);
pthread_mutex_unlock(&u->lock);
}
static void l_acquire(EV_P)
{
userdata *u = ev_userdata(EV_A);
pthread_mutex_lock(&u->lock);
}
void *l_run(void *thr_arg)
{
struct ev_loop *loop = (struct ev_loop *) thr_arg;
l_acquire(EV_A);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
ev_run(EV_A_ 0);
l_release(EV_A);
return 0;
}
static void l_invoke(EV_P)
{
userdata *u = ev_userdata(EV_A);
while (ev_pending_count(EV_A))
{
wake_up_other_thread_in_some_magic_or_not_so_magic_way();
pthread_cond_wait(&u->invoke_cv, &u->lock);
}
}
void prepare_loop(EV_P)
{
// for simplicity, we use a static userdata struct.
static userdata u;
ev_async_init(&u->async_w, async_cb);
ev_async_start(EV_A_&u->async_w);
pthread_mutex_init(&u->lock, 0);
pthread_cond_init(&u->invoke_cv, 0);
// now associate this with the loop
ev_set_userdata(EV_A_ u);
ev_set_invoke_pending_cb(EV_A_ l_invoke);
ev_set_loop_release_cb(EV_A_ l_release, l_acquire);
// then create the thread running ev_run
pthread_create(&u->tid, 0, l_run, EV_A);
}
static void real_invoke_pending(EV_P)
{
userdata *u = ev_userdata(EV_A);
pthread_mutex_lock(&u->lock);
ev_invoke_pending(EV_A);
pthread_cond_signal(&u->invoke_cv);
pthread_mutex_unlock(&u->lock);
}
static void timeout_cb (EV_P_ ev_timer *w, int revents)
{
puts ("timeout");
// this causes the innermost ev_run to stop iterating
ev_break (EV_A_ EVBREAK_ONE);
}
int main()
{
struct ev_loop *loop = EV_DEFAULT;
ev_timer timeout_watcher;
userdata *u = ev_userdata (EV_A);
ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
pthread_mutex_lock (&u->lock);
ev_timer_start (EV_A_ &timeout_watcher);
ev_async_send (EV_A_ &u->async_w);
pthread_mutex_unlock (&u->lock);
}
/*
* test_watcher_with_customerdata.c
*
* Created on: Jun 3, 2014
* Author: damonhao
*/
// a single header file is required
#include <ev.h>
#include <unistd.h>
#include <stdio.h> // for puts
#include <string.h>
#define BUFFERSIZE 50
struct my_io
{
ev_io io_watcher_;
int data_;
};
void my_io_cb(struct ev_loop *loop, ev_io *w, int revents)
{
struct my_io * custom_watcher = (struct my_io *) w;
char buf[BUFFERSIZE];
if (gets(buf) != NULL) //FIXME: note the size of buf, read is unsafe now;
{
if (strcmp("end", buf) != 0)
{
printf("read data times: %d\n", custom_watcher->data_);
custom_watcher->data_++;
puts(buf);
}
else
{
ev_io_stop(loop, w);
ev_break(loop, EVBREAK_ALL);
}
}
else
{
puts("read error");
}
}
int main()
{
puts("in main");
struct ev_loop *loop = EV_DEFAULT;
struct my_io custom_watcher;
custom_watcher.data_ = 1;
ev_io_init(&custom_watcher.io_watcher_, my_io_cb, STDIN_FILENO, EV_READ);
ev_io_start(loop, &custom_watcher.io_watcher_);
ev_run(loop, 0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment