2009-08-05 8 views
2

Follow-up-Frage: This questionWie Betriebssystem Rückrufe arbeiten

Wie in der verknüpften Frage beschrieben, haben wir eine API, die ein Ereignis aussehen verwendet diese Umfragen() wählen Benutzer definiert Rückrufe zu handhaben.

Ich habe eine Klasse mit diesem wie solche:

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 
    } 
}; 

Die Idee dahinter ist, dass man Function genannt werden wollen, wenn sowohl die Bedingung wahr ist oder wenn der Timer auf. Kein komplexes Konzept. Was ich mich wundere, ist, wenn FunctionName sowohl in der start() - Funktion als auch durch den Callback zur gleichen Zeit aufgerufen wird? Dies könnte einige Speicherbeschädigungen für mich verursachen, da sie auf einen nicht threadsicheren Teil des gemeinsamen Speichers zugreifen.

Meine Tests sagen mir, dass sie in verschiedenen Threads laufen (Korruption nur, wenn ich die Ereignisse verwende), obwohl: cout<<pthread_self()<<endl; sagt, sie haben die gleiche Thread-ID.

Kann mir jemand erklären, wie diese Rückrufe abgezweigt werden? Welcher Reihenfolge werden sie gerecht? In welchen Thread laufen sie? Ich nehme an, dass sie in dem Thread ausgeführt werden, der die select() ausführt, aber wann erhalten sie dieselbe Thread-ID?

+0

sollte markiert werden als C nicht C++ – Tom

+0

@Tom, das Codebeispiel ist offensichtlich C++ ... – bdonlan

Antwort

3

Die wirkliche Antwort würde von der Implementierung von Timer abhängen, aber wenn Sie Callbacks vom selben Thread ausführen, ist es am wahrscheinlichsten, signals oder posix timers zu verwenden. So oder so, select() ist überhaupt nicht beteiligt.

Mit Signalen und Posix-Timer können Sie vom Signal-Handler nur wenig tun. Es dürfen nur bestimmte spezifische signalsichere Aufrufe wie read() und write() (NOT fred() und fwrite(), oder auch new und cout) verwendet werden. In der Regel, was man tun wird, ist write() zu einem pipe oder eventfd, dann in einem anderen Thread, oder Ihre Main-Event-Schleife mit Select(), beachten Sie diese Benachrichtigung und behandeln Sie es. So können Sie das Signal sicher handhaben.

+0

Sie haben Recht. Select ist nur vorhanden, da die Event-API sowohl select() - Ereignisse als auch Timer behandelt. >. Alex

+0

Übrigens, Apis mit Signalen sind wirklich ziemlich schmerzhaft mit zu arbeiten. Ermutigen Sie denjenigen, der es geschafft hat, diese Callbacks als reguläre Funktionen in einem Thread auszuführen, so dass sie nur Sperren auslösen müssen :) – bdonlan

+0

Für jetzt habe ich das gerade mit meiner eigenen Schleife für die Ereignisse umgangen. Widerlich, ich weiß, aber zumindest kann ich sie ordentlich thread sicher machen ... – Alex

1

Ihr Code wie geschrieben wird nicht kompilieren, noch weniger ausführen. Beispiel :: Funktionsname muss statisch sein und muss eine Objektreferenz verwenden, die als Callback-Funktion verwendet werden soll.

Wenn die Timer in separaten Threads ausgeführt werden, kann diese Funktion von drei verschiedenen Threads aufgerufen werden.