"Leo Havmøller" <leh@-nospam-rtx.dk> wrote:
[8<8<8<]
> Jeg har brug for en kø, som jeg har tænkt mig at implementere vha. en
> passende container (deque eller list).
Hvad med at bruge std::queue container adapteren eller lave lave en
tilsvarende container adapter med de ønskede tråd egenskaber ?
Jeg har lavet en sådan tråd sikker adapter. Den er lavet ovenpå ObjectSpace
Thread<ToolKit> bibliotekets tråd klasser.
Send mig en mail, så returnerer jeg gerne koden (uden nogen form for
garantier eller ansvar for korrekt funktion).
Det er ikke helt trivielt at få så simpel så man er _sikker_ på at den
virker (og stress teste den for at fjerne fejl).
Den blev lavet således at mange tråde kunne indsætte i køen men kun een tråd
fjernede fra den (og dermed har den ikke det problem du egentlig spørger
om).
Der ligger nogle vigtige tråd beslutninger:
* skal "back" og "front" udgøre ventepunkter hvis køen er tom ?
* hvad med timeout ?
* hvis ikke, hvordan skal tråden(e) der tager ud fra køen finde ud af
hvornår der bliver sat noget ind i køen - bortset fra at bruge busy-wait
(while(!queue.empty());)
* skal containeren håndtere hvis nogle tråde venter på at der bliver sat
noget ind i køen, når køen bliver nedlagt ?
og der er sikkert flere.
> Nogle tråde fylder data i vha.
> push_back(), og nogle henter data ud vha.
> pop_front() og efterfølgende erase().
Formelt set siger C++ Standarden ikke noget om tråde, og derfor er det ikke
specificeret hvordan container klasserne opfører sig i forhold til tråde.
Når det er sagt forventes det almindeligvis at det er trådsikre på samme
måde som en integer.
Se eventuelt
http://www.sgi.com/tech/stl/thread_safety.html
[8<8<8<]
> Problemet er at der ikke findes en pop()-variant der både returnere
> det sidste element og fjerner det fra køen.
Årsagen til det at der ikke findes en sådan operation er at det generelt
ikke kan gøres exception sikkert.
Hvis det skulle være anderledes og man ville _garantere_ at man ikke mister
elementer skulle man _kræve_ at copy-constructoren ikke må smide exceptions.
> Det giver en
> race-condition mellem pop_front() og erase(). Skal jeg selv lægge en
> lås uden om de 2 kald, eller findes der en anden løsning?
Ja, f.eks.:
1.
Lås den ekternt. Kræv f.eks. pop funktionen tager en reference til et lås
objekt - så er man sikker på at det findes (på den pæne side af et hack).
2.
Lad pop funktionen tage en reference til et objekt, således at der bruges
assignment (i stedet for copy-constructor) inde i pop-funktionen som man så
_ved_ gik godt inden elementet fjernes fra køen.
3.
Alloker en kopi af elementet på heapen og returner en auto_ptr (auto_ptr
copy-constructor smider _aldrig_ exceptions) til kopien. Man _ved_ således
inden pop-funktionen at oprettelsen af kopien gik godt inden elementet
fjernes fra køen.
4. Sørg for at der kun er een tråd der fjerner fra køen
Venlig hilsen
Mogens Hansen