.oisyn schreef op vrijdag 03 april 2009 @ 23:15:
Wanneer kan A die call afhandelen dan? Ik bedoel, is het niet gewoon een thread die ook code runt? Of wil je dat ie een soort van (handmatige) message loop doet, wachtend op commando's van andere threads.
Juist.
En eventueel kun je die thread nog exposen dmv die iteration call.
Klinkt een beetja als C++0x's
futures (let wel, dit is niet de final proposal, maar wel het beste artikel dat ik kon vinden met de meeste achtergrond-informatie, in plaats van wat droge bewoording uit de C++ standaard

)
Weeral juist
Het verschil is echter dat je bij futures verdere processing kan doen en op een gegeven moment future<int>.getValue() doet. Bij deze implementatie geef je een handler mee die met het resultaat aangeroepen wordt.
Het gedrag kan je dan ook zo specifieren dat wanneer je 2 active classes hebt en de ene een async call doet naar de andere met een handler uit zijn eigen class:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| active class B
{
public fn foo() -> (int) { ... }
}
active class A
{
public fn asynchandler(int)
{
// doe iets
}
public fn foo()
{
async b.foo() asynchandler
}
} |
dat de asynchandler dan ook gedispatchet wordt op de thread van A, want deze wordt opgeroepen vanuit thread B.
Je kan dit vergelijken met het doorbreken van een boost::shared_ptr loop dmv het gebruik van een weak_ptr.
Alleen kan je hier statisch en at compile time bepalen of er geen call-loops zijn tussen active classes.
Een andere, en misschien betere, oplossing is dat wanneer active object B een functie oproept van active object A en er een callback is naar active object B (wat dus een deadlock zou opleveren) je die call gewoon synchroon, zonder dispatching uitvoert. thread B is immers aan het wachten op de call van A en er is dus geen gevaar voor thread-unsafe handelingen.
Mocht je dit in C++ willen uitvoeren dan heb je gewoon language support nodig:
- automatische type-generatie voor het dispatchen van de calls
anders moet je zelf per call een struct/class maken die je kan posten in een msgQ, wat teveel werk is.
- Van veel calls (niet alle) kan je statisch afleiden of je zal moeten dispatchen of als je de functie rechtstreeks kan oproepen. Door een call-graph op te stellen kan je per functie bepalen of ze vanuit 1 of meer threads aangeroepen kunnen worden. Eventueel kun je zelfs verschillende versies van een call laten genereren die dan ook andere calls dispatched of juist rechtstreeks aanroept.
- het wrappen van de echte call in een
code:
1
2
3
4
| if (currentThread() == objectAssignedThread)
direct_call()
else
dispatch_call() |
kan door de compiler gedaan worden, inclusief het effectief dispatchen. Mogelijk wordt de stack van de huidige thread gebruikt door de andere thread, enz.
- Een compiler kan heel veel optimalisatiestappen doen die je met library code niet kan doen.
- Parallellisme uitdrukken vereist 1 of 2 keywords: active en eventueel async.
[
Voor 21% gewijzigd door
H!GHGuY op 04-04-2009 11:50
]