diff --git a/soft/mysignal.c b/soft/mysignal.c new file mode 100644 index 0000000..082266d --- /dev/null +++ b/soft/mysignal.c @@ -0,0 +1,89 @@ +#include "mysignal.h" +#include "pthread.h" +#include "stdlib.h" +#include "lambda.h" +#include +#include +#include +#include "stdio.h" +#include "errno.h" +#include + + + + +static void* _thread(void* arg) { + mythread_t* self = arg; + slot_list_with_pars *slot_p; + while (1) { + slot_p = NULL; + sem_wait(&self->sem); + pthread_mutex_lock(&self->lock); + printf("sem take\n"); + // 把槽列表里的函数取出来 + if (self->slot_head) { + slot_p = self->slot_head; + self->slot_head = self->slot_head->next; + } + pthread_mutex_unlock(&self->lock); + if (slot_p) { + if (slot_p->func) { + printf("args_p=%p\n", slot_p); + slot_p->func(slot_p); + } + // 槽函数执行完之后释放 + free(slot_p); + } + } + return NULL; +} + + +// 添加异步执行的槽函数 +void send_slot_fun(mythread_t *self, slot_list_with_pars* slot_p) { + // 这里根据tid来决定把槽函数添加到哪个线程的槽列表里 + pthread_mutex_lock(&self->lock); + if (self->slot_head == NULL) { + self->slot_head = slot_p; + } else { + // 添加到槽列表的开头 + slot_p->next = self->slot_head; + self->slot_head = slot_p; + } + pthread_mutex_unlock(&self->lock); + sem_post(&self->sem); + printf("add_slot_fun\n"); +} + + +void _connect(void* sig_obj, void* sig_fun, mythread_t* thread, void* slot_obj, const char* slot_fun) { + __SIG_OBJ* sig_p = (__SIG_OBJ*)sig_obj; + slot_list* slot_p = calloc(sizeof(slot_list), 1); + slot_p->slot_obj = slot_obj; + slot_p->func = signal_find_slot_func(slot_fun); + if (!slot_p->func) { + // 找不到槽函数,无法连接 + free(slot_p); + return; + } + slot_p->thread = thread; + if (sig_p->slot_head == NULL) { + sig_p->slot_head = slot_p; + } else { + slot_p->next = sig_p->slot_head; + sig_p->slot_head = slot_p; + } + + +} + + +mythread_t *sigthread_init() { + mythread_t* self = calloc(1, sizeof(mythread_t)); + pthread_mutex_init(&self->lock, NULL); + sem_init(&self->sem, 0, 0); + pthread_create(&self->tid, NULL, _thread, self); + return self; +} + + diff --git a/soft/mysignal.h b/soft/mysignal.h new file mode 100644 index 0000000..7f19d70 --- /dev/null +++ b/soft/mysignal.h @@ -0,0 +1,54 @@ +#ifndef mysignal_h__ +#define mysignal_h__ + +#include "pthread.h" +#include "stdint.h" +#include + + +#define emit +#define signal void +#define slot void + + +typedef struct { + void* next; + void (*func)(void* par); + // size_t pars[]; // 这里保存函数的参数实体 +}slot_list_with_pars; + +typedef struct { + pthread_mutex_t lock; /* 互斥锁定义 */ + sem_t sem; + pthread_t tid; + slot_list_with_pars *slot_head; +} mythread_t; + +typedef struct { + void* next; + void (*func)(void* par); + void* slot_obj; + mythread_t* thread; +}slot_list; + +typedef struct { + pthread_mutex_t lock; /* 互斥锁定义 */ + slot_list* slot_head; +}__SIG_OBJ; + +#define SIG_OBJ __SIG_OBJ __sig_obj + + +void send_slot_fun(mythread_t* self, slot_list_with_pars* slot_p); +mythread_t* sigthread_init(); + +void _connect(void* sig_obj, void* sig_fun, mythread_t* thread, void* slot_obj, const char* slot_fun); + +// 这个函数在signal_tmp.c里实现 +void* signal_find_slot_func(const char* name); + +#define connect(sig_obj, sig_fun, thread, slot_obj, slot_fun) {\ + (void)slot_fun;\ + _connect(sig_obj, sig_fun, thread, slot_obj, #slot_fun);}\ + +#endif diff --git a/test/signal_test.c b/test/signal_test.c new file mode 100644 index 0000000..e872a08 --- /dev/null +++ b/test/signal_test.c @@ -0,0 +1,126 @@ +#include "mysignal.h" +#include "pthread.h" +#include "stdlib.h" +#include "lambda.h" +#include "sys/time.h" +#include "errno.h" +#include "stdio.h" +#include "string.h" + + + +typedef struct { + SIG_OBJ; + int test_var; +}test_sig_obj; + +typedef struct { + SIG_OBJ; + int test_var; +}test_sig_obj2; + + +// 定义槽函数 +slot test_slot(test_sig_obj2* self, int a, int b) { + printf("test_slot var=%d\n", self->test_var); + self->test_var = a + b; + printf("test_slot var=%d\n", self->test_var); +} + +// 定义信号 +signal test_signal(test_sig_obj* self, int a, int b); + + + +// 以下是自动生成的代码示例 + +// 把槽函数的参数封装为结构体 +typedef struct { + slot_list_with_pars slot_; + test_sig_obj2* self; + int a; + int b; +}test_signal_args; + +// 封装函数用来调用实际的槽函数 +static void test_slot_func(void* args) { + test_signal_args* a = args; + printf("test_slot_func: %d %d\n", a->a, a->b); + printf("args_p=%p\n", a); + test_slot(a->self, a->a, a->b); +} + +// 信号函数的实现 +signal test_signal(test_sig_obj* self, int a, int b) { + test_signal_args* pars = NULL; + slot_list* slot_p = self->__sig_obj.slot_head; + while (slot_p) { + pars = calloc(1, sizeof(test_signal_args)); + pars->slot_.func = slot_p->func; + // 这里self要换成槽的self + pars->self = slot_p->slot_obj; + pars->a = a; + pars->b = b; + if (slot_p->thread) { + // 异步调用 + send_slot_fun(slot_p->thread, (slot_list_with_pars*)pars); + } else { + // 同步调用 + slot_p->func(pars); + free(pars); + } + slot_p = slot_p->next; + } +} + +// 定义一个数据结构来保存槽封装函数与槽函数的关系 +typedef struct { + void (*func)(void*); + char *name; +} func_name; + +static const func_name g_func_table[] = { + { + .func = test_slot_func, + .name = "test_slot" + } +}; + + +void* signal_find_slot_func(const char* name) { + for (int i = 0; i < sizeof(g_func_table) / sizeof(func_name); i++) { + if (strcmp(name, g_func_table[i].name) == 0) { + return g_func_table[i].func; + } + } + return 0; +} + + +// 自动生成代码示例结束 + +static void mdelay(unsigned long mSec){ + struct timeval tv; + tv.tv_sec=mSec/1000; + tv.tv_usec=(mSec%1000)*1000; + int err; + do{ + err=select(0,NULL,NULL,NULL,&tv); + }while(err<0 && errno==EINTR); +} + +static test_sig_obj g_sig_obj = { .test_var = 1, }; +static test_sig_obj2 g_sig_obj2 = { .test_var = 2, }; + +int thread_fun(void* t) { + mythread_t* th = sigthread_init(); + printf("thread_fun start\n"); + printf("test_slot_func=%p\n", test_slot_func); + connect(&g_sig_obj, test_signal, th, &g_sig_obj2, test_slot); + mdelay(1000); + emit test_signal(&g_sig_obj, 2, 3); + mdelay(1000); + return 0; +} + +