gearman 源码学习笔记2

本文详细解析了gearman如何利用libevent实现多线程及网络框架,包括线程创建、数据初始化、命令通知、事件循环等关键步骤。通过构建管道进行主线程与工作线程间的交互,确保高效的数据处理与任务分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上回说到要说 gearman 如果利用libevent 编写网络框架。但是在说之前还得先说一下 gearman如何使用多线程,

不说了上代码。

 uint32_t x= 0;
    do
    {
      gearmand->ret= gearmand_thread_create(*gearmand);
      if (gearmand->ret != GEARMAND_SUCCESS)
        return gearmand->ret;
      x++;
    }
    while (x < gearmand->threads);

这快就是接入线程逻辑的入口 可以看出当 thread == 0的时候只会创建创建1一个工作线程。

 

gearmand_thread_st* thread= new (std::nothrow) gearmand_thread_st(gearmand);
  if (thread == NULL)
  {
    return gearmand_merror("new", gearmand_thread_st, 1);
  }

  if (! gearman_server_thread_init(gearmand_server(&gearmand), &(thread->server_thread),
                                   _log, thread, gearmand_connection_watch))
  {
    delete thread;
    gearmand_fatal("gearman_server_thread_init(NULL)");
    return GEARMAND_MEMORY_ALLOCATION_FAILURE;
  }
这是创建 thread对象和初始化thread数据需要关注的是 gearmand_connection_watch这个函数请注意。主线程accept的fd 将会发给这个函数 进行吞吐数据。

if (gearmand_failed(ret= _wakeup_init(thread)))
  {
    gearmand_thread_free(thread);
    return ret;
  }
那主线程和工作线程如何进行交互的那请看 _wakeup_init这里将会建立 pip 进行命令通知。

 gearmand_debug("Creating IO thread wakeup pipe");

#if defined(HAVE_PIPE2) && HAVE_PIPE2
  if (pipe2(thread->wakeup_fd, O_NONBLOCK) == -1)
  {
    return gearmand_perror(errno, "pipe");
  }
#else
  if (pipe(thread->wakeup_fd) == -1)
  {
    return gearmand_perror(errno, "pipe");
  }

  gearmand_error_t local_ret;
  if ((local_ret= gearmand_sockfd_nonblock(thread->wakeup_fd[0])))
  {
    return local_ret;
  }
#endif

  event_set(&(thread->wakeup_event), thread->wakeup_fd[0], EV_READ | EV_PERSIST,
            _wakeup_event, thread);
  if (event_base_set(thread->base, &(thread->wakeup_event)) == -1)
  {
    gearmand_perror(errno, "event_base_set");
  }

  if (event_add(&(thread->wakeup_event), NULL) < 0)
  {
    gearmand_perror(errno, "event_add");
    return GEARMAND_EVENT;
  }

  thread->is_wakeup_event= true;

  return GEARMAND_SUCCESS;
然后将pip放到 gearmand_thread_st 结构体中
 pthread_ret= pthread_create(&(thread->id), NULL, _thread, thread);
  if (pthread_ret != 0)
  {
    thread->count= 0;
    gearmand_thread_free(thread);

    return gearmand_perror(pthread_ret, "pthread_create");
  }
然后将gearmand_thread_st 做为主线程和子线程的共享数据。当然这个必须要用到锁来保证共享数据的安全

int pthread_ret= pthread_mutex_init(&(thread->lock), NULL);
  if (pthread_ret != 0)
  {
    thread->count= 0;
    gearmand_thread_free(thread);

    return gearmand_fatal_perror(pthread_ret, "pthread_mutex_init");
  }
然后再 create_thread中利用libevent 建立 event loop

 pthread_ret= pthread_create(&(thread->id), NULL, _thread, thread);
  if (pthread_ret != 0)
  {
    thread->count= 0;
    gearmand_thread_free(thread);

    return gearmand_perror(pthread_ret, "pthread_create");
  }
static void *_thread(void *data)
{
  gearmand_thread_st *thread= (gearmand_thread_st *)data;
  char buffer[BUFSIZ];

  int length= snprintf(buffer, sizeof(buffer), "[%6u ]", thread->count);
  if (length <= 0 or sizeof(length) >= sizeof(buffer))
  {
    assert(0);
    buffer[0]= 0;
  }

  (void)gearmand_initialize_thread_logging(buffer);

  gearmand_debug("Entering thread event loop");

  if (event_base_loop(thread->base, 0) == -1)
  {
    gearmand_fatal("event_base_loop(-1)");
    Gearmand()->ret= GEARMAND_EVENT;
  }

  gearmand_debug("Exiting thread event loop");

  return NULL;
}
下回在细说 gearman的网络框架。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值