3

Trying to write a simple Redis client using hiredis and libev libraries. Everything is going well, except stopping event loop - m_thread.join() just stuck. Moving all initializing stuff to the newly created thread does nothing.

Here is part of my code:


    void RedisSubscriber::Start() {
        m_redis = redisAsyncConnect(m_addr.c_str(),m_port);
        m_redis->data = (void*)this;

        m_loop = ev_loop_new(EVFLAG_NOINOTIFY);
        redisLibevAttach(m_loop, m_redis);
        redisAsyncSetConnectCallback(m_redis,connectCallback);
        redisAsyncSetDisconnectCallback(m_redis,disconnectCallback);
        redisAsyncCommand(m_redis, subscribeCallback, NULL, "SUBSCRIBE %s", m_channel.c_str());

        m_thread = boost::thread(ev_loop,m_loop,0);
    }

    void RedisSubscriber::Stop() {
        redisAsyncFree(m_redis);
        m_thread.join();
        m_redis = 0;
    }

    void RedisSubscriber::connectCallback(const redisAsyncContext *c) {

    }

    void RedisSubscriber::disconnectCallback(const redisAsyncContext *c, int status) {
        RedisSubscriber* r = (RedisSubscriber*)(c->data);
        ev_unloop(r->m_loop,EVUNLOOP_ALL);
    }

    void RedisSubscriber::subscribeCallback(redisAsyncContext *c, void *r, void *privdata) {

    }

2 Answers2

1

Assuming that you mean ev_run for your boost::thread, here's what you can do:

  1. Setup an ev_async

  2. In the callback of ev_async call ev_break.

  3. Call ev_async_send from RedisSubscriber::Stop(). ev_async watchers are thread-safe -- it uses memory barriers for synchronising between threads.

This will cause the event loop to stop, and m_thread.join() will return.

themoondothshine
  • 2,983
  • 5
  • 24
  • 34
0

It seems your use of boost::thread() is incorrect. For one, ev_loop is a type, not a function.

Ioan
  • 2,382
  • 18
  • 32