pthreads - останавливает текущее выполнение потоков и перезапускает их после определенного события - PullRequest
2 голосов
/ 22 июня 2011

Я делаю проект по VoIP, и у меня есть pthreads в моем C-коде. Мне нужно запустить потоки и заставить их работать, поспав между ними. Прямо сейчас мои потоки работают, и когда я получаю завершение сеанса от сервера, мне нужно остановить запущенные потоки и перезапустить их снова с самого начала.

Мой код выглядит примерно так:

void *recv_thread(void *arg)
{
/*receive the multimedia data and close the recv_thread when there is no more data to receive*/
}


void *send_thread(void *arg)
{
/*send the multimedia data*/
}

send_recv_data()
{

pthread_create(thread2, NULL, send_thread, NULL);
pthread_create(thread3, NULL, recv_thread, NULL);
}

void *first_thread(void *arg)
{
/*if some condition met the start the routine for creation of two threads one for receiving and one for sending data*/
if(cond == TRUE){
send_recv_data();
}

}
main()
{
pthread_create(thread1, NULL, first_thread, NULL);
}

Мой вопрос заключается в том, что как только я получаю сообщение от другого пользовательского агента о том, что он не посылает мне больше данных, мне нужно остановить потоки send и recv и, наконец, first_thread, который отвечает за создание двух других потоки. Как только я остановлю все темы, мне нужно перезапустить их снова. Я пытался использовать мьютексы и условные переменные, но все прошло напрасно.

Любая идея о том, как я могу преодолеть это, может быть, небольшая часть простого кода была бы намного полезнее

Спасибо

Ответы [ 2 ]

4 голосов
/ 22 июня 2011

Зачем вам нужно запускать и останавливать темы? Обычно лучше поддерживать потоки в рабочем состоянии и блокировать их чем-либо (например, условной переменной), когда у них нет никакой полезной работы.

1 голос
/ 23 июня 2011

Я собираюсь сделать несколько предположений, потому что, как отметили более знающие люди, чем я, такое поведение немедленно поднимает вопрос , почему вам (кажется, вам) нужно уничтожить / воссоздать эти темы, и почему это так запутано, как это:

  • У вас есть веская причина для удаления / воссоздания потоков
  • У вас есть веская причина для добавления такого количества бесполезных слоев в процесс создания потока
  • Ваш код, который будет «получать сообщение от другого пользовательского агента», имеет доступ к идентификаторам потоков
  • Ваши функции send и recv могут иметь доступ к какому-либо механизму пометки

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

Во-первых, давайте настроим функции send и recv, чтобы они могли получать уведомления о том, что пришло время прощаться:

void* send_thread(void *arg)
{
    pthread_mutex_lock(&wrapUpFlagMutex);
    bool timeToQuit = wrapUpFlag;
    pthread_mutex_unlock(&wrapUpFlagMutex);

    while( timeToQuit == false )
    {
        ...
        // You're doing something here
        ...
        pthread_mutex_lock(&wrapUpFlagMutex);
        timeToQuit = wrapUpFlag;
        pthread_mutex_unlock(&wrapUpFlagMutex);
    }

    // We've been flagged! Get out...the join will catch us.
    pthread_exit();
}

Теперь измените код, который каким-то образом знает, когда магия должна закончиться и перезапуститься:

dontShootTheMessenger()
{
    ...
    // We've just determined that those threads need to be restarted

    // Flag those functions to wrap it up
    pthread_mutex_lock(&wrapUpFlagMutex);
    wrapUpFlag = true;
    pthread_mutex_unlock(&wrapUpFlagMutex);

    // Join the threads, note that this will block
    pthread_join(thread3, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread1, NULL);

    // Flag those functions to...not...wrap it up
    pthread_mutex_lock(&wrapUpFlagMutex);
    wrapUpFlag = false;
    pthread_mutex_unlock(&wrapUpFlagMutex);

    // Launch those puppies again
    pthread_create(thread1, NULL, first_thread, NULL);
    ...
}

Опять же, это мимималистский подход. Более надежный метод, вероятно, будет включать условные переменные, реорганизацию вашей вызывающей структуры, фактически используя переданные аргументы функциям потока и возвращаемые значения для pthread_exit(), и многое другое.

Также, в зависимости от ваших ограничений, вас могут заинтересовать такие функции, как pthread_kill . Обратите внимание, что какой бы дорогой вы ни шли, вы не избавляете себя от каких-либо проблем, просто надеясь, что процесс уничтожения нитей каким-то образом прояснит вам ситуацию.

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