简体   繁体   English

C++ libhiredis 带有 libev 和自定义事件循环

[英]C++ libhiredis with libev and custom event loop

My application uses libhiredis with libev backend.我的应用程序使用带有 libev 后端的 libhiredis。 I need to send Redis async commands and process the resulting Redis async callback.我需要发送 Redis 异步命令并处理生成的 Redis 异步回调。 However, unlike the simple example from here I cannot use the default event loop.但是,与此处的简单示例不同,我不能使用默认事件循环。 The following code approximates the example with a custom event loop.以下代码使用自定义事件循环近似示例。 However, when compiled with only the redisLibevAttach() induced libev io watcher, the event loop thread terminates immediately.但是,当仅使用redisLibevAttach()诱导的 libev io 观察程序进行编译时,事件循环线程会立即终止。 You can see this by running您可以通过运行看到这一点

g++ -g -std=c++11 -Wall -Wextra -Werror hiredis_ev.cpp -o hiredis_ev -lpthread -lhiredis -lev && gdb ./hiredis_ev

where GDB happily prints that a new thread is created and almost immediately terminates. GDB 高兴地打印出一个新线程已创建并几乎立即终止。 This is further confirmed by running info thread in GDB which does not show my_ev_loop .通过在 GDB 中运行未显示my_ev_loopinfo thread进一步证实了这一点。 However, if I change the code to add any other libev watcher, like a timer, then everything is good.但是,如果我更改代码以添加任何其他 libev 观察程序,例如计时器,那么一切都很好。 You can see this by running您可以通过运行看到这一点

g++ -g -DTIMER -std=c++11 -Wall -Wextra -Werror hiredis_ev.cpp -o hiredis_ev -lpthread -lhiredis -lev &&  ./hiredis_ev

I should not need a dummy libev timer to keep the event loop running.我不应该需要一个虚拟的 libev 计时器来保持事件循环运行。 What am I missing?我错过了什么?

#include <iostream>
#include <thread>
#include <hiredis/hiredis.h>
#include <hiredis/async.h>
#include <hiredis/adapters/libev.h>

static struct ev_loop *loop = nullptr;
static void redis_async_cb(redisAsyncContext *, void *, void *)
{
  std::cout << "Redis async callback" << std::endl;
  fflush(nullptr);
}

#ifdef TIMER
  static ev_timer timer_w;
  static void ev_timer_cb(EV_P_ ev_timer *, int)
  {
    std::cout << "EV timer callback" << std::endl;
    fflush(nullptr);
  }
#endif

int main()
{
  loop = ev_loop_new(EVFLAG_AUTO);

#ifdef TIMER
  ev_timer_init(&timer_w, ev_timer_cb, 0, 0.1);
  ev_timer_start(loop, &timer_w);
#endif

  redisAsyncContext* async_context = redisAsyncConnect("localhost", 6379);
  if (nullptr == async_context)
  {
    throw std::runtime_error("No redis async context");
  }

  redisLibevAttach(loop, async_context);
  std::thread ev_thread(ev_run, loop, 0); 
  pthread_setname_np(ev_thread.native_handle(), "my_ev_loop");
  ev_thread.detach();

  // Give the event loop time to start
  while (!ev_iteration(loop))
  {
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  }

  // Send a SUBSCRIBE message which should generate an async callback
  if (REDIS_OK != redisAsyncCommand(async_context, redis_async_cb, nullptr, "SUBSCRIBE foo"))
  {
    throw std::runtime_error("Could not issue redis async command");
  }
  std::cout << "Waiting for async callback" << std::endl;
  fflush(nullptr);
    fflush(nullptr);

  // Wait forever (use CTRL-C to terminate)
  while (true)
  {
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  }

  return 0;
}

I found out that hiredis community has their own GitHub instance where I can ask questions.我发现hiredis 社区有他们自己的GitHub 实例,我可以在其中提问。 Since I had't yet received the answer here, I asked there.由于我在这里还没有收到答案,所以我在那里问。 The answer can be found at https://github.com/redis/hiredis/issues/801#issuecomment-626400959答案可以在https://github.com/redis/hiredis/issues/801#issuecomment-626400959找到

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM