wxWidgets threads



  • So, die sockets laufen, jetzt hab ich im wxWidgets Buch weitergelesen und festgestellt, dass ich für die sockets einen thread brauch. Leider versteh ich die Benutzung von wxMutex noch nicht so ganz.

    // this variable has an "s_" prefix because it is static: seeing an "s_" in
        // a multithreaded program is in general a good sign that you should use a
        // mutex (or a critical section)
        static wxMutex *s_mutexProtectingTheGlobalData;
    
        // we store some numbers in this global array which is presumably used by
        // several threads simultaneously
        wxArrayInt s_data;
    
        void MyThread::AddNewNode(int num)
        {
            // ensure that no other thread accesses the list
            s_mutexProtectingTheGlobalList->Lock();
    
            s_data.Add(num);
    
            s_mutexProtectingTheGlobalList->Unlock();
        }
    
        // return true the given number is greater than all array elements
        bool MyThread::IsGreater(int num)
        {
            // before using the list we must acquire the mutex
            wxMutexLocker lock(s_mutexProtectingTheGlobalData);
    
            size_t count = s_data.Count();
            for ( size_t n = 0; n < count; n++ )
            {
                if ( s_data[n] > num )
                    return false;
            }
    
            return true;
        }
    

    Anscheinend blockiert jetzt so ein Mutex alle global Variablen. Aber was passiert jetzt genau, wenn beide threads gleichzeitig auf das Array zugreifen wollen? Beide locken gleichzeitig? Geht irgendwie nicht. Es gibt nen Fehler bei der lock-Funktion? Der eine thread wartet solange bis der andre fertig ist?
    Schon mal danke im voraus.



  • Wenn zwei deiner Mutex versuchen, einen Lock zu setzten, wartet einer der beiden Threads, bis der andere den Mutex wieder freigibt.



  • Ah, danke. Ist also stark vereinfacht sowas wie:

    bool isLocked = false; //globale Variable
    
    void lock()
    {
      while(isLocked);
      isLocked = true
    }
    
    void unlock()
    {
      isLocked = false;
    }
    


  • kynarion schrieb:

    Ah, danke. Ist also stark vereinfacht sowas wie: [...]

    Vom Prinzip her, ja. Die Umsetzung in der Praxis ist aber um einiges komplexer...



  • Hallo!

    Ist das in dem Beispiel ein Schreibfehler oder Absicht, daß einmal
    s_mutexProtectingTheGlobalList und an anderer Stelle
    s_mutexProtectingTheGlobalData verwendet wird?

    Ich habe versucht, die Befehle 1:1 in mein Programm zu kopieren, aber erhalte haufenweise Fehlermeldungen. Was mache ich falsch?

    Der eine Thread soll aus X Y berechnen und X inkrementieren, der andere Thread soll X und Y ausgeben, ohne daß Thread1 gerade mitten in der Berechnung ist.
    Die Sleep-Befehle sind Absicht, damit möglichst viel Unsynchronität entsteht.

    static wxMutex *s_mutexProtectingTheGlobalData; 
    
    struct	MyThread1 : wxThread
    {	ThreadsFrm*	window;
    	bool		stop;
    
    	MyThread1(ThreadsFrm* p)
    	{	stop = false;
    		window = p;
    	}
    	wxMutexLocker lock(s_mutexProtectingTheGlobalData); 
    	virtual ExitCode Entry()
    	{	while(!stop)
    		{	(*window->WxMemo1) << "x: " << global_x << " -> " << global_y  << "\r\n";
    			Sleep(1000);
    		}
    		(*window->WxMemo1) << "Thread1 fertig!\r\n";
    		return 0;
    	}
    };
    
    struct	MyThread2 : wxThread
    {
    	ThreadsFrm*	window;
    	bool		stop;
    
    	MyThread2(ThreadsFrm* p)
    	{	stop = false;
    		window = p;
    	}
    	s_mutexProtectingTheGlobalList->Lock();
    
    	virtual ExitCode Entry()
    	{	while(!stop)
    		{	global_x++;
    			Sleep(100);
    			global_y = global_x * 10;
    			Sleep(100);
    		}
    		(*window->WxMemo1) << "Thread2 fertig!\r\n";
    		return 0;
    	s_mutexProtectingTheGlobalList->Unlock();
    	}
    };
    
    11 `s_mutexProtectingTheGlobalData' is not a type
    11 ISO C++ forbids declaration of `parameter' with no type
    31 ISO C++ forbids declaration of `s_mutexProtectingTheGlobalList' with no type
    31 expected `;' before '->' token
    In member function `virtual void* MyThread2::Entry()':
    42 `s_mutexProtectingTheGlobalList' was not declared in this scope
    42 [Warning] unused variable 's_mutexProtectingTheGlobalList'
    

    Ich habe bereits versucht, die Lock/Unlock-Befehle an verschiedene Stellen zu schieben, aber keine wirkliche Verbesserung bemerkt.

    PS: Das ist nur ein Übungsbeispiel, mir ist klar, daß die Aufgabe eigentlich keine Threads braucht.
    PPS: meine Kenntnisse sind im Moment auf Stufe 0, aber ich muß in möglichst kurzer Zeit durch sämtliche Themen durch...



  • Ich hab es jetzt so gelöst:

    wxMutex schloss; //Mutex-Variable

    dann jeweils in den Threads:

    wxMutexLocker lock(schloss);
    ...
    wxMutexLocker unlock(schloss);

    Und das funktioniert!
    Ich würde natürlich trotzdem gern wissen, warum es auf die andere Weise nicht geht.


Anmelden zum Antworten