critical section problem



  • fricky schrieb:

    BorisDieKlinge schrieb:

    Hab ne dafür ne Mutex klasse geschrieben:

    wieso schreibt jemand eine klasse für 3 einfach zu verwendende funktionen?
    🙂

    weil die leute dank des c++ marketing wahns (und durch die teils diletantischen buchempfehlungen von mitgliedern hiesigen forums) den eindruck gewonnen haben, sie müssten alles, aber auch alles, in klassen stopfen, weil ihr code dann modularer und besser sei, etc. typisch c++'ler halt, machens sich immer komplizierter als nötig :lol:



  • fricky schrieb:

    BorisDieKlinge schrieb:

    Hab ne dafür ne Mutex klasse geschrieben:

    wieso schreibt jemand eine klasse für 3 einfach zu verwendende funktionen?
    🙂

    weil der destruktor der klasse unheimlich hilfreich ist



  • raii schrieb:

    weil der destruktor der klasse unheimlich hilfreich ist

    aber das critical-section object ist danach auch ungültig, wenn es ein object-member ist. legt man es statisch an, benutzen alle objecte die selbe CS. das bringt auch nix. also besser keine klasse drum herumstricken.
    🙂



  • 😕 😕 😕 😕 😕



  • class Mutex
    {
        CRITICAL_SECTION *cs;
    
    public:
        Mutex (CRITICAL_SECTION *sect) 
        {
           cs = sect; 
           EnterCriticalSection (cs);
        }
    
        ~Mutex() 
        {
          LeaveCriticalSection (cs);
        }
    };
    ...
    CRITICAL_SECTION the_section;
    ...
    void f()
    {
       Mutex m (&the_section);
       // Locked
       ...
    } // Unlocked
    ...
    

    sinnvoller wäre sowas^^
    🙂



  • Und dein Code funktioniert nicht mal.. Genau deshalb verwendet man Klassen, damit man nicht den Aufruf zu InitializeCriticalSection vergisst. Abgesehen davon ist es doch auch üblich, eine Mutex- und eine MutexLocker- (o.s.ä.) Klasse zu haben.

    edit: übrigens auch und vor allem wegen Exceptions, die überspringen beim "Wurf" ja einfach das "Release".



  • Badestrand schrieb:

    Und dein Code funktioniert nicht mal.. Genau deshalb verwendet man Klassen, damit man nicht den Aufruf zu InitializeCriticalSection vergisst.

    stimmt. ich blindfisch 😞

    Badestrand schrieb:

    Abgesehen davon ist es doch auch üblich, eine Mutex- und eine MutexLocker- (o.s.ä.) Klasse zu haben.

    nö, mein misslungenes beispiel beweisst doch eindeutig, daß man sowas nicht in klassen packen sollte. wo willst du da das InitializeCriticalSection unterbringen?
    🙂



  • Badestrand schrieb:

    edit: übrigens auch und vor allem wegen Exceptions, die überspringen beim "Wurf" ja einfach das "Release".

    unter windows hast du dafür '__finally'
    übrigens ist SEH weitaus nützlich als C++ exceptions
    🙂



  • fricky schrieb:

    Badestrand schrieb:

    Und dein Code funktioniert nicht mal.. Genau deshalb verwendet man Klassen, damit man nicht den Aufruf zu InitializeCriticalSection vergisst.

    stimmt. ich blindfisch 😞

    hihi :p

    fricky schrieb:

    nö, mein misslungenes beispiel beweisst doch eindeutig, daß man sowas nicht in klassen packen sollte. wo willst du da das InitializeCriticalSection unterbringen?
    🙂

    class Mutex{
    
        CRITICAL_SECTION _critSection;
    
    public:
    
        Mutex () { InitializeCriticalSection (& _critSection); }
        ~Mutex () { DeleteCriticalSection (& _critSection); }
    
        void Acquire(){ EnterCriticalSection (& _critSection); }
        void Release(){ LeaveCriticalSection (& _critSection); }
    };
    
    class MutexLocker
    {
        Mutex& cs;
    
    public:
        MutexLocker( Mutex& m ) : cs(m)
        {
           cs.Acquire();
        }
    
        ~MutexLocker()
        {
            cs.Release();
        }
    };
    
    ...
    Mutex the_section;
    ...
    
    void f()
    {
       MutexLocker m (the_section);
       // Locked
       ...
    } // Unlocked
    

    Meinetwegen auch mit "friend", damit man auf Aquire und Release keinen Zugriff mehr hat 🙂



  • fricky halt einfach deine fresse wenn du keine ahnung hast



  • sowas hab ich auch noch^^ immer cool bleiben

    class Lock {
    
    private:
    
        Mutex & _mutex;
    
    public:
        // Acquire the state of the semaphore
        Lock (Mutex &mutex): _mutex(mutex){
            _mutex.Acquire();
        }
    
    	// Release the state of the semaphore
        ~Lock (){ _mutex.Release();	}
    
    };
    


  • BorisDieKlinge schrieb:

    sowas hab ich auch noch^^ immer cool bleiben

    Gut, man kann ja nie wissen 😉

    fricky schrieb:

    Badestrand schrieb:

    edit: übrigens auch und vor allem wegen Exceptions, die überspringen beim "Wurf" ja einfach das "Release".

    unter windows hast du dafür '__finally'

    Joar, aber dann musst du ja schon wieder an was denken, ich mag's automatisch (beim Programmieren) 🙂

    fricky schrieb:

    übrigens ist SEH weitaus nützlich als C++ exceptions
    🙂

    Das verstehe ich nicht, sind die C++-Exceptions nicht genau "Structured Exception Handling"?



  • hey leute,
    vergisst nochmal die mutex , Lock klassen geschichte, und geht noch mal zu manfng ds Threads..

    Ich frage mich wieso es überhaupt eine Dead-lock gibt?????

    Wenn ich mit SendMessage eine Msg an das Fenster schicke, ich dann glichzeitig ein button im fenst drücke, können doch keine messages parallel barbeitet wrden oder? d.h. solange die message queue die click message des button bearbeiten, kann der thread doch keine message schicken??? zudem wir in der Klick message aufruffe des Mutex gsperrt, der thread kann schon mal gar keine message schicken? bin verwirrt.



  • BorisDieKlinge schrieb:

    manfng ds

    *very* 😕

    BorisDieKlinge schrieb:

    Ich frage mich wieso es überhaupt eine Dead-lock gibt?????

    Ist doch logisch, die Funktion "SendMessage" ruft die WndProc auf, die wiederum den Mutex haben will, der aber von der aufrufenden Funktion belegt ist.

    m_Mutes.Acquire (); // Locked
    
    //::SendMessage(m_hWnd,WM_PR2_DATASTATE,(WPARAM)it->c_str(),NULL); //Hier hängt er sich auf
    // Führt onBnClickedTransfer hier aus:
        m_Mutes.Acquire (); // Ist schon gelockt, DeadLock
        ...
        m_Mutex.Release(); 
    
    m_Mutex.Release();
    

    Also einfach PostMessage nehmen, da wird die Nachricht in die Message-Queue gedrückt und die Funktion kommt sofort zurück. Danach kann auch das Aquire aus onBnClickedTransfer greifen 🙂



  • ja eben... für das sind mutex doch da:

    wenn ich m_Mutes.Acquire (); mache, und schon gelockt ist, müsste er doch da warten bis der Mutex wieder freigegeben ist...



  • BorisDieKlinge schrieb:

    wenn ich m_Mutes.Acquire (); mache, und schon gelockt ist, müsste er doch da warten bis der Mutex wieder freigegeben ist...

    Ja klar, aber wie soll er bei diesem linearen Programmstückchen wieder freigegeben werden?:

    Mutex m;
    m.Aquire();
    m.Aquire();
    m.Release();
    m.Release();
    

    Und genau so läuft das bei deinem Programm momentan ja ab 😉

    Falls das noch nicht so ganz klar geworden ist: Bei SendMessage springt dein Thread (der SendMessage ausführt) in deine WndProc und läuft dort ja direkt in's nächste Aquire. Erst wenn die Abarbeitung der WndProc fertig ist, ist die SendMessage-Funktion "fertig" und das Release nach dem SendMessage wird ausgeführt.



  • Falls das noch nicht so ganz klar geworden ist: Bei SendMessage springt dein Thread (der SendMessage ausführt) in deine WndProc und läuft dort ja direkt in's nächste Aquire. Erst wenn die Abarbeitung der WndProc fertig ist, ist die SendMessage-Funktion "fertig" und das Release nach dem SendMessage wird ausgeführt.

    eben nicht,

    durch drücken eine buttons wird eine messesage an das fenster geschickt. während er diese message abarbeitet, kann er ja keine andere message startet bzw. bearbeiten. so kann eine doppeles m.Aquire(); ja nich vorkommen....

    FENSTER {
    LPRESULT OnKlick(..){
    
    m.Aquire();
    
    m.Release();
    
    }
    ThreadMessage (..){
     ..do someething
    }
    
    }
    
    THREAD{
    
    m.Aquire();
    SendMessage(ThreadMEssage);
    m.Release();
    
    }
    

    1.Thread Locked
    2.SendMessage
    3.Message ABarbeitung
    4.Butten wird getrückt
    5.warten bis theadMessageabg earbeitet wurde
    6.Jetzt Button Message bearbeiten
    6.OnKlick will locken (während dessen läuft ja thread weiter und gibt mutext frei)
    7. nun kann OnKlick Locken
    .



  • Sorry, dann hatte ich das falsch verstanden 😞
    Wie sieht denn die Abarbeitung der WM_PR2_DATASTATE-Nachricht aus?



  • LRESULT CThreadTest::OnPR2_DataState( WPARAM wParam, LPARAM lParam ) 
    {
    
    	SendPR2Message(GetDlgItem(IDC_TRACELIST)->m_hWnd," %s",(char*)wParam);
    
     // ... Handle message here
      return 0L;
    }
    

    SendPR2Message hängt einen formatieren TExt an eine Listboxk im Fenster.. also da kommt nirgens m.Aquiere.. etc.

    naja denn och ist komisch, das sich das programm aufhhängt wenn ich es so mache.. ein deadlock wird es nich sein

    Was passiert denn wenn zwei SendMessage funktionen "gleichzeig" an ein fenster gschickt werden? das system wird an dem Funktionaufurf ::SendMEssage(..) warten bis frei ist oder?

    wenn das so wäre was ich vermutte habe ich ds problem:

    m_Mutex.Acquire();
    //Zudiesem Zeitpunkt, wird der Button gedrückt, es wird also erst die MEssage des Button bearbeitet, darin findest ein m_Mutex.Acquire(); statt und es wird da gewartet.
    //Aber die folgende SEndMEssage kann nicht ausgeführt werden weil er noch in der anderen vom Button hängt...
    ::SendMessage(m_hWnd,WM_PR2_DATASTATE,(WPARAM)&("kopie data"),NULL);
    m_Mutex.Release();
    

  • Mod

    Wenn Du SendMessage verwendets hast Du eine automatische Thread-Synchronisation. In diesem Moment steht der Thread und der empfanege Thread läuft (hoffentlich) in die achrichtenschleife in Deine Nachricht.
    Der Thread der SendMessage ausführt kehrt erst zurück, wenn die WndProc Deine Funktion abgearbeitet hat.

    Wenn man diese Technik gezielt anwendet, kann man sich Mutexe/Semaphoren/Crticialsections sparen.


Anmelden zum Antworten