C++: Как реализовать тайм-аут для произвольного вызова функции?

В вашей функции есть какая-то логическая ошибка declareNewMayor.

1> Вы присвоили строковый литерал символьной переменной winner. Это приведет к неопределенному поведению

 winner = "A";
 winner = "B";
 winner = "C";

. Поэтому его следует заменить на:

 winner = 'A';
 winner = 'B';
 winner = 'B';

2> if ... else в функции declareNewMayor. Вы не проверяете другие случаи. Например: aStatesWon == bStatesWon == cStatesWon == dStatesWon. Как результат в этом случае? если вас не волнуют другие случаи, вы можете инициализировать 2 переменные winner, statesWon с некоторым значением, которое позволяет избежать неопределенного поведения с неинициализированной переменной (вот почему ваш вывод странный с -2324252 или 62341). Вот мое решение

void declareNewMayor(int aStatesWon, int bStatesWon, int cStatesWon, int dStatesWon)
{

char winner = '?';
int statesWon = 0;

if (aStatesWon > bStatesWon&&aStatesWon > cStatesWon&&aStatesWon > dStatesWon)
{

    statesWon = aStatesWon;
    winner = 'A';
}
else if (bStatesWon > aStatesWon&&bStatesWon > cStatesWon&&bStatesWon > dStatesWon) {


    statesWon = bStatesWon;
    winner = 'B';
}
else if (cStatesWon > aStatesWon&&cStatesWon > bStatesWon&&cStatesWon > dStatesWon) {


    statesWon = cStatesWon;
    winner = 'C';
}
else if (dStatesWon > aStatesWon&&dStatesWon > cStatesWon&&dStatesWon > aStatesWon) {


    statesWon = dStatesWon;
    winner = 'D';
}


printf("The new Mayor is candiate %c with %d states won!", winner,statesWon);



}//calculate new mayor and declare it
27
задан Frank 18 May 2009 в 21:20
поделиться

8 ответов

Вы можете создать boost :: thread для вызова API:

boost::thread api_caller(::api_function, arg1, arg2);
if (api_caller.timed_join(boost::posix_time::milliseconds(500)))
{
    // API call returned within 500ms
}
else
{
    // API call timed out
}

Boost не позволяет вам убить рабочий поток. В этом примере он просто осиротел.

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

18
ответ дан 28 November 2019 в 05:03
поделиться

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

15
ответ дан 28 November 2019 в 05:03
поделиться

То, о чем вы говорите, обычно называется «сторожевой» системой. Сторожевой таймер обычно представляет собой второй поток, который проверяет состояние всех других потоков. Сторожевой таймер обычно настроен на периодическую работу. Если от других потоков не было получено ответа, сторожевое устройство может уведомить пользователя или даже убить нарушивший поток, если это возможно сделать безопасно (в зависимости от вашего приложения).

8
ответ дан 28 November 2019 в 05:03
поделиться

Что вам нужно, так это поток и Future Object , который может хранить результат вызова функции.

Пример использования повышения см. здесь .

Вам нужно будет проверить будущее после тайм-аута, и если оно не установлено, действовать соответственно.

1
ответ дан 28 November 2019 в 05:03
поделиться

Монитор выполнения Boost.Test делает то, что вы хотите:

http://www.boost.org/doc/libs/1_39_0/libs/test/doc/html/execution-monitor/reference.html#boost. Execution_monitor

3
ответ дан 28 November 2019 в 05:03
поделиться

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

3
ответ дан 28 November 2019 в 05:03
поделиться

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

Пример: когда вы завершаете поток, пока происходит выделение памяти, возможно, куча вашего процесса повреждена.

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

Вы можете, как предлагает Бен Штрауб, просто осиротить поток: установить для него самый низкий приоритет и позволить ему работать бесконечно. Это, конечно, только ограниченное решение: если поток потребляет ресурсы (вероятно), они замедлят работу системы, также существует ограничение на количество потоков на процесс (обычно из-за адресного пространства для стека потоков).

Как правило, я ' Я предпочитаю решение внешнего процесса. Вот простой шаблон:
Записать входные данные в файл, запустить внешний процесс с файлом в качестве аргумента. Внешний процесс записывает прогресс (если таковой имеется) в файл на диске, который можно отслеживать, и даже может позволить процессу возобновиться с того места, где он был запущен. Результаты записываются на диск, и родительский процесс может их считывать.

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

3
ответ дан 28 November 2019 в 05:03
поделиться

Перейдите к процессу-сироте, запустите его и рассчитайте время его выполнения. Если время истекает, вызовите ОС, чтобы убить его.

Как избежать гонок. по этому шаблону:

  • создать файл для хранения в args (конечно, все передается как VAL). Сиротскому процессу разрешено только читать данные из этого файла.

  • Сиротский процесс обрабатывает входные данные, создает выходной файл со значениями результатов и закрывает его.

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

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

1
ответ дан 28 November 2019 в 05:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: