Вызов функции одновременно в отдельном потоке - PullRequest
0 голосов
/ 20 июня 2011

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

Но проблема в том, что если я вызываю функцию из дочернего потока, то только один поток может работать с этой функцией (fromByte). Например, если поток 1 вызвал функцию, то другой поток не сможет войти в функцию.

void WorkHandler::workLoop(){
    printf("WorkHandler::workLoop, called\n");

    while(m_workHandlerRun){
        Work *work = getWork();
        char *pdata = work->getMsg();
        /*
         * Get type only
         */
        unsigned char type = pdata[0];

        printf("WorkHandler::workLoop, type %d\n", type);

        Packet *packet = m_packetFactory->createInstance(static_cast<PACKET_TYPES>(type));
        packet->fromByte(pdata);
    }
}

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

bool WorkHandler::initThreads(){

    for(int i=0; i < m_maxThreads; i++){
        pthread_t *thread(new pthread_t);
        m_workThreadList.push_back(thread);

        if(pthread_create(thread, NULL, runWorkThread, reinterpret_cast<void *>(this))!=0){
            perror("WorkHandler::initThreads, pthread_create error \n");
            return false;
        }

        pthread_detach(*thread);
    }

    return true;
}

Так я порождаю поток, а runWorkThread - статический метод для вызова функции workLoop. Как мне исправить мой код, чтобы дочерние потоки могли работать с функцией одновременно. Заранее спасибо ..

Редактировать

Я блокирую и разблокирую вот так

void WorkHandler::addWork(Work* w){
    printf("WorkHandler::insertWork Thread, insertWork locking \n");
    lock();
    printf("WorkHandler::insertWork Locked, and inserting into queue \n");
    m_workQueue.push(w);
    signal();
    unLock();
}

Work* WorkHandler::getWork(){
    printf("WorkHandler::getWork, locking (tid : %lu) \n", pthread_self());
    lock();
    printf("WorkHandler::getWork, locked (tid : %lu) \n", pthread_self());
    while(m_workQueue.empty()){//Need 'while' instead of 'If'
        printf("WorkHandler::getWork, waiting... (tid : %lu) \n", pthread_self());
        wait();
        printf("WorkHandler::getWork, waiting DONE (tid : %lu) \n", pthread_self());
    }
    Work *work = m_workQueue.front();
    printf("WorkHandler::getWork, got a job (tid : %lu) \n", pthread_self());
    m_workQueue.pop();
    unLock();

    return work;
}

Кроме того, этот класс расширяет созданный мною класс MutexdCondtion. MutexCondition.cpp file

bool MutexCondition::init(){
    printf("MutexCondition::init called\n");
    pthread_mutex_init(&m_mut, NULL);
    pthread_cond_init(&m_con, NULL);
    return true;
}

bool MutexCondition::destroy(){
    pthread_mutex_destroy(&m_mut);
    pthread_cond_destroy(&m_con);
    return true;
}

bool MutexCondition::lock(){
    pthread_mutex_lock(&m_mut);
    return true;
}

bool MutexCondition::unLock(){
    pthread_mutex_unlock(&m_mut);
    return true;
}

bool MutexCondition::wait(){
    pthread_cond_wait(&m_con, &m_mut);
    return true;
}

bool MutexCondition::signal(){
    pthread_cond_signal(&m_con);
    return true;
}

1 Ответ

0 голосов
/ 20 июня 2011

проблема в том, что если я позвоню функция из дочернего потока тогда разрешено работать только одному потоку

Если вы основываете это предположение на своем printf, то вы ошибаетесь. Возможно, что рабочий поток завершает свою работу до того, как новый элемент будет помещен в очередь. Это создает возможность того, что одна и та же функция будет подбирать два элемента подряд.

Не существует способа, чтобы другие потоки ожидали рабочего, поскольку нет ничего, что блокирует их после возврата getWork ().

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