Как работают обратные вызовы операционной системы - PullRequest
2 голосов
/ 05 августа 2009

Задайте вопрос: Этот вопрос

Как описано в связанном вопросе, у нас есть API, который использует просмотр событий, который опрашивает select () для обработки пользовательских обратных вызовов.

У меня есть класс, использующий это как:

class example{
 public:
    example(){
        Timer* theTimer1 =  Timer::Event::create(timeInterval,&example::FunctionName);
        Timer* theTimer2 =  Timer::Event::create(timeInterval,&example::FunctionName);
        start();
       cout<<pthread_self()<<endl;
    }
  private:
     void start(){
        while(true){
           if(condition)
              FunctionName();
           sleep(1);
        }
     }
     void FunctionName(){
         cout<<pthread_self()<<endl;
         //Do stuff
     }
};

Идея заключается в том, что вы хотите, чтобы FunctionName вызывалось как в случае выполнения условия, так и при включенном таймере. Не сложная концепция. Что мне интересно, так это если FunctionName будет вызываться как в функции start (), так и при обратном вызове одновременно? Это может привести к некоторому повреждению памяти для меня, так как они получают доступ к не поточно-безопасной части общей памяти.

Мое тестирование говорит мне, что они работают в разных потоках (повреждение только при использовании событий), хотя: cout<<pthread_self()<<endl; говорит, что они имеют одинаковый идентификатор потока.

Может кто-нибудь объяснить мне, как эти обратные вызовы разветвляются? Какой порядок они получают? В каком потоке они работают? Я предполагаю, что они работают в потоке, который выполняет select (), но когда же они получают тот же идентификатор потока?

Ответы [ 2 ]

3 голосов
/ 05 августа 2009

Реальный ответ будет зависеть от реализации Timer, но если вы получаете обратные вызовы, запускаемые из того же потока, он, скорее всего, использует сигналов или posix таймеров . В любом случае, select () вообще не задействован.

С помощью сигналов и posix-таймеров очень мало что можно сделать безопасно из обработчика сигналов. Только определенные определенные безопасные вызовы сигналов, такие как read () и write () ( NOT fread () и fwrite (), или даже new и cout) разрешено использовать Обычно то, что нужно сделать, это записать () в pipe или eventfd , затем в другом потоке или цикле основного события, выполняющем select (), заметить это уведомление и обработать его. Это позволяет вам безопасно обрабатывать сигнал.

1 голос
/ 05 августа 2009

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

Если таймеры работают в отдельных потоках, эта функция может быть вызвана тремя разными потоками.

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