boost :: this_thread :: sleep_ для сна всей программы - PullRequest
1 голос
/ 18 июня 2020

C ++ 98 и Boost 1.54

Мне сложно понять, почему при использовании boost::this_thread::sleep_for вся моя программа спит. Единственный раз и место, где вызывается функция Wait(), - это внутри этого потока, и единственная цель этого потока - прочитать имена файлов в каталоге и инициировать загрузку.

Но по какой-то причине, когда он достигает Строка boost::this_thread::sleep_for в функции Wait(), она висит там и засыпает также все остальные потоки. Я не уверен, что мне не хватает, поэтому любая помощь будет принята с благодарностью.

Код:

void Upload::ReadFileNames()
{
    cout << "[DEBUG] ReadFileNames -> A " << endl;
    Wait();  
    cout << "[DEBUG] ReadFileNames -> B " << endl;


    // read filename stuff
}

void Upload::Wait()
{
    typedef boost::chrono::duration<long, boost::ratio<60> > seconds;
    int randomWaitTime = 0;
    try{   
        randomWaitTime = lexical_cast<unsigned int>(getId());
        randomWaitTime = randomWaitTime * 10;
    }
    catch ( const boost::bad_lexical_cast & e){
        // cout << "[LOG] FileUpLoad : Wait : bad_lexical_cast : "  << e.what() << endl ;
        randomWaitTime = 0;
    }

    seconds testTimeToWait(randomWaitTime);

    cout << "[DEBUG] Wait() -> A" << endl;
    boost::this_thread::sleep_for(testTimeToWait);
    cout << "[DEBUG] Wait() -> B" << endl;

    cout << "RANDOM WAIT TIME = " << randomWaitTime << endl;
}

основной. cpp

int  main()
{   
    pthread_t threadA; 
    pthread_create(&threadA,NULL,threadAfn,NULL);

    pthread_t threadB;
    pthread_create(&threadB,NULL,threadBfn,NULL);

    pthread_t Upload;    //  <--- Thread in question
    pthread_create(&Upload,NULL,Uploadfn,NULL);

    pthread_join(threadA,NULL);
    pthread_join(threadB,NULL);
    pthread_join(Upload,NULL); // <--- Thread in question

    return 0; 
}

Выход

[DEBUG] ReadFileNames -> A 
[DEBUG] Wait() -> A
// hangs here and rest of the threads are locked/slept as well?

1 Ответ

0 голосов
/ 18 июня 2020

он висит там и спит и все другие потоки

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

Ищите вещи, которые блокируют (mutex.lock, condition wait, IO операции, et c.) или убедитесь, что потоки не завершились.

Примечания

  1. Ваши seconds вычисления отключены. В моей системе следующее:

    Live On Coliru

    #include <boost/chrono.hpp>
    #include <iostream>
    
    int main() {
        std::cout << boost::chrono::duration<long, boost::ratio<60> >(1)/boost::chrono::seconds(1) << std::endl;
    }
    

    Печать

    60
    

    Итак, что вы по имени seconds на самом деле минут. Вместо этого просто сделайте это:

    using boost::chrono::seconds;
    int delay = std::strtoul(getId().c_str(), NULL, 10)*10;
    sleep_for(seconds(delay));
    
  2. Ваша случайная задержка будет случайной, только если возврат getId. Используя boost/random.hpp, вы можете сделать его действительно случайным с хорошим контролем дальности. Например, чтобы засыпать между 1'000 и 3'000 мс:

    int random_gen (int low, int high) {// не потокобезопасное состояние c boost :: random_device rdev; stati c boost :: mt19937 prng (rdev); return boost :: uniform_int <> (низкий, высокий) (prng); }

    void Upload :: Wait () {int const ms_delay = random_gen (1000, 3000); cout << "RANDOM WAIT TIME =" << ms_delay << endl; sleep_for (миллисекунды (ms_delay)); } </p>

    Обратите внимание, что для начального числа с использованием random_device, как показано (так что истинное случайное начальное число), вам необходимо связать случайную библиотеку. В противном случае вы можете «st oop» на основе начального числа:

     static boost::mt19937 prng(std::time(NULL));
    

Вот автономная версия вашего кода с различными примененными предложениями, демонстрируя отсутствие взаимоблокировки / программной блокировки:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/chrono.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <boost/random.hpp>

using boost::this_thread::sleep_for;
using boost::chrono::seconds;
using boost::chrono::milliseconds;

using boost::lexical_cast;
using std::cout;
using std::endl;

struct Upload {
    std::string getId() const { return "42"; }
    void Wait();
    void ReadFileNames();
};

void Upload::ReadFileNames() {
    cout << "[DEBUG] ReadFileNames -> A " << endl;
    Wait();
    cout << "[DEBUG] ReadFileNames -> B " << endl;

    // read filename stuff
}

int random_gen(int low, int high) { // not threadsafe
    static boost::mt19937 prng(std::time(NULL));
    return boost::uniform_int<>(low, high)(prng);
}

void Upload::Wait() {
    int const ms_delay = random_gen(1000, 3000);
    cout << "RANDOM WAIT TIME = " << ms_delay << endl;
    sleep_for(milliseconds(ms_delay));
}

void background(char const* name) {
    // desync different background threads
    sleep_for(milliseconds(boost::hash_value(name) % 1000));

    for (int i=0; i<5; ++i) {
        sleep_for(seconds(1));
        std::clog << name << " " << i << std::endl;
    }
}

void threadAfn() { background("thread A"); }
void threadBfn() { background("thread B"); }

void Uploadfn() {
    Upload u;
    u.ReadFileNames();
}

int main() {
    boost::thread threadA(threadAfn);
    boost::thread threadB(threadBfn);
    boost::thread Upload(Uploadfn);

    threadA.join();
    threadB.join();
    Upload.join();
}

Печать, например:

[DEBUG] ReadFileNames -> A 
RANDOM WAIT TIME = 1150
[DEBUG] ReadFileNames -> B 
thread A 0
thread B 0
thread A 1
thread B 1
thread A 2
thread B 2
thread A 3
thread B 3
thread A 4
thread B 4
...