添加信号槽基本实现
This commit is contained in:
89
soft/mysignal.c
Normal file
89
soft/mysignal.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "mysignal.h"
|
||||
#include "pthread.h"
|
||||
#include "stdlib.h"
|
||||
#include "lambda.h"
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/types.h>
|
||||
#include "stdio.h"
|
||||
#include "errno.h"
|
||||
#include <semaphore.h>
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
54
soft/mysignal.h
Normal file
54
soft/mysignal.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef mysignal_h__
|
||||
#define mysignal_h__
|
||||
|
||||
#include "pthread.h"
|
||||
#include "stdint.h"
|
||||
#include <semaphore.h>
|
||||
|
||||
|
||||
#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
|
126
test/signal_test.c
Normal file
126
test/signal_test.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user