io_servie implementiert eine Aufgabenwarteschlange, wobei die Aufgabe die Funktion void(void) ist. Die beiden am häufigsten verwendeten Schnittstellen von Io_servie sind Post und Run. Post liefert Aufgaben in der Warteschlange, bis alle ausgeführt sind, und Run kann von N Threads aufgerufen werden. Io_service ist eine vollständig threadsichere Warteschlange.
boost::io_service-Interpretation
asio ist eine von Boost bereitgestellte asynchrone C++-Programmiermodellbibliothek. Ihre Kernklasse io_service stellt Aufgabenwarteschlangen- und Aufgabenverteilungsfunktionen hauptsächlich in der Multithread-Programmierung bereit Wird als Ereignistreiber in der IO-Programmierung verwendet (Abschlussport, Auswahl, Umfrage, Epoll usw.).
Warteschlangenmodell
Jeder io_service verfügt über eine öffentliche Aufgabenwarteschlange und mehrere private Aufgabenwarteschlangen. Die öffentliche Warteschlange wird von jedem Thread gemeinsam genutzt und die private Warteschlange ist exklusiv für jeden Thread.
Der Aufgabenausführungsprozess von io_service ist ungefähr wie folgt:
Rufen Sie die Ausführungsmethode auf und geben Sie die Hauptschleife ein; >
- Stellen Sie fest, ob die öffentliche Warteschlange leer ist. Wenn die Anzahl der Aufgaben größer als 1 ist, wecken Sie gleichzeitig andere inaktive Threads Zeit;
- Die Aufgabenausführung ist abgeschlossen und die Aufgaben in der privaten Warteschlange jedes Threads werden in die öffentliche Aufgabenwarteschlange verschoben
- Löst den Reaktor aus. Wenn ein Ereignis vorliegt, wird es in die private Warteschlange gestellt.
- Wenn die Warteschlange leer ist, fügen Sie den aktuellen Thread zur Leerlauf-Thread-Warteschlange hinzu und wechseln Sie in den Wartezustand, in dem Sie darauf warten, dass andere Threads aufwachen (task_operation).
- Wenn der Benutzer post aufruft, wird die Aufgabe direkt an die öffentliche Warteschlange op_queue übermittelt.
Thread-Pool-Modell
Es gibt zwei häufig verwendete Thread-Pool-Modelle:
Eines besteht darin, dass mehrere Threads eine Aufgabenwarteschlange teilen und der Benutzer sie platziert Wird die Aufgabe in die Aufgabenwarteschlange gestellt, konkurrieren andere Threads darum, die Aufgabenausführung aus der Warteschlange zu erhalten. In Kombination mit boost::thread kann der Thread-Pool durch Aufrufen der Ausführungsmethode in mehreren Threads realisiert werden:
using namespace boost;
using namespace boost::asio;
io_service ios;
int thread_num = 10;
thread *t[thread_num] = {0};
// 创建线程池
for(int i = 0; i < thread_num; ++i)
{
t[i] = new thread(bind(&io_service::run, &ios));
}
// 向任务队列中投递任务,该任务将随机由一个调用run方法的线程执行
ios.post(func);
// 等待线程退出
for(int i = 0; i < thread_num; ++i)
{
t[i]->join();
}
Nach dem Login kopieren
Es ist leicht zu erkennen, dass der Engpass dieser Art von Thread-Pool eine Aufgabenwarteschlange ist, und zwar mehrere Threads konkurrieren um Zugriff, was bei großen gleichzeitigen Programmen leicht zu Leistungseinbußen führen kann.
Das andere ist, dass jeder Thread eine Aufgabenwarteschlange verwaltet, die Aufgaben zufällig oder abwechselnd an eine der Aufgabenwarteschlangen senden kann. Die Aufgaben in der Aufgabenwarteschlange können nur von dem Thread verbraucht werden es liegt. Diese Art von Thread-Pool verfügt im Boost-Beispiel auch über eine entsprechende Implementierung (io_service_pool). Die grundlegende Methode besteht darin, mehrere io_service-Objekte zu erstellen, die jeweils einem Thread entsprechen. Der Code lautet wie folgt:
using namespace boost;
using namespace boost::asio;
int thread_num = 10;
io_service ios[thread_num];
thread *t[thread_num] = {0};
// 创建线程池
for(int i = 0; i < thread_num; ++i)
{
t[i] = new thread(bind(&io_service::run, &ios[i]));
}
// 轮训投递任务
for(int i = 0; i < thread_num; ++i)
{
ios[i].post(func);
}
// 等待线程退出
for(int i = 0; i < thread_num; ++i)
{
t[i]->join();
}
Nach dem Login kopieren
Das Folgende ist ein Klassendiagramm, das auf einer Linux-Umgebung basiert, da einige Klassen unter Windows unterschiedliche Definitionen haben.
io_service definiert die Hauptschnittstelle und die Implementierung unter Linux ist task_io_service.
task_io_service definiert hauptsächlich drei Dinge:
- Ein Reaktor, der ein Ereignistreiber wie Abschlussport, Auswahl, Umfrage und Epoll ist; Eine öffentliche Aufgabenwarteschlange op_queue, die zum Speichern von von Benutzern geposteten und von Reaktor zurückgegebenen Aufgaben verwendet wird.
-
Thread-bezogene Variablen. io_service selbst erstellt keine Threads, speichert jedoch einige Thread-Aufrufinformationen, z. B. private Thread-Warteschlangen usw.
-
Darüber hinaus verwaltet task_io_service auch eine Liste der inaktiven Threads und weckt einen der inaktiven Threads, wenn zusätzliche Aufgaben eintreffen. Im allgemeinen Linux-Thread-Pool für einzelne Aufgabenwarteschlangen wird eine Bedingungsvariable verwendet, um den Thread aufzuwecken. In einem Multi-Core-System weckt ein pthread_cond_signal-Aufruf einen oder mehrere Threads im Wartezustand (siehe https://linux .die.net/man/3/pthread_cond_signal), obwohl es nur eine Aufgabe gibt, wird bei Verwendung der Idle-Thread-Methode nur ein Idle-Thread aktiviert, wenn eine Aufgabe vorhanden ist, was viele unnötige Aktivierungen reduzieren kann.
Die thread_info_base-Klasse verwaltet einen einfachen Speicherpool mit nur einem Speicherbereich. Sie kann den Speicherzuweisungsaufwand nur reduzieren, wenn kontinuierlich eine Speicherfreigabe beantragt wird.
Die Rolle von io_service::work: io_service::run wird sofort zurückgegeben, wenn die Aufgabe abgeschlossen ist. Dies ist nicht das, was Sie beim Schreiben eines residenten Serviceprogramms wünschen. Die von Boost bereitgestellte Lösung besteht darin, eine Arbeit zu definieren Variable, es ist auf den ersten Blick erstaunlich, dass diese Variable, die nichts mit io_server zu tun zu haben scheint, tatsächlich das Verhalten von run steuern kann. Sie können sehen, dass die Implementierung der Arbeit überraschend einfach ist work_started()-Methode von io_service im Konstruktor, sodass die Anzahl der ausstehenden Aufgaben (++outstanding_work_) größer als 0 ist. In diesem Fall geht io_service::run davon aus, dass immer Aufgaben verarbeitet werden müssen, und gibt nicht zurück.
Verwandte Empfehlungen:
Angular aktualisiert Directive_AngularJS entsprechend dem Status des Dienstes
Einführung in die Methoden zur Verwendung von Factory und Service in AngularJS_AngularJS
Das obige ist der detaillierte Inhalt vonboost::io_service-Interpretation. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!