Pthread, Mutexe, Zugriff nur bei neuen Daten, Assert Ownership



  • Hallo zusammen,

    ich hab ein kleines Problem mit Mutexen.

    Zwei Threads sollen auf gemeinsamen Speicher zugreifen.

    Jetzt ist das grundsätzlich kein Problem:
    - der eine lockt den Speicher, schreibt was rein, gibt frei.
    - der zweite lockt den Speicher, liest was raus, gibt frei.

    Doch ein kleines Problem ergibt sich dennoch...der zweite Thread soll nämlich nur aus dem Shared Mem lesen, wenn neue Daten dort liegen. Die gleichen Daten soll er nicht noch einmal abholen.

    Bisher wurde dies mit einem zweiten Mutex erledigt, dem SignalMutex. Dieser wurde bei neuen Daten vom ersten Thread freigegeben. Der zweite Thread sperrte diesen dann vor dem Auslesen der Daten im Shared Mem.

    Das Problem ist halt, das eigentlich ja nur der Thread den Mutex freigeben darf, der ihn auch gesperrt hat. Also kamen teilweise Fehler im Programm wegen der Besitzerüberprüfung vor.

    Wie kann man nun dies verhindern? Wie nutzt man sowas richtig?

    Hier mal der Code, der für Lesen und schreiben jetzt benutzt wird...man beachte, daß im Moment ein Thread-Polling läuft, was erst recht nicht ideal ist...

    template <class T>
    void MutexSharedMem <T>::read (T *target) {
    //	if (pthread_mutex_lock (&(this->signalMutex)) == 0) {
    	while (newData == false) {
    		usleep(1);
    	}
    		if (pthread_mutex_lock (&(this->memMutex)) == 0) {
    			*target = *data;
    			newData = false;
    			pthread_mutex_unlock (&(this->memMutex));
    		}
    //	}
    	return;
    }
    
    template <class T>
    void MutexSharedMem <T>::write (T &source) {
    	if (pthread_mutex_lock (&memMutex) == 0) {
    		*data = source;
    		newData = true;
    		pthread_mutex_unlock (&memMutex);
    //		pthread_mutex_unlock (&signalMutex);
    	}
    }
    

    EDIT: Ups, falsches Forum, Linux/Unix wär wohl passender gewesen... 😕



  • Ich versteh dein Problem nicht ganz. Dein bool wird doch nur innerhalb von Abschnitten verändert die eh durch ein Mutex geschützt sind?



  • Genau dafür gibt es Condition-Variablen.

    template <class T>
    void MutexSharedMem <T>::read(T *target) {
        lock_mutex(this->memMutex);
        wait_condition(this->memChangedCondition, this->memMutex); // gibt memMutex, wartet dann auf die Condition, lockt memMutex wieder, und kommt dann zurück
        *target = *data;
        unlock_mutex(this->memMutex);
        return;
    }
    
    template <class T>
    void MutexSharedMem <T>::write(T &source) {
        lock_mutex(this->memMutex);
        *data = source;
        signal_condition(this->memChangedCondition); // "signalisiert" die Condition, d.h. sorgt dafür, dass wait_condition() in read() zurückkommt
        pthread_mutex_unlock(&memMutex);
    }
    

    Die genauen Namen/Parameter der Funktionen such dir bitte aus der PTHREADS Doku raus (ich verwende PTHREADS nie "roh", weiss daher nicht auswendig wie die heissen).



  • Danke schön, hat mir sehr geholfen.

    @rean: Das Problem ist halt, daß bei meiner Variante der thread nicht schlafengelegt wurde, sondern zwischendurch die ganze Zeit gepollt und so CPU-Zeit gefressen hat. Bei der Condition-Variante wird der Thread solange schlafengelegt, bis die Bedingung erfüllt/signalisiert wird.


Anmelden zum Antworten