Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /home/www/novacisko.cz/subdomains/bredy/init.php on line 11

Warning: mysql_connect(): Headers and client library minor version mismatch. Headers:50562 Library:100020 in /home/www/novacisko.cz/subdomains/bredy/init.php on line 11

Warning: Cannot modify header information - headers already sent by (output started at /home/www/novacisko.cz/subdomains/bredy/init.php:11) in /home/www/novacisko.cz/subdomains/bredy/index.php on line 38
Multithreading v C++ (ve Win32) II - ThreadHook - Bredyho blog - Ondřej Novák
Bredyho blog - Ondřej Novák

Multithreading v C++ (ve Win32) II - ThreadHook

Pokračování dokumentace k Multithreading v C++ (ve Win32)


Pokud chceme mít kontrolu nad vznikajícími a zanikajícími thready, nemáme ve WinApi mnoho šancí. V rámci ThreadBase lze instalovat tzv. hooky. Jsou to funkce, které jsou volány před spuštěním threadu a po jeho ukončením. Význam těchto funkcí je zejména v možnosti inicializovat TLS proměnné, se kterými posléze pracují knihovní funkce. Možnosti jsou ale širší.

Třída ThreadHook

Pokud je potřeba instalovat hook, je nutné nejprve zdědit třídu ThreadHook

class MyHook: public ThreadHook
{
public:
virtual unsigned long ProcessThreadHook(ThreadBase *instance)
{
... implementace...
}
}

Instalace hooku

Instalaci hooku provedeme pomocí funkce ThreadHook::AddHook a jako parametr uvedeme instanci našeho hooku. Tato instance musí bezpodmínečně existovat po dobu běhu všech vláken, kde je instalována.

  • Nejjednodušší je instanci hooku vytvářet staticky jako globální instanci.
  • V určitých situacích lze hook vytvářet na zásobníku, pokud ten obsluhuje pouze vlákna vytvořené uvnitř funkce a tyto vlákna zanikají před ukončením funkce.
  • Dynamické hooky si musí počítat aktivní vlákna, a odinstalovat se v okamžiku, kdy všechna obsluhovaná vlákna zaniknou.
MyHook myHook;

void main()
{
ThreadHook::AddHook(&myHook);
MyThread myThread;
myThread.Start();
...
...
myThread.Join();
}

Obsluha vlákna v hooku

V okamžiku startu vlákna je zavolána funkce ProcessThreadHook. Parametrem této funkce je ukazatel na instanci třídy ThreadBase která je spouštěna. Tato instance ještě není inicializována na běh vlákna, takže jej nelze ovládat. Hook funkce se volají před provedením Init.

Funkce může odmítnout start vlákna. V tom případě ukončí zpracování pomocí return obsahující návratový kód. V tom případě se spouštěná třída ani nedozví, že vlákno bylo spuštěno.

V případě, že hook nemá důvod ukončit vlákno, po inicializaci vlákna zavolá funkci ProcessNextHook(ThreadBase *instance). Předávaný parametr musí být stejný jako ten, se kterým byla funkce zavolána.

Funkce ProcessNextHook vlastně spustí vlákno. Přitom se provedou všechny další hooky instalované v pořadí. Proto návrat z této funkce proběhne až při ukončení vlákna. V této fázi musí hook provést vyčištění paměti a zdojů které spravuje, a poté se ukončit. Jako návratovou hodnotu musí použít tu, kterou získá z volání funkce ProcessNextHook

class MyHook: public ThreadHook
{
public:
virtual unsigned long ProcessThreadHook(ThreadBase *instance)
{
//... Inicializace hooku ....
unsigned long res=ProcessNextHook(instance);
//... Čištění hooku ...
return res;
}
};

Selektivní hook - inicializuje se jen pro některé thready

class MyHook: public ThreadHook
{
public:
virtual unsigned long ProcessThreadHook(ThreadBase *instance)
{
if (!IsMyThread(instance)) return ProcessNextHook(instance);
//... Inicializace hooku ....
unsigned long res=ProcessNextHook(instance);
//... Čištění hooku ...
return res;
}
};

Výše uvedený příklad testuje, zda ukazatel ukazuje na instanci vlákna, který chceme spravovat. V případě, že tomu tak není, ihned předá řízení dalšímu hooku. Jinak provede standardní inicializaci.

V tomto případě je možné, aby instance hooku v době ukončení vlákna, pro které nebyla provedena inicializace, již neexistovala. Při zpětném procházení hooků je zde pouze return, který předá řízení nadřazenému hooku. Nepracuje se zde s instancí hooku.

Pozor
Při návratu do hooku může nastat situace, kdy parametr instance již nebude platným. Bude obsahovat pointer na místo v paměti, které již byla uvolněna. Proto se nedoporučuje přistupovat do instance vlákna nebo dokonce se pokoušet instanci vlákna ovládat. Hodnotu ukazatele použijte pouze k identifikaci vlákna (jako číslo).

Odinstalování hooku

Hook lze odinstalovat funkcí RemoveHook(ThreadHook *hk).

Je však potřeba hlídat toto

  • Odinstalování hook způsobí, že hook již nebude volán při startu vláken.
  • I když je hook odinstalován, stále může být volán a to vlákny, které byly spuštěny během jeho aktivity - při jejich ukončení.

Další aspekty

  • Hooky se spouští v opačném pořadí jejich instalace. Posledně instalovaný hook se spouští jako první.
  • Na konci seznamu hooku je systémový hook který spustí vlákno, tj provede Init, Run a Done.
  • Není dovoleno volat ProcessNextHook víckrát. Mělo by to za následek vícenásobné spoštění vláken.
  • Hooky jsou prováděny serializovaně. V danný okamžik poběží pouze jedna sekvence hooků. Ostatní vlákna, která jsou spouštěna musí počkat. Proto není dobré v hooku spouštět vlákna. Už vůbec není možné v hooku čekat na jiné vlákno.
  • Stějně je serializované instalování a odinstalování hooků. Proto není dobré instalovat hooky v hooku.

Hlavní vlákno a cizí vlákna

Při práci s vlákny často narazíme na problém hlavního vlákna. Hlavní vlákno vytváří operační systém, nikoliv knihovna MultiThread. Přesto je často potřeba, aby vlákno mělo přiřazenou existující instanci třídy ThreadBase.

K tomu lze využít třídu RunningThread<Base>. Jedná se vlastně o template, kde Base je třída, ze které je třeba vytvořit třídu mající schopnosti inicializovat se podle aktuálního vlákna. Base musí být buď ThreadBase nebo libovolná třída která tuto třídu dědí.

Inicializací třídy typu RunningThread toto nekončí. Je třeba na vlákno napojit všechny registrované hooky a spustit metodu Run. K tomu využijeme statickou funkci unsigned long ThreadHook::StartThreadInstance(ThreadBase *instance). Jako parametr se předává instance objektu, jenž má přiřazeno aktuální vlákno. Funkce pak vrací výsledek funkce Run.

Stejně lze postupovat i v případě cizích vláken, což jsou vlákna, která vznikají mimo MultiThread knihovnu, například v nějakých třetích knihovnách.

Pokud již máme instanci připravenou, avšak stále neinicializovanou, "čekající" na spuštění, a místo toho potřebujeme již běžící vlákno spojit s touto instancí, lze to udělat následovně.

  1. Zavolat funkci ThreadBase::AttachToCurrentThread(). Funkce normálně vrací NULL, pouze v případě, že již thread má přiřazenou instanci, vrací ukazatel na tuto instanci. V tomto případě je to chyba.
  2. Zavolat unsigned long ThreadHook::StartThreadInstance(ThreadBase *instance)
  3. Po návratu zavolat ThreadBase::DetachThread(0).

Protože funkce AttachToCurrentThread a DetachThread jsou protected: musí se zavolat uvnitř některé zděděné třídy.

vytvořeno: 1.6.2006 20:06:50, změněno: 28.6.2006 14:21:01
Jsou informace v článku pro Vás užitečné?
  • (1)
  • (0)
  • (0)
  • (0)
  • (1)
Nick nebo OpenID
Vzkaz
 
25.7.2016 18:22:50

oVpTr7xMl

Leider nein, ich war das letzte Mal l&igr8;n2e2frist#g 1998 in Hannover nd damals wusste ich noch nicht, was eine Saz ist. Ein guter Kontakt sind h&#228;ufig die regionalen t&#252;rkischen Kulturzentren. Suche Dir eines aus dem Telefonbuch oder Bekanntenkreis heraus.
25.7.2016 18:10:18

JmK2XJaYyjcF

Hi Aileenthis is such a cute po.wr.s.b.otnie and sugar are such stars!They really are so expressive in their faces! How could they be jailed for long I&#39;d want them to sit on my knee for a cuddle! Thanks for your email about the feature I hope to put it on my blog soon.(will let you know when)love K x

Podobné články

Multithreading v C++ (ve Win32)

Představení knihovny pro multithreading v C++. Jedná se čistě o objektový návrh multithreadingu inspirovaný Javou. Mnoho programátorům může usnadnit práci s vícero vlákny ve WinApi.

Multithreading v C++ (ve Win32) III - OOP a vlákna

Pokračování dokumentace k Multithreading v C++ (ve Win32) - Tentokrát si povíme něco o tom jak začlenit vlákna do OOP

MultiThread 2

Knihovna MultiThread-2.0

Základy komunikace mezi procesy (ve Windows)

Od počátku Windows95 jsou procesy v paměti oddělené. Každý proces je vlastně svým světem sám pro sebe. Jak tedy mohou komunikovat procesy mezi sebou? Podrobný výčet možností...
Reklama: