2015-11-14 3 views
2

Я не уверен, будет ли std::thread работать под Cygwin. Единственные должности, которые я нахожу, - это годы и имеют дело с ошибками компилятора. Так что эта проблема немного другая.Неожиданные результаты с std :: thread под Cygwin

Я переношу приложение из Linux в Cygwin. Он использует несколько потоков с std::thread и работает, за исключением одного: в одном месте звонок std::thread::detach() сбрасывает Invalid argument, хотя std::thread::joinable() возвращает true.

Я попытался построен пример:

#include<thread> 
#include<iostream> 
#include<mutex> 
#include<condition_variable> 

std::thread* t; 
std::mutex m; 
std::condition_variable cv; 

void func(void) 
try 
{ 
    std::cout << "func" << std::endl; 
    if (t->joinable()) 
    { 
     std::cout << "t is joinable" << std::endl; 
     t->detach(); 
     delete t; 
     std::unique_lock<std::mutex> lck(m); 
     cv.notify_all(); 
    } 
} 
catch(std::exception& e) 
{ 
    std::cout << "exception in func: " << e.what() << std::endl; 
} 


int main(void) 
{ 
    try 
    { 
     std::unique_lock<std::mutex> lck(m); 
     t=new std::thread(&func); 
     cv.wait(lck); 
     std::cout << "func finished" << std::endl; 
     cv.wait(lck); 
    } 
    catch(std::exception& e) 
    { 
     std::cout << "exception in main: " << e.what() << std::endl; 
    } 

    return(0); 
} 

компилировать это на Linux с

g++ -std=c++0x -pthread example.cc 

с использованием GCC версии 4.6.3. Он производит

func 
t is joinable 
func finished 

затем вешает на неопределенное время каждый раз, который, как ожидается, поведение в связи со вторым, непревзойденная вызова cv.wait().

На Cygwin компилировать с

g++ -std=c++11 -pthread example.cc 

с использованием GCC версии 4.9.3.

Это иногда показывает описанное выше поведение, иногда это просто показывает

func 

затем выходит с 0.

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

+0

Ваш второй вызов 'cv.wait()' скорее всего, будет заблокирован навсегда - вам больше нечего будет уведомлять 'cv'. –

+0

Не просто вероятно ... это было бы ожидаемым поведением. Я добавил второй вызов 'cv.wait()', чтобы подчеркнуть, что Cygwin в некоторых случаях игнорирует 'cv.wait()' alltogether.В Linux он всегда блокируется навсегда, что ожидается, под Cygwin он иногда выходит. – TFM

+0

Ну, ты сказал, что он висит бесконечно, не упоминая, что ты считал это успешным. –

ответ

1

Ваша опубликованная программа содержит неопределенное поведение. Там два потока (main и func) участвуют в гонке для доступа t (это обычный, неатомный необработанный указатель).

Что происходит с программами, которые содержат неопределенное поведение, включает (но не ограничивается) носовые демоны. Таким образом, как linux, так и cygwin, похоже, работают в этом смысле, только носовые демоны бывают разных типов.

+0

Да, это проблема с приведенным выше примером. Хотя я все еще не удовлетворен, потому что не вижу, как это приводит к пропуску вызовов 'cv.wait()'. – TFM

1

Во-первых, вы, вероятно, жертвой поддельного просыпаются ....

Реализация разрешается будить переменной условия, так это ваша ответственность, чтобы убедиться, что условие выполняется ... Вы может сделать это путем подачи дополнительного аргумента в cv.wait()

Пожалуйста, см: http://www.cplusplus.com/reference/condition_variable/condition_variable/wait/

Во-вторых, получение только «Func» в качестве выходного сигнала с возбужденном ноль (0) меня беспокоит. Потому что этого не должно быть вообще.

По крайней мере, «func finished» должен быть напечатан, потому что вы сбросили поток: std :: endl;