bluedroid的消息传递机制
1 创建一个队列:
btu_bta_msg_queue = fixed_queue_new(SIZE_MAX);
fixed_queue_t *ret = osi_calloc(sizeof(fixed_queue_t));
//队列里面最大的容量
ret->capacity = capacity;
//链表
ret->list = list_new(NULL);
//创建二个eventfd类型的fd,可以用epoll来监控
//enqueue_sem访问链表时,要先获取这个值减1
ret->enqueue_sem = semaphore_new(capacity);
ret->fd = eventfd(value, EFD_SEMAPHORE); //EFD_SEMAPHORE实现每次读减1的效果
//dequeue_sem当添加一个消息到链表时,加1
ret->dequeue_sem = semaphore_new(0);
2 创建一个线程:
bt_workqueue_thread = thread_new(BT_WORKQUEUE_NAME);
ret->reactor = reactor_new();
ret->epoll_fd = epoll_create(MAX_EVENTS); //创建一个epoll
//创建一个内部队列,创建过程跟上面一样
ret->work_queue = fixed_queue_new(work_queue_capacity);
pthread_create(&ret->pthread, NULL, run_thread, &start);
run_thread
//获取内部队列的dequeue_sem
int fd = fixed_queue_get_dequeue_fd(thread->work_queue);
//向epoll添加一个读监控
reactor_object_t *object = (reactor_object_t *)osi_calloc(sizeof(reactor_object_t));
object->fd = fd;
object->read_ready = read_ready; //work_queue_read_cb
struct epoll_event event;
event.events |= (EPOLLIN | EPOLLRDHUP);
epoll_ctl(reactor->epoll_fd, EPOLL_CTL_ADD, fd, &event)
reactor_start
while (1)
epoll_wait(reactor->epoll_fd, events, MAX_EVENTS, -1)
//当有事件
if (events[j].events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR) && object->read_ready)
object->read_ready(object->context);
work_queue_read_cb
//void *context = thread->work_queue; 内部队列
fixed_queue_t *queue = (fixed_queue_t *)context;
//取出消息,然后删掉该条消息
work_item_t *item = fixed_queue_dequeue(queue);
//执行最终的函数
item->func(item->context);
3 上面有个问题谁去填充线程内部队列,答案就是:
thread_post(bt_workqueue_thread, btu_task_start_up, NULL);
work_item_t *item = (work_item_t *)osi_malloc(sizeof(work_item_t));
item->func = func;
item->context = context;
fixed_queue_enqueue(thread->work_queue, item);
4 这里有个问题,第一步创建的队列我们没有使用,这里介绍另外一个函数,看下它的实现:
fixed_queue_register_dequeue(
btu_bta_msg_queue, //第一步创建的队列
thread_get_reactor(bt_workqueue_thread), //线程的epoll相关的结构体
btu_bta_msg_ready, //最终要执行的函数
NULL);
queue->dequeue_ready = ready_cb;
queue->dequeue_context = context;
queue->dequeue_object = reactor_register(
reactor,
fixed_queue_get_dequeue_fd(queue), //新队列的dequeue_sem的fd
queue,
internal_dequeue_ready,
NULL
);
//向epoll添加一个读监控(新队列的dequeue_sem的fd)
reactor_object_t *object = (reactor_object_t *)osi_calloc(sizeof(reactor_object_t));
object->fd = fd;
object->read_ready = read_ready; //btu_bta_msg_ready
struct epoll_event event;
event.events |= (EPOLLIN | EPOLLRDHUP);
epoll_ctl(reactor->epoll_fd, EPOLL_CTL_ADD, fd, &event)
//当有事件
if (events[j].events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR) && object->read_ready)
object->read_ready(object->context);
btu_bta_msg_ready
//取出消息,然后删掉该条消息
BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
//自定义处理消息函数
bta_sys_event(p_msg);
5 最后一个问题:如何给这个队列传递消息:进队列如下:
fixed_queue_enqueue(btu_bta_msg_queue, p_msg);
总结:
核心就是通过线程的epoll监控每个队列里面的event_fd(通过fixed_queue_register_dequeue注册新队列以及新处理函数)
有两种方式传递处理消息:
第一使用线程内部自带的队列:thread_post(bt_workqueue_thread, btu_task_start_up, NULL);
第二自己创建一个队列:fixed_queue_new / 注册fixed_queue_register_dequeue(自定义处理函数)/ 进队列fixed_queue_enqueue,自由度更大