Checken ob der current Thread eine CRITICAL_SECTION gelockt hat (und wie "tief")



  • Kann man unter Windows halbwegs portabel checken ob, und wenn wie "tief" rekursiv (=nesting count), der aktuelle Thread eine CRITICAL_SECTION gelockt hat?

    Das ganze soll lediglich zu Debugging-Zwecken dienen. z.B. wenn man Code schreibt der sich darauf verlässt dass eine bestimmte CRITICAL_SECTION bereits extern gelockt wurde wäre es nett wenn man das prüfen könnte.
    Und in Fällen wo man diese CRITICAL_SECTION temporär "aufmachen" muss (wie man es z.B. mit den Mutex+ConditionVariable macht) wäre dann noch gut wenn man überprüfen könnte ob der "nesting count" eh genau 1 ist.

    Soll wie gesagt nur zum Testen/Debuggen eingesetzt werden, muss also nicht wirklich sehr schnell sein. Es wäre aber natürlich trotzdem gut wenn die verwendete Technik auf allen möglichen Win32 Systemen funktioniert - sagen wir mal ab Windows XP, aber natürlich inklusive z.B. WOW64 unter Vista/Windows 7/Windows 8 64 Bit.



  • Vielleicht: http://msdn.microsoft.com/en-us/magazine/cc164040.aspx ist von 2003. Oder: http://msdn.microsoft.com/en-us/library/ff541979(v=vs.85).aspx . Dabei scheint ein LockCount von -1 bzw. -2 (abhaengig vom Betriebssystem) eine freie CriticalSection zu repraesentieren.



  • Danke! 🙂

    knivil schrieb:

    Dabei scheint ein LockCount von -1 bzw. -2 (abhaengig vom Betriebssystem) eine freie CriticalSection zu repraesentieren.

    Ich schätze ein Test auf OwningThread müsste reichen um zu entscheiden ob der "Current Thread" die CS gelockt hat oder nicht.
    Und wenn ja, dann denke ich müsste es reichen das RecursionCount Feld zu checken um zu entscheiden ob die CS einfach oder mehrfach gelockt ist.

    Dabei vermeidet man dann diverse Unterschiede beim LockCount Feld.

    Die "is free" Information brauch ich dabei nämlich gar nicht, mir reicht ein "LockedByCurrentThread" das 0 für "nein" und ansonsten die nesting depth zurückgibt.

    Quasi so

    uint32_t LockedByCurrentThread(CRITICAL_SECTION const& cs)
    {
        DWORD const owningThread = HandleToULong(*static_cast<HANDLE const volatile*>(&cs.OwningThread)); // Dass das Feld ein HANDLE ist hübsch pervers
        if (owningThread != GetCurrentThreadId())
            return 0;
        else
        {
            assert(cs.RecursionCount > 0);
            return cs.RecursionCount;
        }
    }
    
    // ...
    
    void Foo::MethodThatNeedsToTemporarilyUnlock()
    {
        assert(LockedByCurrentThread(m_cs) == 1);
        // ...
        ScopedUnlock ul(m_cs);
        // ...
    }
    
    void Foo::MethodThatDependsOnLockByCaller()
    {
        assert(LockedByCurrentThread(m_cs));
        // ...
    }
    

Anmelden zum Antworten