#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "testlib.h"
#include "mevent.h"
typedef enum {
CB_NONE,
CB_READ,
CB_TIMER,
} lastwake_t;
static lastwake_t lastwake = CB_NONE;
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
static struct mevent *read_event;
static void
munch(int fd, enum ev_type ev, void *arg)
{
ssize_t nbytes;
char buf[32] = { 0 };
int err;
if ((nbytes = read(fd, buf, sizeof (buf))) < 0) {
FAIL_ERRNO("bad read");
}
VERBOSE(("read %ld bytes '%s'", nbytes, buf));
err = mevent_disable(read_event);
ASSERT_INT_EQ(("mevent_disable: ", strerror(err)), err, 0);
pthread_mutex_lock(&mtx);
ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_NONE);
lastwake = CB_READ;
pthread_cond_signal(&cv);
VERBOSE(("wakeup"));
pthread_mutex_unlock(&mtx);
}
static void
tick(int ms, enum ev_type ev, void *arg)
{
pthread_mutex_lock(&mtx);
ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_READ);
lastwake = CB_TIMER;
pthread_cond_signal(&cv);
VERBOSE(("wakeup"));
pthread_mutex_unlock(&mtx);
}
int
main(int argc, const char *argv[])
{
int pipefds[2];
struct mevent *timer;
ssize_t written;
char *msgs[] = { "first", "second" };
char *msg;
start_test(argv[0], 5);
start_event_thread();
if (pipe(pipefds) != 0) {
FAIL_ERRNO("pipe");
}
if (fcntl(pipefds[0], F_SETFL, O_NONBLOCK) != 0) {
FAIL_ERRNO("set pipe nonblocking");
}
msg = msgs[0];
read_event = mevent_add(pipefds[0], EVF_READ, munch, msg);
ASSERT_PTR_NEQ(("mevent_add pipefd"), read_event, NULL);
pthread_mutex_lock(&mtx);
written = write(pipefds[1], msg, strlen(msg));
if (written < 0) {
FAIL_ERRNO("bad write");
}
ASSERT_INT64_EQ(("write '%s' failed", msg), written, strlen(msg));
pthread_cond_wait(&cv, &mtx);
ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_READ);
pthread_mutex_unlock(&mtx);
msg = msgs[1];
timer = mevent_add(50, EVF_TIMER, tick, msg);
ASSERT_PTR_NEQ(("mevent_add timer"), timer, NULL);
pthread_mutex_lock(&mtx);
written = write(pipefds[1], msg, strlen(msg));
if (written < 0) {
FAIL_ERRNO("bad write");
}
ASSERT_INT64_EQ(("write '%s' failed", msg), written, strlen(msg));
pthread_cond_wait(&cv, &mtx);
ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_TIMER);
pthread_mutex_unlock(&mtx);
PASS();
}