bluedroid 之OSI ---- reactor

2. Reactor


Reactor 英文意思: 反应器,反应堆

此处的reactor 是作为thread 的执行者,封装了event 接收,以及消息分发

reactor_t* reactor_new(void) {
  reactor_t* ret = (reactor_t*)osi_calloc(sizeof(reactor_t));

  ret->epoll_fd = INVALID_FD;
  ret->event_fd = INVALID_FD;

  ret->epoll_fd = epoll_create(MAX_EVENTS);   创建epoll
  if (ret->epoll_fd == INVALID_FD) {
    LOG_ERROR(LOG_TAG, "%s unable to create epoll instance: %s", __func__,
              strerror(errno));
    goto error;
  }

  ret->event_fd = eventfd(0, 0);            创建eventfd
  if (ret->event_fd == INVALID_FD) {
    LOG_ERROR(LOG_TAG, "%s unable to create eventfd: %s", __func__,
              strerror(errno));
    goto error;
  }

  ret->list_mutex = new std::mutex;            创建mutex
  ret->invalidation_list = list_new(NULL);     创建list
  if (!ret->invalidation_list) {
    LOG_ERROR(LOG_TAG, "%s unable to allocate object invalidation list.",
              __func__);
    goto error;
  }

  struct epoll_event event;
  memset(&event, 0, sizeof(event));
  event.events = EPOLLIN;
  event.data.ptr = NULL;
  if (epoll_ctl(ret->epoll_fd, EPOLL_CTL_ADD, ret->event_fd, &event) == -1) {
    LOG_ERROR(LOG_TAG, "%s unable to register eventfd with epoll set: %s",
              __func__, strerror(errno));
    goto error;
  }

  return ret;

error:;
  reactor_free(ret);
  return NULL;
}

reactor 的创建过程,就是创建了一堆的运行环境工

  • epoll
  • eventfd
  • mutex
  • list
  • epoll_event

Reactor 对象数据结构:

struct reactor_object_t {
  int fd;              // 此fd 作为监视事件的文件描述符,存储的是dequeue 的fd
  void* context;       // a context that's passed back to the *_ready functions.
  reactor_t* reactor;  // the reactor instance this object is registered with.
  std::mutex* mutex;  // protects the lifetime of this object and all variables.

  void (*read_ready)(void* context);   // function to call when the file
                                       // descriptor becomes readable.
  void (*write_ready)(void* context);  // function to call when the file
                                       // descriptor becomes writeable.
};

struct reactor_t {
  int epoll_fd;
  int event_fd;               在reactor_new 时创建,唯一的event_fd 的data_ptr 为空,利用这个特性来终止reator 的执行 , reactor_stop 时给这个event_fd写event, 在run_reactor 中判断,data_ptr为空,则退出reactor 的运行
  std::mutex* list_mutex;  对invalidation_list 操作起到线程保护作用
  list_t* invalidation_list;  // reactor objects that have been unregistered.
  pthread_t run_thread;       // the pthread on which reactor_run is executing.
  bool is_running;            // indicates whether |run_thread| is valid.
  bool object_removed;
};

invalidation_list 主要是保证的是reactor 的unregister 动作可能是在本线程中调用,也可能是在其他线程调用

如果是在本县成调用,则直接执行,如果是在外部调用,则存入invalidation_list 中,当线程在运行时,判断reactor_object_t 在invalidation_list中时,则event 不会被处理。

reactor 通信之所以可以完美工作得益于epoll 机制(类似与select)

创建epoll 后通过epoll-ctrl函数 注册监听事件:

函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
该函数用于控制某个epoll文件描述符上的事件,可以注册事件,修改事件,删除事件。
参数:
epfd:由 epoll_create 生成的epoll专用的文件描述符;
op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除

fd:关联的文件描述符;
event:指向epoll_event的指针;
如果调用成功返回0,不成功返回-1

   int epoll_ctl(int epfd, intop, int fd, struct epoll_event*event); 

第三个参数fd ,通过这个文件描述符把事件串联起来

在reactor 中执行epoll_wait 等待事件发生,在fixed_queue中操作这个文件描述符,使得reactor 得知有event 事件

在reactor    fixed_queue 中共同享有一个fd,

reactor 如何thread 之间是如何触发事件处理的?

int fd = fixed_queue_get_dequeue_fd(thread->work_queue);
  void* context = thread->work_queue;
将fd 注册到reactor中
  reactor_object_t* work_queue_object =
      reactor_register(thread->reactor, fd, context, work_queue_read_cb, NULL);
fd 的庐山真面目就是dequeue_sem 的fd
int fixed_queue_get_dequeue_fd(const fixed_queue_t* queue) {
  CHECK(queue != NULL);
  return semaphore_get_fd(queue->dequeue_sem);

}

当需要向thread 发送消息时:

void fixed_queue_enqueue(fixed_queue_t* queue, void* data) {
  CHECK(queue != NULL);
  CHECK(data != NULL);

  semaphore_wait(queue->enqueue_sem);

  {
    std::lock_guard<std::mutex> lock(*queue->mutex);
    list_append(queue->list, data);
  }

  semaphore_post(queue->dequeue_sem);
}
而semaphore_post 的实现就是, 通过event_fd 向semaphore fd 中写1
void semaphore_post(semaphore_t* semaphore) {
  CHECK(semaphore != NULL);
  CHECK(semaphore->fd != INVALID_FD);

  if (eventfd_write(semaphore->fd, 1ULL) == -1)
    LOG_ERROR(LOG_TAG, "%s unable to post to semaphore: %s", __func__,
              strerror(errno));
}


    OSI_NO_INTR(ret = epoll_wait(reactor->epoll_fd, events, MAX_EVENTS, -1));
    if (ret == -1) {
      LOG_ERROR(LOG_TAG, "%s error in epoll_wait: %s", __func__,
                strerror(errno));
      reactor->is_running = false;
      return REACTOR_STATUS_ERROR;
    }

收到有事件的event 后,触发thread 注册的callback 函数:
static void work_queue_read_cb(void* context) {
  CHECK(context != NULL);

  fixed_queue_t* queue = (fixed_queue_t*)context;
  work_item_t* item = static_cast<work_item_t*>(fixed_queue_dequeue(queue));
  item->func(item->context);
  osi_free(item);
}
从而去queue 中取数据,并进行执行

-

猜你喜欢

转载自blog.csdn.net/iccome/article/details/82962442
今日推荐