redispthreadslibevhiredis

Asynchronous hiredis with libev and pthread, what am I doing wrong?


I am writing a GUI for a small monochromatic display and I want to update the data on the screen every second.

The data is stored in a redis database and I am trying to coordinate using pthread, libev, and asynchronous hiredis calls.

My plan is to have a thread that pulls new data from the database every second and store a local copy for quick access.

Another thread that updates the screen will access that data at will without having to wait for database access.

First question, is my approach correct?

Second question, why am I having trouble polling the database every second? I think I can switch to a synchronous method and get it to work but is that the right approach?

Here is the relevant code:

int main(int argc, char *argv[])
{
  pthread_t dataThread;
  pthread_t guiThread;

  pthread_create(&dataThread, NULL,  dataHandler, NULL);
  pthread_create(&guiThread, NULL, guiHandler, NULL);

  while (true)
  {
    sleep(10);
  }

  return 0;
}

In the following, if I move ev_loop(EV_DEFAULT_ 0); inside the while loop after the redisAsync commands my callback gets called for the first loop but never again. The way it sits, my callback never gets called.

void* dataHandler(void *ptr)
{ 
  m_ctx = redisAsyncConnect("127.0.0.1", 6379); 
  if (m_ctx->err) {

    printf("Redis async connection failed. Error: %s\n", m_ctx->errstr);
    exit(-1);
  }

  redisLibevAttach(EV_DEFAULT_ m_ctx);
  redisAsyncSetConnectCallback(m_ctx,connectCallback);
  redisAsyncSetDisconnectCallback(m_ctx,disconnectCallback);
  ev_loop(EV_DEFAULT_  0);

  while (true)
  {
    int result;

    result = redisAsyncCommand(m_ctx, updateCallback, (char*)"data1", "HGET data1 data");
    printf("result: %d\n", result);
    result = redisAsyncCommand(m_ctx, updateCallback, (char*)"data2", "HGET data2 data");
    printf("result: %d\n", result);
    //ev_loop(EV_DEFAULT_  0); <- this will work one time
  }

  redisAsyncDisconnect(m_ctx);  
  return 0;
}

void updateCallback(redisAsyncContext *c, void *r, void *privdata)
{
  redisReply *reply = (redisReply*)r;
  if (reply == NULL) return;

  printf("%s: %s\n", (char*)privdata, reply->str);
}

void* guiHandler(void *ptr)
{
  while (true)
  {
    // Update the GUI accordingly
    sleep(1);
  }
}

Solution

  • Firstly, I would recommend you to read the manual for libev before using it : http://man7.org/linux/man-pages/man3/event.3.html

    Now for your code, ev_loop function will start an event loop that you only "feed" it with 2 HGET operations. In order to add more operations you need to add attach events for the event loop but I'm not sure it will be the right approach for you case. If the purpose of your thread is just to fetch the db every X seconds why are you using the async approach at all? IMO just use the hiredis sync API