Skip to content

Commit

Permalink
support signal event for (#423)(#458)
Browse files Browse the repository at this point in the history
  • Loading branch information
ithewei committed Apr 26, 2024
1 parent 3564a4f commit 6ad0d72
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
## ✨ 特性

- 跨平台(Linux, Windows, macOS, Android, iOS, BSD, Solaris)
- 高性能事件循环(网络IO事件、定时器事件、空闲事件、自定义事件)
- 高性能事件循环(网络IO事件、定时器事件、空闲事件、自定义事件、信号
- TCP/UDP服务端/客户端/代理
- TCP支持心跳、重连、转发、多线程安全write和close等特性
- 内置常见的拆包模式(固定包长、分界符、头部长度字段)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ but simpler api and richer protocols.
## ✨ Features

- Cross-platform (Linux, Windows, macOS, Android, iOS, BSD, Solaris)
- High-performance EventLoop (IO, timer, idle, custom)
- High-performance EventLoop (IO, timer, idle, custom, signal)
- TCP/UDP client/server/proxy
- TCP supports heartbeat, reconnect, upstream, MultiThread-safe write and close, etc.
- Built-in common unpacking modes (FixedLength, Delimiter, LengthField)
Expand Down
2 changes: 2 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,8 @@
- htimer_reset
- hidle_add
- hidle_del
- hsignal_add
- hsignal_del

### nlog.h
- network_logger
Expand Down
8 changes: 7 additions & 1 deletion docs/cn/hloop.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct hevent_s {
// 获取事件用户数据
#define hevent_userdata(ev) (((hevent_t*)(ev))->userdata)

// hidle_t、htimer_t、hio_t皆是继承自hevent_t,继承上面的数据成员和函数方法
// hio_t、htimer_t、hsignal_t、hidle_t皆是继承自hevent_t,继承上面的数据成员和函数方法

// 新建事件循环
hloop_t* hloop_new(int flags DEFAULT(HLOOP_FLAG_AUTO_FREE));
Expand Down Expand Up @@ -107,6 +107,12 @@ void* hloop_userdata(hloop_t* loop);
// 投递事件
void hloop_post_event(hloop_t* loop, hevent_t* ev);

// 添加信号处理
hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo);

// 删除信号处理
void hsignal_del(hsignal_t* sig);

// 添加空闲事件
hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));

Expand Down
4 changes: 4 additions & 0 deletions event/hevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define HIO_READ_UNTIL_DELIM 0x4

ARRAY_DECL(hio_t*, io_array);
ARRAY_DECL(hsignal_t*, signal_array);
QUEUE_DECL(hevent_t, event_queue);

struct hloop_s {
Expand All @@ -45,6 +46,9 @@ struct hloop_s {
uint32_t npendings;
// pendings: with priority as array.index
hevent_t* pendings[HEVENT_PRIORITY_SIZE];
// signals
struct signal_array signals;
uint32_t nsignals;
// idles
struct list_head idles;
uint32_t nidles;
Expand Down
57 changes: 57 additions & 0 deletions event/hloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,14 @@ static void hloop_cleanup(hloop_t* loop) {
}
heap_init(&loop->realtimers, NULL);

// signals
printd("cleanup signals...\n");
for (int i = 0; i < loop->signals.maxsize; ++i) {
hsignal_t* sig = loop->signals.ptr[i];
HV_FREE(sig);
}
signal_array_cleanup(&loop->signals);

// readbuf
if (loop->readbuf.base && loop->readbuf.len) {
HV_FREE(loop->readbuf.base);
Expand Down Expand Up @@ -587,6 +595,55 @@ void* hloop_userdata(hloop_t* loop) {
return loop->userdata;
}

static hloop_t* s_signal_loop = NULL;
static void signal_handler(int signo) {
if (!s_signal_loop) return;
if (signo >= s_signal_loop->signals.maxsize) return;
hsignal_t* sig = s_signal_loop->signals.ptr[signo];
if (!sig) return;
hloop_post_event(s_signal_loop, sig);
}

hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo) {
int max_signo = 64;
#ifdef _NSIG
max_signo = _NSIG;
#endif
if (signo <= 0 || signo >= max_signo) {
hloge("signo %d over %d!", signo, max_signo);
return NULL;
}
if (loop->signals.maxsize == 0) {
signal_array_init(&loop->signals, max_signo);
}
hsignal_t* sig = loop->signals.ptr[signo];
if (sig == NULL) {
HV_ALLOC_SIZEOF(sig);
sig->loop = loop;
sig->event_type = HEVENT_TYPE_SIGNAL;
// NOTE: use event_id as signo
sig->event_id = signo;
sig->cb = cb;
sig->priority = HEVENT_HIGHEST_PRIORITY;
loop->signals.ptr[signo] = sig;
loop->nsignals++;
}
EVENT_ACTIVE(sig);
s_signal_loop = loop;
signal(signo, signal_handler);
return sig;
}

void hsignal_del(hsignal_t* sig) {
if (!sig->active) return;
hloop_t* loop = sig->loop;
int signo = (int)sig->event_id;
if (signo >= loop->signals.maxsize) return;
loop->signals.ptr[signo] = NULL;
loop->nsignals--;
EVENT_DEL(sig);
}

hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat) {
hidle_t* idle;
HV_ALLOC_SIZEOF(idle);
Expand Down
11 changes: 9 additions & 2 deletions event/hloop.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@ typedef struct hevent_s hevent_t;

// NOTE: The following structures are subclasses of hevent_t,
// inheriting hevent_t data members and function members.
typedef struct hio_s hio_t;
typedef struct hidle_s hidle_t;
typedef struct htimer_s htimer_t;
typedef struct htimeout_s htimeout_t;
typedef struct hperiod_s hperiod_t;
typedef struct hio_s hio_t;
typedef struct hevent_s hsignal_t;

typedef void (*hevent_cb) (hevent_t* ev);
typedef void (*hio_cb) (hio_t* io);
typedef void (*hidle_cb) (hidle_t* idle);
typedef void (*htimer_cb) (htimer_t* timer);
typedef void (*hio_cb) (hio_t* io);
typedef void (*hsignal_cb) (hsignal_t* sig);

typedef void (*haccept_cb) (hio_t* io);
typedef void (*hconnect_cb) (hio_t* io);
Expand All @@ -42,6 +44,7 @@ typedef enum {
HEVENT_TYPE_PERIOD = 0x00000020,
HEVENT_TYPE_TIMER = HEVENT_TYPE_TIMEOUT|HEVENT_TYPE_PERIOD,
HEVENT_TYPE_IDLE = 0x00000100,
HEVENT_TYPE_SIGNAL = 0x00000200,
HEVENT_TYPE_CUSTOM = 0x00000400, // 1024
} hevent_type_e;

Expand Down Expand Up @@ -184,6 +187,10 @@ HV_EXPORT void* hloop_userdata(hloop_t* loop);
// NOTE: hloop_post_event is thread-safe, used to post event from other thread to loop thread.
HV_EXPORT void hloop_post_event(hloop_t* loop, hevent_t* ev);

// signal
HV_EXPORT hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo);
HV_EXPORT void hsignal_del(hsignal_t* sig);

// idle
HV_EXPORT hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
HV_EXPORT void hidle_del(hidle_t* idle);
Expand Down
8 changes: 8 additions & 0 deletions examples/hloop_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ void on_custom_events(hevent_t* ev) {
printf("on_custom_events event_type=%d userdata=%ld\n", (int)ev->event_type, (long)(intptr_t)ev->userdata);
}

void on_signal(hsignal_t* sig) {
printf("on_signal signo=%d\n", (int)hevent_id(sig));
hloop_stop(hevent_loop(sig));
}

int main() {
// memcheck atexit
HV_MEMCHECK;
Expand All @@ -87,6 +92,9 @@ int main() {
htimer_add_period(loop, cron_minutely, -1, -1, -1, -1, -1, INFINITE);
htimer_add_period(loop, cron_hourly, minute+1, -1, -1, -1, -1, INFINITE);

// test signal: enter Ctrl-C to trigger
hsignal_add(loop, on_signal, SIGINT);

// test network_logger
htimer_add(loop, timer_write_log, 1000, INFINITE);
hlog_set_handler(mylogger);
Expand Down

0 comments on commit 6ad0d72

Please sign in to comment.