-
Notifications
You must be signed in to change notification settings - Fork 133
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
2,362 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
cmake_minimum_required(VERSION 2.8) | ||
|
||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I.. -Iinclude -std=c++11 -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter -D_XOPEN_SOURCE -lrt -D_GNU_SOURCE") | ||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I.. -Iinclude -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter -D_XOPEN_SOURCE -lrt -D_GNU_SOURCE") | ||
|
||
project(eloop_mini) | ||
|
||
set(ELOOP_LIB eloop_mini) | ||
set(ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) | ||
set(BUILD_DIR ${ROOT_DIR}/build/) | ||
|
||
message("Root dir: " ${ROOT_DIR}) | ||
|
||
file(GLOB SOURCES src/*.c) | ||
include_directories(${ROOT_DIR}/include) | ||
|
||
|
||
add_library(${ELOOP_LIB} SHARED ${SOURCES}) | ||
set_target_properties(${ELOOP_LIB} | ||
PROPERTIES | ||
LIBRARY_OUTPUT_DIRECTORY ${BUILD_DIR} | ||
) | ||
|
||
file(GLOB INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h") | ||
install(FILES ${INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#ifndef __ELOOP_H__ | ||
#define __ELOOP_H__ | ||
|
||
#ifndef _GNU_SOURCE | ||
#define _GNU_SOURCE | ||
#endif | ||
|
||
#include <inttypes.h> | ||
#include <stdbool.h> | ||
|
||
#define INVALID_ID 0 | ||
#define PRIid PRIuPTR | ||
typedef uintptr_t eloop_id_t; | ||
|
||
typedef void (*task_cb_t)(void *ctx); | ||
typedef void (*fd_cb_t)(void *ctx, uint32_t event_mask); | ||
|
||
int eloop_init(void); | ||
void eloop_exit(void); | ||
void eloop_run(void); | ||
void eloop_stop(void); | ||
|
||
eloop_id_t eloop_timer_add(task_cb_t cb, | ||
void *ctx, | ||
unsigned int expires_ms, | ||
unsigned int period_ms); | ||
void eloop_timer_delete(eloop_id_t timer_id); | ||
int eloop_timer_start(eloop_id_t timer_id); | ||
int eloop_timer_stop(eloop_id_t timer_id); | ||
|
||
#define ELOOP_FD_EVENT_ERROR 0x01 | ||
#define ELOOP_FD_EVENT_HUP 0x02 | ||
#define ELOOP_FD_EVENT_READ 0x04 | ||
#define ELOOP_FD_EVENT_WRITE 0x08 | ||
|
||
eloop_id_t eloop_handler_add_fd(int fd, fd_cb_t cb, void *ctx); | ||
void eloop_handler_remove_fd(eloop_id_t fd_id); | ||
|
||
#endif /* __ELOOP_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#include <eloop.h> | ||
|
||
#include "syncer.h" | ||
#include "scheduler.h" | ||
#include "fd.h" | ||
|
||
#define MAX_FD_EVENTS 512 | ||
|
||
struct { | ||
struct syncer *syncer; | ||
struct scheduler *scheduler; | ||
struct fd_handler *fd_handler; | ||
bool running; | ||
} eloop_ctx; | ||
|
||
eloop_id_t eloop_timer_add(task_cb_t cb, | ||
void *ctx, | ||
unsigned int expires_ms, | ||
unsigned int period_ms) | ||
{ | ||
return scheduler_timer_new(eloop_ctx.scheduler, | ||
cb, ctx, expires_ms, period_ms); | ||
} | ||
|
||
void eloop_timer_delete(eloop_id_t timer_id) | ||
{ | ||
scheduler_timer_delete(timer_id); | ||
} | ||
|
||
int eloop_timer_start(eloop_id_t timer_id) | ||
{ | ||
scheduler_timer_start(timer_id); | ||
} | ||
|
||
int eloop_timer_stop(eloop_id_t timer_id) | ||
{ | ||
scheduler_timer_stop(timer_id); | ||
} | ||
|
||
eloop_id_t eloop_handler_add_fd(int fd, fd_cb_t cb, void *ctx) | ||
{ | ||
return fd_handler_add_fd(eloop_ctx.fd_handler, fd, cb, ctx); | ||
} | ||
|
||
void eloop_handler_remove_fd(eloop_id_t fd_id) | ||
{ | ||
fd_handler_remove_fd(eloop_ctx.fd_handler, fd_id); | ||
} | ||
|
||
int eloop_init() | ||
{ | ||
eloop_ctx.running = false; | ||
|
||
eloop_ctx.syncer = syncer_new(); | ||
if (!eloop_ctx.syncer) | ||
return -1; | ||
|
||
eloop_ctx.scheduler = scheduler_new(eloop_ctx.syncer); | ||
if (!eloop_ctx.scheduler) { | ||
syncer_delete(eloop_ctx.syncer); | ||
return -1; | ||
} | ||
|
||
eloop_ctx.fd_handler = | ||
fd_handler_new(eloop_ctx.syncer, MAX_FD_EVENTS); | ||
if (!eloop_ctx.fd_handler) { | ||
scheduler_delete(eloop_ctx.scheduler); | ||
syncer_delete(eloop_ctx.syncer); | ||
return -1; | ||
} | ||
|
||
eloop_ctx.running = true; | ||
|
||
return 0; | ||
} | ||
|
||
void eloop_exit() | ||
{ | ||
fd_handler_delete(eloop_ctx.fd_handler); | ||
scheduler_delete(eloop_ctx.scheduler); | ||
syncer_delete(eloop_ctx.syncer); | ||
} | ||
|
||
void eloop_run() | ||
{ | ||
while (eloop_ctx.running) { | ||
fd_handler_handle_events(eloop_ctx.fd_handler); | ||
syncer_process_queue(eloop_ctx.syncer); | ||
} | ||
} | ||
|
||
void eloop_stop() | ||
{ | ||
eloop_ctx.running = false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
#include "fd.h" | ||
#include "list.h" | ||
|
||
#include <sys/epoll.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
|
||
struct fd_handler { | ||
struct syncer *syncer; | ||
struct list_head fd_list; | ||
int poll_fd; | ||
uint32_t max_events; | ||
struct epoll_event* events_buffer; | ||
}; | ||
|
||
#define _event_ctx(handler, idx) \ | ||
(struct fd_data *)(handler)->events_buffer[(idx)].data.ptr | ||
#define _event_mask(handler, idx) \ | ||
(handler)->events_buffer[(idx)].events; | ||
|
||
struct fd_data { | ||
struct list_head list; | ||
int fd; | ||
fd_cb_t cb; | ||
void *ctx; | ||
}; | ||
|
||
static struct fd_data *fd_data_new(struct fd_handler *handler, | ||
int fd, | ||
fd_cb_t cb, | ||
void *ctx) | ||
{ | ||
struct fd_data *fd_data = malloc(sizeof(*fd_data)); | ||
if (!fd_data) | ||
return NULL; | ||
|
||
list_add(&handler->fd_list, &fd_data->list); | ||
fd_data->fd = fd; | ||
fd_data->cb = cb; | ||
fd_data->ctx = ctx; | ||
|
||
return fd_data; | ||
} | ||
|
||
static void fd_data_delete(struct fd_data *fd_data) | ||
{ | ||
list_del(&fd_data->list); | ||
free(fd_data); | ||
} | ||
|
||
struct fd_handler *fd_handler_new(struct syncer *syncer, | ||
uint32_t max_events) | ||
{ | ||
struct fd_handler *handler = | ||
(struct fd_handler *)malloc(sizeof(*handler)); | ||
if (!handler) | ||
return NULL; | ||
|
||
handler->syncer = syncer; | ||
handler->max_events = max_events; | ||
handler->events_buffer = calloc(handler->max_events, | ||
sizeof(struct epoll_event)); | ||
if (!handler->events_buffer) | ||
{ | ||
free(handler); | ||
return NULL; | ||
} | ||
|
||
list_init(&handler->fd_list); | ||
|
||
handler->poll_fd = epoll_create1(0); | ||
if (handler->poll_fd < 0) | ||
{ | ||
free(handler->events_buffer); | ||
free(handler); | ||
return NULL; | ||
} | ||
|
||
return handler; | ||
} | ||
|
||
void fd_handler_delete(struct fd_handler *handler) | ||
{ | ||
struct list_head *itr, *item; | ||
|
||
list_for_each_safe(&handler->fd_list, itr, item) | ||
fd_handler_remove_fd(handler, (eloop_id_t)item); | ||
|
||
close(handler->poll_fd); | ||
free(handler->events_buffer); | ||
free(handler); | ||
} | ||
|
||
eloop_id_t fd_handler_add_fd(struct fd_handler *handler, | ||
int fd, | ||
fd_cb_t cb, | ||
void *ctx) | ||
{ | ||
struct epoll_event event_config; | ||
struct fd_data *fd_data = fd_data_new(handler, fd, cb, ctx); | ||
if (!fd_data) | ||
return INVALID_ID; | ||
|
||
event_config.data.ptr = fd_data; | ||
event_config.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET; | ||
|
||
if (epoll_ctl(handler->poll_fd, | ||
EPOLL_CTL_ADD, | ||
fd_data->fd, | ||
&event_config) < 0) { | ||
fd_data_delete(fd_data); | ||
return INVALID_ID; | ||
} | ||
|
||
return (eloop_id_t)fd_data; | ||
} | ||
|
||
void fd_handler_remove_fd(struct fd_handler *handler, | ||
eloop_id_t fd_id) | ||
{ | ||
struct fd_data *fd_data = (struct fd_data *)fd_id; | ||
|
||
epoll_ctl(handler->poll_fd, EPOLL_CTL_DEL, fd_data->fd, NULL); | ||
fd_data_delete(fd_data); | ||
} | ||
|
||
struct event_sync_ctx { | ||
struct fd_data *fd_data; | ||
uint32_t event_mask; | ||
}; | ||
|
||
static struct event_sync_ctx *event_sync_ctx_new(struct fd_data *fd_data, | ||
uint32_t event_mask) | ||
{ | ||
struct event_sync_ctx *event_sync_ctx = malloc(sizeof(*event_sync_ctx)); | ||
if (!event_sync_ctx) | ||
return NULL; | ||
|
||
event_sync_ctx->fd_data = fd_data; | ||
event_sync_ctx->event_mask = event_mask; | ||
|
||
return event_sync_ctx; | ||
} | ||
|
||
static void event_sync_ctx_delete(struct event_sync_ctx *event_sync_ctx) | ||
{ | ||
free(event_sync_ctx); | ||
} | ||
|
||
static void fd_handler_sync_event(void *ctx) | ||
{ | ||
struct event_sync_ctx *event_sync_ctx = ctx; | ||
struct fd_data *fd_data = event_sync_ctx->fd_data; | ||
|
||
fd_data->cb(fd_data->ctx, event_sync_ctx->event_mask); | ||
event_sync_ctx_delete(event_sync_ctx); | ||
} | ||
|
||
static uint32_t epoll_event_to_fd_event(uint32_t epoll_event) | ||
{ | ||
uint32_t event_mask = 0; | ||
|
||
if (epoll_event & EPOLLERR) { | ||
event_mask = ELOOP_FD_EVENT_ERROR; | ||
} else if ((epoll_event & EPOLLHUP) || | ||
(epoll_event & EPOLLRDHUP)) { | ||
event_mask = ELOOP_FD_EVENT_HUP; | ||
} else { | ||
if (epoll_event & EPOLLIN) | ||
event_mask |= ELOOP_FD_EVENT_READ; | ||
if (epoll_event & EPOLLOUT) | ||
event_mask |= ELOOP_FD_EVENT_WRITE; | ||
} | ||
|
||
return event_mask; | ||
} | ||
|
||
void fd_handler_handle_events(struct fd_handler *handler) | ||
{ | ||
uint32_t i; | ||
int num_events = epoll_wait(handler->poll_fd, | ||
handler->events_buffer, | ||
handler->max_events, | ||
5); | ||
if (num_events <= 0) | ||
return; | ||
|
||
for (i = 0; i < num_events; i++) { | ||
struct fd_data *fd_data = _event_ctx(handler, i); | ||
uint32_t current_event = _event_mask(handler, i); | ||
uint32_t event = epoll_event_to_fd_event(current_event); | ||
|
||
struct event_sync_ctx *event_sync_ctx = | ||
event_sync_ctx_new(fd_data, event); | ||
if (!event_sync_ctx) | ||
continue; | ||
|
||
syncer_task_add(handler->syncer, fd_handler_sync_event, event_sync_ctx); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#ifndef __FD_H__ | ||
#define __FD_H__ | ||
|
||
#include <eloop.h> | ||
|
||
#include "syncer.h" | ||
|
||
struct fd_handler; | ||
|
||
struct fd_handler *fd_handler_new(struct syncer *syncer, | ||
uint32_t max_events); | ||
|
||
void fd_handler_delete(struct fd_handler *handler); | ||
|
||
eloop_id_t fd_handler_add_fd(struct fd_handler *handler, | ||
int fd, | ||
fd_cb_t cb, | ||
void *ctx); | ||
|
||
void fd_handler_remove_fd(struct fd_handler *handler, | ||
eloop_id_t fd_id); | ||
|
||
void fd_handler_handle_events(struct fd_handler *handler); | ||
|
||
#endif /* __FD_H__ */ |
Oops, something went wrong.