2012-06-22 2 views
1

Я использую стороннюю библиотеку, которая имеет функцию блокировки, то есть она не вернется, пока она не будет выполнена; Я могу установить тайм-аут для этого вызова.Метод вызова сразу после блокировки вызова

Проблема в том, что эта функция помещает библиотеку в определенное состояние. Как только он войдет в это состояние, мне нужно что-то сделать из своего собственного кода. Моим первым решением было сделать это в отдельной теме:

void LibraryWrapper::DoTheMagic(){ 
    //... 
    boost::thread EnteredFooStateNotifier(&LibraryWrapper::EnterFooState, this); 
    ::LibraryBlockingFunction(timeout_); 
    //... 
} 

void LibraryWrapper::EnterFooState(){ 
    ::Sleep(50); //Ensure ::LibraryBlockingFunction is called first 
    //Do the stuff 
} 

Довольно противный, не так ли? Мне пришлось поставить вызов Sleep, потому что :: LibraryBlockingFunction обязательно нужно вызвать перед тем, что я делаю ниже, или все провалится. Но ждать 50 миллисекунд - довольно плохая гарантия, и я не могу ждать больше, потому что эта конкретная задача должна быть выполнена как можно быстрее.

Нет ли лучшего способа сделать это? Учтите, что у меня нет доступа к коду библиотеки. Ускорение решений приветствуется.

ОБНОВЛЕНИЕ: Как сказано в одном из ответов, API-интерфейс библиотеки не определен. Я отправил электронное письмо разработчикам, объяснив проблему и предложив решение (т. Е. Сделав вызов неблокирующим и отправив событие зарегистрированному обратному сообщению, уведомляющему об изменении состояния). Тем временем я установил тайм-аут достаточно высоким, чтобы обеспечить, чтобы материал X был выполнен, и установите задержку достаточно высоко, прежде чем выполнять работу после вызова, чтобы обеспечить выполнение функции библиотеки. Он не детерминирован, но работает большую часть времени.

+0

Я смущен. Почему вы не можете сделать очевидное и просто делать то, что вам нужно сделать после того, как звонок блокировки вернулся? Почему вторая нить? –

+0

@John: Я интерпретировал проблему как требующую изменения состояния после вызова, но до его возвращения. Я мог ошибаться, хотя ... –

+0

@ Джон: Это похоже на Алекс. Мне нужно сделать это как можно скорее (аппаратные средства) –

ответ

2

Будет ли использование форсированного будущего прояснить этот код? Чтобы использовать пример из boost future documentation:

int calculate_the_answer_to_life_the_universe_and_everything() 
{ 
    return 42; 
} 

boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything); 
boost::unique_future<int> fi=pt.get_future(); 

boost::thread task(boost::move(pt)); 

// In your example, now would be the time to do the post-call work. 

fi.wait(); // wait for it to finish 

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

+0

Эй, это выглядит интересно, +1. Я начну читать о фьючерсах Boost. О задержке, все, что я знаю, заключается в том, что 'LibraryBlockingFunction' должен быть запущен, чтобы иметь возможность выполнять изменение после вызова. У меня плотный контакт с разработчиками библиотеки, поэтому я могу попросить об изменении API, но это может занять некоторое время. –

2

Проблема, как я понимаю, это то, что вам нужно сделать, это:

  1. Введите блокирующий вызов
  2. После того, как вы ввели блокирующий вызов, но до его завершения, вам нужно сделать что-то другое
  3. вы должны иметь законченный # 2 до вызова блокировки возвращает

с чисто C++ точки зрения, нет никакого способа, вы можете accomish это детерминированным образом. Это не понимает детали библиотеки, которую вы используете.

Но я заметил ваше значение таймаута. Может быть, это может быть лазейкой.

Что делать, если вы:

  1. Введите блокирующий вызов с тайм-аута нуля, так что она немедленно возвращает
  2. ли вам другие вещи, либо в том же потоке или синхронно с основным потоком. Возможно, используя барьер.
  3. После проверки №2 снова введите блокирующий вызов с нормальным ненулевым таймаутом.

Это будет работать, только если состояние библиотеки изменится, если вы введете блокирующий вызов с нулевым таймаутом.

+0

Невозможно установить тайм-аут на ноль: это означало бы, что аппаратное обеспечение A не будет ждать действия аппаратного B вообще; таймаут связан со временем, когда аппаратное обеспечение A останется в состоянии S, ожидая, когда произойдет X. –

Смежные вопросы