Wenn Sie dies richtig machen wollen, denke ich, dass Sie ein Wrapper-Objekt um Ihre kritischen Abschnitte verwenden, das verfolgen wird, welcher Thread (falls vorhanden) die einzelnen CS in Debug-Builds besitzt. Wenn Sie EnterCriticalSection nicht direkt aufrufen, rufen Sie eine Methode auf Ihrem Wrapper auf, die den EnterCriticalSection-Befehl ausführt und dann bei erfolgreichem Abschluss GetCurrentThreadId in einem DWORD speichert, das von den Asserts überprüft wird. Eine andere Methode würde diese Thread-ID DWORD vor dem Aufruf von LeaveCriticalSection auf Null setzen.
(In Release-Builds, würde der Wrapper wahrscheinlich die extra Sachen weglassen und rufen Sie einfach Enter/Leavecriticalsection.)
Wie Casablanca darlegt, ist der Eigentümer Thread-ID in der aktuellen CRITICAL_SECTION Struktur, so ein Wrapper wie Ich schlage vor, redundante Informationen zu speichern. Casablanca weist jedoch auch darauf hin, dass die Struktur CRITICAL_SECTION nicht Bestandteil eines API-Vertrags ist und sich ändern könnte. (In der Tat hat es in früheren Windows-Versionen geändert.)
Die interne Struktur ist nützlich für das Debuggen, sollte aber nicht in Produktionscode verwendet werden.
Welche Methode Sie verwenden, hängt davon ab, wie "richtig" Ihre Lösung sein soll. Wenn Sie nur einige temporäre Argumente für das Aufspüren von Problemen heute in der aktuellen Windows-Version möchten, dann erscheint mir die Verwendung der Felder CRITICAL_SECTION direkt sinnvoll. Erwarte nicht, dass diese Behauptungen für immer gültig sind. Wenn Sie etwas länger halten möchten, verwenden Sie einen Wrapper.
(Ein weiterer Vorteil der Verwendung eines Wrappers ist, dass Sie RAII bekommen. Dh Der Konstruktor und der Destruktor des Wrappers kümmern sich um die Calls InitializeCriticalSection und DeleteCriticalSection, sodass Sie sich nicht länger darum kümmern müssen Es ist äußerst nützlich, ein Hilfsobjekt zu haben, das bei der Konstruktion in ein CS eindringt und es dann automatisch bei der Zerstörung belässt.Nicht mehr kritische Teile sind versehentlich gesperrt geblieben, weil eine Funktion früher in der Mitte versteckt war ...)
It macht Sinn. Ich habe eine API und mit einer Sperre, entsperren und viele Arbeiterfunktionen. Ich möchte eine Bestätigung in alle Worker-Funktionen einfügen und prüfen, ob der Anrufer nicht vergessen hat, die Sperre anzurufen, bevor er eine Reihe anderer Funktionen aufruft.Ich nehme an, Sie haben nie über den Design-Stil "Design By Contract" erfahren. – Lothar
Ich kann nicht sehen, wie das die Verantwortung der Arbeiter ist. Das ist die Aufgabe des Anrufers. Sie machen Ihre Mitarbeiter auf die Implementierungsdetails des Managers/Orchestrators aufmerksam. Da ist irgendwo ein SRP-Verstoß. Persönlich denke ich, dass Sie Ihre Anforderungen noch einmal überprüfen sollten, und denken Sie daran, dass, falls es Ihren Kunden möglich ist, diesen Fehler zu machen, Sie vielleicht Ihre API überarbeiten sollten, um das zu verhindern. Und ja, ich habe von dem "Design by Contract" Programmierstil gehört, aber ich muss es nicht mögen, noch denke ich, dass Ihre Anforderungen es implizieren. –
Ihr Argument würde auch für alle anderen zustandsbasierten APIs gelten, wo Sie bestimmte Funktionen nur in bestimmten Zuständen aufrufen können. Dies macht keinen Sinn und ist auch nicht praktisch. In Eiffel Programmierer verbringen Sie eine Menge Zeit für Vorbedingungen, um dort State Machine Anforderungen/Spezifikationen zu modellieren. Alles was du sagst ist, dass es egal ist, teste nicht, wiederhole die Validierungstests mehrmals im Caller anstatt im Caller oder überprüfe überhaupt nicht und vertraue auf die Güte des Allmächtigen. – Lothar