Mic_chen

It is not the strongest of the species that survive, nor the most intelligent, but the one most responsive to change

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
在模块化的设计中,对各个模块的解耦是至关重要的,本组件通过可以对模块所扮演的角色定义为发布者、订阅者。
订阅者通过订阅的方式注册,发布者内部状态发生变化时不用关心谁会响应自己的消息,发布者发布只管发布消息,
由notice组件自动分发消息到已注册的观察者。
// notice.h #define OBSERVER_MAX 4 typedef struct notice_msg { // public char *sub_name; int cmd; int data_fix; // 固定数据 unsigned int data_ex_len; // 扩展数据长度,0:没有扩展数据 void *pdata_ex; // 扩展数据指针 }notice_msg_t; typedef int (*NOTICE_ON_MSG_CB)(notice_msg_t *pmsg); typedef struct notice_observer { ak_queue_t msg_queue; }notice_observer_t; typedef struct notice_subject { char *name; notice_observer_t* obs_tbl[OBSERVER_MAX]; }notice_subject_t;

  

// notice.c
/****************************************************** * Constant ******************************************************/ /****************************************************** * Macro ******************************************************/ #define NOTICE_MSG_MAX 20 #define CHECK_THIS_IS_NULL() do{if(NULL == this) return -1;}while(0) /****************************************************** * Type Definitions ******************************************************/ /****************************************************** * Function Declarations ******************************************************/ // obsever int akp_notice_observer_ctor(notice_observer_t *this) { int ret; CHECK_THIS_IS_NULL(); ret = ak_thread_queue_init(&(this->msg_queue), sizeof(notice_msg_t),NOTICE_MSG_MAX); if(ret) return -1; else return 0; } int akp_notice_observer_dector(notice_observer_t *this) { int ret; CHECK_THIS_IS_NULL(); ret = ak_thread_queue_destroy(&(this->msg_queue)); if(ret) return -1; else return 0; } int akp_notice_on_msg(notice_observer_t *this, NOTICE_ON_MSG_CB fun_cb) { CHECK_THIS_IS_NULL(); notice_msg_t msg; ak_thread_queue_wait(&(this->msg_queue), &msg); fun_cb(&msg); if(msg.data_ex_len > 0 && msg.pdata_ex != NULL) { free(msg.pdata_ex); } } // subject int akp_notice_subject_ctor(notice_subject_t *this,const char *name) { CHECK_THIS_IS_NULL(); this->name = (char *)name; memset(this->obs_tbl,0,sizeof(this->obs_tbl)); return 0; } int akp_notice_subject_dector(notice_subject_t *this) { CHECK_THIS_IS_NULL(); return 0; } int akp_notice_add_observer(notice_subject_t *this, notice_observer_t *obs) { CHECK_THIS_IS_NULL(); int i; for(i = 0; i< OBSERVER_MAX;i++) { if(this->obs_tbl[i] == 0) { break; } } if(i >= OBSERVER_MAX) { ak_print_error("[notice]: no more room to add\n"); return -1; } //ak_print_error("akp_notice_add_observer tbl=%x obs=%x i=%d\n",this->obs_tbl,obs,i); this->obs_tbl[i] = obs; return 0; } int akp_notice_remove_observer(notice_subject_t *this, notice_observer_t *obs) { CHECK_THIS_IS_NULL(); int i; for(i = 0; i< OBSERVER_MAX;i++) { if(this->obs_tbl[i] == obs) { break; } } if(i >= OBSERVER_MAX) { ak_print_error("[notice]: match observer fail\n"); return -1; } this->obs_tbl[i] = 0; return 0; } int akp_notice_notify(notice_subject_t *this, notice_msg_t *pmsg, void *pdata_ex, unsigned int len) { CHECK_THIS_IS_NULL(); void *p = NULL; notice_observer_t *pobs = NULL; // clear extend data area pmsg->pdata_ex= NULL; pmsg->data_ex_len = 0; // msg dispense int i; for(i = 0; i < OBSERVER_MAX;i++) { if(this->obs_tbl[i] != 0) { if(len > 0) { p = malloc(len); if(NULL != p){ memcpy(p ,pdata_ex,len); pmsg->pdata_ex= p; pmsg->data_ex_len = len; } else { ak_print_error_ex("[notice]: malloc error\n"); } } //ak_print_normal("[notice]: post msg src name [%s] cmd %d\n",pmsg->sub_name,pmsg->cmd); //ak_print_error("[notice]: %d this->obs_tbl[i]=%x\n",i,this->obs_tbl[i]); pobs = this->obs_tbl[i]; ak_thread_queue_post(&(pobs->msg_queue), pmsg); } } return 0; }

  

posted on 2018-05-05 17:06  Mic_chen  阅读(396)  评论(0编辑  收藏  举报