297 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| 
 | |
| #include "signal.h"
 | |
| #include "board.h"
 | |
| #include "stdlib.h"
 | |
| #include "stdio.h"
 | |
| #include "debug.h"
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| typedef struct{
 | |
|   void *mutex;
 | |
|   signal_list *head;
 | |
| }self_def;
 | |
| 
 | |
| 
 | |
| static self_def g_self;
 | |
| 
 | |
| 
 | |
| 
 | |
| int signal_init(void)
 | |
| {
 | |
|   self_def *s=&g_self;
 | |
|   if(s->mutex==0)
 | |
|   {
 | |
|     s->mutex=rt_mutex_create("signal_",RT_IPC_FLAG_FIFO);
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| static void cpy4byte(uint32_t *dst,uint32_t *src,int num_4byte)
 | |
| {
 | |
|   for(int i=0;i<num_4byte;i++)
 | |
|   {
 | |
|     dst[i]=src[i];
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #define SLOT_FUN_RUN(fun,param) \
 | |
|   ((slot_fun_def)(fun))(param[0],param[1],param[2],\
 | |
|     param[3],param[4],param[5],param[6],param[7])
 | |
| 
 | |
| typedef void (*slot_fun_def)(uint32_t a,uint32_t b,uint32_t c,uint32_t d,uint32_t e,uint32_t f,uint32_t g,uint32_t h);
 | |
| 
 | |
| static void slot_run(void *t)
 | |
| {
 | |
|   param_check(t);
 | |
|   slot_run_def *s=t;
 | |
|   int msg_size=sizeof(slot_msg_def)+sizeof(uint32_t)*8;
 | |
|   slot_msg_def *msg=calloc(1,msg_size);
 | |
|   while(s->run)
 | |
|   {
 | |
|     rt_mq_recv(s->mb,msg,msg_size,RT_WAITING_FOREVER);
 | |
|     SLOT_FUN_RUN(msg->fun,msg->param);
 | |
|   }
 | |
|   free(msg);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| // 创建一个线程
 | |
| sig_thread thread_creat(int pro)
 | |
| {
 | |
|   static uint16_t count=0;
 | |
|   char name[20]={0};
 | |
|   slot_run_def *run=calloc(1,sizeof(slot_run_def));
 | |
|   run->run=1;
 | |
|   sprintf(name,"sig_mq#%d",count);
 | |
|   run->mb=rt_mq_create(name,(sizeof(slot_msg_def)+sizeof(uint32_t)*8),50,RT_IPC_FLAG_FIFO);
 | |
|   sprintf(name,"sig_t#%d",count);
 | |
|   rt_thread_t rt_t=rt_thread_create(name,slot_run,run,2048,pro,20);
 | |
|   rt_thread_startup(rt_t);
 | |
|   count++;
 | |
|   return run->mb;
 | |
| }
 | |
| 
 | |
| 
 | |
| void thread_delete(sig_thread t)
 | |
| {
 | |
|   // 删除线程需要删除与此线程相关的所有信号槽
 | |
|   // 删除消息队列
 | |
|   param_check(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| // 如果这个类的信号已注册
 | |
| static signal_list *find(void *sig_obj,void *signal_)
 | |
| {
 | |
|   self_def *s=&g_self;
 | |
|   signal_list *l=s->head;
 | |
|   while(l!=0)
 | |
|   {
 | |
|     if(l->signal_==signal_&&l->sig_obj==sig_obj)
 | |
|       return l;
 | |
|     l=l->next;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int connect(void *sig_obj,void *signal_,sig_thread t,void *slot_obj,void *slot)
 | |
| {
 | |
|   self_def *s=&g_self;
 | |
|   signal_def *sig;
 | |
|   sig=signal_find(signal_);
 | |
|   if(sig==0) return -1;
 | |
|   rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
 | |
|   slot_list *slo=calloc(1,sizeof(slot_list));
 | |
|   param_check(slo);
 | |
|   slo->fun=slot;
 | |
|   slo->mb=t;
 | |
|   slo->next=0;
 | |
|   slo->obj=slot_obj;
 | |
|   signal_list *sig_l=find(sig_obj,signal_);
 | |
| 
 | |
|   if(sig_l==0){
 | |
|     sig_l=calloc(1,sizeof(signal_list));
 | |
|     param_check(sig_l);
 | |
|     sig_l->signal_=signal_;
 | |
|     sig_l->sig_obj=sig_obj;
 | |
|     sig_l->next=s->head;
 | |
|     s->head=sig_l;
 | |
|   }
 | |
|   slo->next=sig_l->head;
 | |
|   sig_l->head=slo;
 | |
|   //DBG_LOG("signal connect:%08x",slo);
 | |
|   rt_mutex_release(s->mutex);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| int disconnect(void *sig_obj,void *signal_,sig_thread t,void *slot_obj,void *slot)
 | |
| {
 | |
|   self_def *s=&g_self;
 | |
|   signal_list *sig;
 | |
|   sig=find(sig_obj,signal_);
 | |
|   if(sig==0) return -1;
 | |
|   int ret=-1;
 | |
|   rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
 | |
|   slot_list *next=sig->head;
 | |
|   slot_list *prev=0;
 | |
|   while(next!=0)
 | |
|   {
 | |
|     if(next->fun==slot&&next->obj==slot_obj)
 | |
|     {
 | |
|       if(prev) prev->next=next->next;
 | |
|       else sig->head=next->next;
 | |
|       //DBG_LOG("signal disconnect:%08x",next);
 | |
|       free(next);
 | |
|       ret=0;
 | |
|       break;
 | |
|     }
 | |
|     prev=next;
 | |
|     next=next->next;
 | |
|   }
 | |
|   rt_mutex_release(s->mutex);
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| // 消除与指定对象相关的所有信号槽连接
 | |
| int disconnect_sig(void *sig_obj)
 | |
| {
 | |
|   self_def *s=&g_self;
 | |
|   rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
 | |
|   signal_list *sig=s->head;
 | |
|   signal_list *prev_sig=0;
 | |
|   while(sig!=0)
 | |
|   {
 | |
|     if(sig->sig_obj==sig_obj)
 | |
|     {
 | |
|       slot_list *next=sig->head;
 | |
|       while(next!=0)
 | |
|       {
 | |
|         sig->head=next->next;
 | |
|         free(next);
 | |
|         next=sig->head;
 | |
|       }
 | |
|       if(prev_sig) prev_sig=sig->next;
 | |
|       else s->head=sig->next;
 | |
|       free(sig);
 | |
|       break;
 | |
|     }
 | |
|     prev_sig=sig;
 | |
|     sig=sig->next;
 | |
|   }
 | |
|   rt_mutex_release(s->mutex);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| // 消除与指定对象相关的所有信号槽连接
 | |
| int disconnect_slot(void *slot_obj)
 | |
| {
 | |
|   self_def *s=&g_self;
 | |
|   rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
 | |
|   signal_list *sig=s->head;
 | |
|   while(sig!=0)
 | |
|   {
 | |
|     slot_list *next=sig->head;
 | |
|     slot_list *prev=0;
 | |
|     while(next!=0)
 | |
|     {
 | |
|       if(next->obj==slot_obj)
 | |
|       {
 | |
|         if(prev) prev->next=next->next;
 | |
|         else sig->head=next->next;
 | |
|         free(next);
 | |
|         break;
 | |
|       }
 | |
|       prev=next;
 | |
|       next=next->next;
 | |
|     }
 | |
|     sig=sig->next;
 | |
|   }
 | |
|   rt_mutex_release(s->mutex);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| signal_def *signal_find(void *signal_)
 | |
| {
 | |
|   extern const int signalstruct$$Base;
 | |
|   extern const int signalstruct$$Limit;
 | |
|   signal_def *start=(signal_def *)&signalstruct$$Base;
 | |
|   signal_def *end=(signal_def *)&signalstruct$$Limit;
 | |
|   for(signal_def *t=start;t<end;t++)
 | |
|   {
 | |
|     if(t->signal_==signal_)
 | |
|     {
 | |
|       return t;
 | |
|     }
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| // 发送信号
 | |
| int _signal_emit(void *sig_obj,void *signal_,uint32_t *param,int param_num)
 | |
| {
 | |
|   self_def *s=&g_self;
 | |
|   signal_list *sig=find(sig_obj,signal_);
 | |
|   if(sig==0) return -1;
 | |
|   if(param_num>7) return -2;
 | |
|   int size=sizeof(slot_msg_def)+sizeof(uint32_t)*(8);
 | |
|   slot_msg_def *m=malloc(size);
 | |
|   rt_mutex_take(s->mutex,RT_WAITING_FOREVER);
 | |
|   slot_list *h=sig->head;
 | |
|   m->param_num=param_num;
 | |
|   m->src=signal_;
 | |
|   while(h)
 | |
|   {
 | |
|     m->fun=h->fun;
 | |
|     if(h->obj)
 | |
|     {
 | |
|       cpy4byte(m->param+1,param,param_num);
 | |
|       m->param[0]=(uint32_t)h->obj;
 | |
|     }else{
 | |
|       cpy4byte(m->param,param,param_num);
 | |
|     }
 | |
|     if(h->mb){
 | |
|       rt_mq_send(h->mb,m,size);
 | |
|     }else{
 | |
|       SLOT_FUN_RUN(m->fun,m->param);
 | |
|     }
 | |
|     h=h->next;
 | |
|   }
 | |
|   rt_mutex_release(s->mutex);
 | |
|   free(m);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | 
