Kdykoli někdo používá architekturu řízenou událostmi, je třeba mít jediný mechanismus pro hlášení dokončení události. V Linuxu, pokud někdo používá soubory, je vyžadováno použít něco z rodiny select nebo poll, což znamená, že se zasekne pomocí kanálu k inicializaci všech událostí souvisejících se souborem.
Upravit :Linux má eventfd a timerfd. Ty lze přidat do epoll
a používá se k opuštění epoll_wait
při spuštění z jiného vlákna nebo při události časovače.
Je tu ještě jedna možnost a tou jsou signály. Lze použít fcntl
upravit deskriptor souboru tak, aby byl vysílán signál, když se deskriptor souboru stane aktivním. Obsluha signálu pak může odeslat zprávu připravenou k souboru do libovolného typu fronty podle vašeho výběru. Může to být jednoduchý semafor nebo fronta řízená mutexem/condvarem. Protože jeden již nepoužívá select
/poll
, již není potřeba používat roura k řazení žádných zpráv založených na souborech.
Zdravotní varování:Nezkoušel jsem to, a ačkoli nevidím důvod, proč to nefunguje, ve skutečnosti neznám dopady signal
na výkon přístup.
Edit:Manipulace s mutexem v obslužném programu signálu je pravděpodobně velmi špatný nápad.
Vyřešil jsem přesně tento problém pomocí toho, co uvádíte, pipe() a libevent (který obaluje epoll). Pracovní vlákno zapíše bajt do svého kanálu FD, když jeho výstupní fronta přejde z prázdné do neprázdné. To probudí hlavní IO vlákno, které pak může uchopit výstup pracovního vlákna. Funguje to skvěle, kódování je ve skutečnosti velmi jednoduché.
Máte linuxový tag, takže toto vyhodím:POSIX Message Queues tohle všechno dělají, což by mělo splnit váš „vestavěný“ požadavek, pokud ne vaše méně žádané multiplatformní přání.
Vestavěná je synchronizace bezpečná pro vlákna. Pracovní vlákna můžete zablokovat při čtení fronty. Alternativně mohou MQ použít mq_notify() k vytvoření nového vlákna (nebo signalizace existujícího vlákna), když je do fronty vložena nová položka. A protože to vypadá, že budete používat select(), lze identifikátor MQ (mqd_t) použít jako deskriptor souboru s select.