Out-of-Process Server Implementation Helpers
Er zijn vier helperfuncties beschikbaar die kunnen worden aangeroepen door out-of-process-servers om de taak van het schrijven van servercode te vereenvoudigen. COM-clients en COM-in-process-servers zouden deze doorgaans niet aanroepen. Deze functies zijn ontworpen om raceomstandigheden in serveractivering te voorkomen wanneer de servers meerdere appartementen of meerdere klasseobjecten hebben. Ze kunnen echter ook net zo eenvoudig worden gebruikt voor servers met één thread en één klasseobject. De functies zijn als volgt:
Een COM-server moet bijhouden hoeveel objectexemplaren deze heeft geïnstantieerd en hoe vaak de IClassFactory::LockServer methode is aangeroepen om deze goed af te sluiten. Alleen wanneer beide aantallen nul bereiken, kan een server worden afgesloten. In COM-servers met één thread werd de beslissing om af te sluiten gecoördineerd met binnenkomende activeringsaanvragen, die werden geserialiseerd door de berichtenwachtrij. De server, na ontvangst van een release op het uiteindelijke objectexemplaren en besluit af te sluiten, trekt de klasseobjecten in voordat er meer activeringsaanvragen worden verzonden. Als er na dit punt een activeringsaanvraag binnenkwam, zou COM herkennen dat de klasseobjecten zijn ingetrokken en een fout zou retourneren aan Service Control Manager (SCM), waardoor een nieuw exemplaar van het lokale serverproces zou worden uitgevoerd.
Op een server van een appartementsmodel, waarin verschillende klasseobjecten zijn geregistreerd op verschillende appartementen en op alle gratis threads servers, moet deze beslissing om af te sluiten worden gecoördineerd met activeringsaanvragen voor meerdere threads, zodat één thread van de server niet besluit af te sluiten terwijl een andere thread van de server bezig is met het delen van klasseobjecten of objectexemplaren. Een klassieke maar omslachtige benadering om dit op te lossen, is door de server te laten uitvoeren, nadat deze de klasseobjecten heeft ingetrokken, het aantal exemplaren opnieuw te controleren en in leven te blijven totdat alle exemplaren zijn vrijgegeven.
Om het voor serverschrijvers gemakkelijker te maken om deze soorten racevoorwaarden te verwerken, biedt COM twee referentietelfuncties:
- CoAddRefServerProcess een globaal aantal referentiegegevens per proces verhogen.
- CoReleaseServerProcess het globale referentieaantal per proces verlagen.
Wanneer het globale referentieaantal per proces nul bereikt, roept COM automatisch CoSuspendClassObjectsaan, waardoor er geen nieuwe activeringsaanvragen binnenkomen. De server kan vervolgens de registratie van de verschillende klasseobjecten van de verschillende threads op uw gemak ongedaan maken, zonder dat u zich zorgen hoeft te maken dat er een andere activeringsaanvraag binnenkomt. Alle nieuwe activeringsaanvragen worden voortaan verwerkt door de SCM die een nieuw exemplaar van het lokale serverproces start.
De eenvoudigste manier voor een lokale servertoepassing om gebruik te maken van deze functies is het aanroepen van CoAddRefServerProcess in de constructor voor elk van de exemplaarobjecten en in elk van de IClassFactory::LockServer methoden wanneer de parameter fLock is TRUE. De servertoepassing moet ook CoReleaseServerProcess aanroepen in de destructor van elk van de exemplaarobjecten en in elk van de bijbehorende IClassFactory::LockServer methoden wanneer de parameter fLock is FALSE.
Ten slotte moet de servertoepassing aandacht besteden aan de retourcode van CoReleaseServerProcess, en als deze 0 retourneert, moet de servertoepassing de opschoonbewerking starten. Voor een server met meerdere threads betekent dit meestal dat de verschillende threads moeten worden aangegeven om hun berichtenlussen af te sluiten en CoAddRefServerProcess en CoReleaseServerProcessaan te roepen. Als de levensduurbeheerfuncties van het serverproces worden gebruikt, moeten ze worden gebruikt in zowel de objectexemplaren als de LockServer-methode; anders kan de servertoepassing voortijdig worden afgesloten.
Wanneer een CoGetClassObject aanvraag wordt ingediend, neemt COM contact op met de server, marshals de IClassFactory interface van het klasseobject, keert terug naar het clientproces, unmarshals the IClassFactory interface en retourneert deze naar de client. Op dit moment roepen clients meestal LockServer- aan met TRUE- om te voorkomen dat het serverproces wordt afgesloten. Er is echter een tijdvenster tussen wanneer het klasseobject marshaled is en wanneer de client LockServer aanroept waarin een andere client verbinding kan maken met dezelfde server, een exemplaar kan ophalen en dat exemplaar vrijgeeft, waardoor de server wordt afgesloten en de eerste client hoog en droog laat met een niet-verbonden IClassFactory- aanwijzer. Om deze racevoorwaarde te voorkomen, voegt COM een impliciete aanroep toe aan LockServer- met TRUE- aan het klasseobject wanneer het de interface IClassFactory en een impliciete aanroep naar LockServer- met FALSE wanneer de client de IClassFactory-interface uitgeeft. Daarom is het niet nodig om externe LockServer terugroepen naar de server, en de proxy voor LockServer retourneert S_OK zonder de aanroep daadwerkelijk te verwijderen.
Er is een andere activeringsgerelateerde racevoorwaarde tijdens de initialisatie van een out-of-process-serverproces. Een COM-server die meerdere klassen registreert, roept doorgaans CoRegisterClassObject- aan met REGCLS_LOCAL_SERVER voor elke CLSID die wordt ondersteund. Nadat dit voor alle klassen is gebeurd, voert de server de berichtenlus in. Voor een COM-server met één thread worden alle activeringsaanvragen geblokkeerd totdat de server de berichtenlus binnenkomt. Voor een appartementsmodelserver die verschillende klasseobjecten in verschillende appartementen registreert en voor alle gratis threaded servers, kunnen activeringsaanvragen eerder dan deze komen. In het geval van servers van het appartementsmodel kunnen activeringsaanvragen binnenkomen zodra een thread de berichtenlus heeft ingevoerd. In het geval van gratis threaded-servers kan een activeringsaanvraag binnenkomen zodra het eerste klasseobject is geregistreerd. Omdat een activering dit vroeg kan gebeuren, is het ook mogelijk dat de definitieve release plaatsvindt (waardoor de server wordt afgesloten) voordat de rest van de server de initialisatie heeft voltooid.
Als u deze racevoorwaarden wilt elimineren en de taak van de serverschrijver wilt vereenvoudigen, moet elke server die meerdere klasseobjecten wil registreren bij COM CoRegisterClassObject aanroepen met REGCLS_LOCAL_SERVER | REGCLS_SUSPENDED voor elke andere CLSID die door de server wordt ondersteund. Nadat alle klassen zijn geregistreerd en het serverproces gereed is om binnenkomende activeringsaanvragen te accepteren, moet de server één aanroep uitvoeren naar CoResumeClassObjects. Deze functie vertelt COM om de SCM te informeren over alle geregistreerde klassen en het begint met het laten activeren van aanvragen in het serverproces. Het gebruik van deze functies biedt de volgende voordelen:
- Er wordt slechts één aanroep naar de SCM gedaan, ongeacht het aantal CLSID's dat is geregistreerd, waardoor de totale registratietijd (en dus de opstarttijd van de servertoepassing) wordt verminderd.
- Als de server meerdere appartementen en verschillende CLSID's heeft, zijn geregistreerd in verschillende appartementen, of als de server een gratis threaded server is, worden er geen activeringsaanvragen binnengekomen totdat de server CoResumeClassObjects, waardoor de server een kans krijgt om alle CLSID's te registreren en correct in te stellen voordat u te maken hebt met activeringsaanvragen en mogelijke afsluitaanvragen.
Verwante onderwerpen