2010-11-27 12 views

Antwort

1

Was zu tun, wie ich weiß, gibt es keinen dokumentierten Weg, um diese Informationen zu erhalten. Wenn Sie sich die Header ansehen, enthält die Struktur CRITICAL_SECTION einen Thread-Handle, aber ich würde mich nicht auf solche Informationen verlassen, da sich interne Strukturen ohne vorherige Ankündigung ändern könnten. Ein besserer Weg wäre, diese Informationen selbst zu pflegen, sobald ein Thread den kritischen Bereich betritt/verlässt.

0

Ihre Anforderung ergibt keinen Sinn. Wenn Ihr aktueller Thread nicht der Thread ist, der sich im kritischen Abschnitt befindet, wird der Code im aktuellen Thread nicht ausgeführt. Er wird blockiert, wenn Sie versuchen, den kritischen Abschnitt zu sperren.

Wenn sich Ihr Thread tatsächlich in dem kritischen Abschnitt befindet, wird Ihre Assertion immer wahr sein. Wenn nicht, wird Ihre Behauptung immer falsch sein!

Also was ich meine ist, vorausgesetzt, Sie sind in der Lage zu verfolgen, welcher Thread im kritischen Abschnitt ist, wenn Sie Ihre Behauptung innerhalb der kritischen Abschnitt Code, wird es immer wahr sein. Wenn du es draußen platzierst, wird es immer falsch sein.

+0

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

+0

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. –

+0

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

4

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 ...)

+1

+1 - das ist der richtige Weg, um das Problem zu lösen, wenn Sie in C++ programmieren. Keine Prüfung, die Sie direkt auf dem Thread-Griff in der CritSec-Struktur machen können, wird zuverlässig sein, da sich der Zustand dieser Struktur unter Ihren Füßen ändern kann. Verwenden Sie eine RAII 'lock_guard' Klasse, die ein 'locked'-Flag behält. –