Асинхронный Hiredis с libev и pthread, что я делаю не так? - PullRequest
0 голосов
/ 29 августа 2018

Я пишу графический интерфейс для небольшого монохромного дисплея и хочу обновлять данные на экране каждую секунду.

Данные хранятся в базе данных redis, и я пытаюсь координировать их с помощью вызовов pthread, libev и асинхронных вызовов hiredis.

Мой план - создать поток, который каждую секунду извлекает новые данные из базы данных, и хранить локальную копию для быстрого доступа.

Другой поток, который обновляет экран, получит доступ к этим данным по своему усмотрению, не дожидаясь доступа к базе данных.

Первый вопрос, мой подход правильный?

Второй вопрос, почему у меня возникают проблемы с опросом базы данных каждую секунду? Я думаю, что могу переключиться на синхронный метод и заставить его работать, но это правильный подход?

Вот соответствующий код:

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;
}

В следующем случае, если я переместу ev_loop(EV_DEFAULT_ 0); внутри цикла while после команд redisAsync, мой обратный вызов будет вызван для первого цикла, но больше никогда. Как он сидит, мой обратный вызов никогда не вызывается.

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);
  }
}

1 Ответ

0 голосов
/ 11 сентября 2018

Во-первых, я бы порекомендовал вам прочитать руководство для libev перед его использованием: http://man7.org/linux/man-pages/man3/event.3.html

Теперь для вашего кода, Функция ev_loop запустит цикл обработки событий, который вы «кормите» только двумя операциями HGET. Чтобы добавить больше операций, вам нужно добавить события присоединения для цикла событий, но я не уверен, что это будет правильным подходом для вашего случая. Если целью вашего потока является просто получение базы данных каждые X секунд, почему вы вообще используете асинхронный подход? IMO просто используйте API синхронизации hiredis

...