[gelöst] Mutex nach Initialisierung gelockt!?

  • Themenstarter Themenstarter Gelöschtes Mitglied 16444
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 16444

Guest
Moin, Moin!

Ich schlage mich hier gerade mit einem Multithreadingproblem herum und sehe den Fehler einfach nicht. Meine Applikation erstellt an einem Punkt einen neuen Thread, um GPS Informationen zu empfangen. In der Hauptapplikation werden die empfangenen Positionen dann zwischen durch immer mal wieder abgefragt. Ich habe die Datenstruktur, die die Positionen speichert deshalb mit einem Mutex geschützt. Das Problem ist nur, dass bereits der erste Aufruf um den Mutex zu sperren blockiert bzw. den Fehler schmeißt, der Mutex sei bereits gesperrt. Irgendwo muss in meinem Programm also ein Fehler sein, aber ich finde ihn einfach nicht. Sieht vielleicht einer von euch, wo das Problem liegt?

Code:
void Executor::startReceivingGPSData()
{
    gpsInfos = new GPSMoveCommand::VehicleInfos();

    gpsReceiverThread = new pthread_t;
    int err = pthread_create( gpsReceiverThread, NULL, Executor::gpsReceivingFunc, &gpsInfos);
    if(err)
    {
        logger << "GPS receiving thread: pthread_create() failed with error code: " << err
               << " " << strerror(err);
    }
}
Code:
/* static */ void * Executor::gpsReceivingFunc( void * result )
{
    logger << "GPS receiving thread started";

    GPSMoveCommand::VehicleInfos * const vehicleInfos = reinterpret_cast<GPSMoveCommand::VehicleInfos * const>(result);

    Receiver & receiver = Receiver::getInstance();
    receiver.startReceive( vehicleInfos );

    return NULL;
}
Code:
class GPSMoveCommand
{

public:

  struct VehicleInfos
  {
      typedef std::map<int, double> vehicleInfo;
      typedef std::map<unsigned int, vehicleInfo> vehicleInfoList;
      
      VehicleInfos()
      {
          pthread_mutexattr_t attr;
          pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

          int err = pthread_mutex_init( &mutex, &attr );
          if( err )
          {
              logger << "Failed to init mutex: "
                     << strerror(err);
          }
      };

      double getLongByVehicle( const unsigned int vehicleID )
      {
          if( vehicles.end() == vehicles.find(vehicleID) )
          {
              logger << "Got Request for GPS information for non-existing vehicleId=" << vehicleID;

              return 0;
          }

          int err = pthread_mutex_trylock( &mutex );
          if( err )
          {
              logger << "Failed to lock mutex: "
                     << strerror(err);

              return 0;
          }

          const double longitudeDeg = vehicles[vehicleID].at(longitude);

          err = pthread_mutex_unlock( &mutex );
          if( err )
          {
              logger << "Failed to unlock mutex: "
                     << strerror(err);
          }

          return longitudeDeg;
      };

      double getLatByVehicle( const unsigned int vehicleID )
      {
          if( vehicles.end() == vehicles.find(vehicleID) )
          {
              logger << "Got Request for GPS information for non-existing vehicleId=" << vehicleID;

              return 0;
          }

          int err = pthread_mutex_trylock( &mutex );
          if( err )
          {
              logger << "Failed to lock mutex: "
                     << strerror(err);

              return 0;
          }

          const double latitudeDeg = vehicles[vehicleID].at(latitude);

          err = pthread_mutex_unlock( &mutex );
          if( err )
          {
              logger << "Failed to unlock mutex: "
                     << strerror(err);
          }

          return latitudeDeg;
      };

      double getVelocityByVehicle( const unsigned int vehicleID )
      {
          if( vehicles.end() == vehicles.find(vehicleID) )
          {
              logger << "Got Request for GPS information for non-existing vehicleId=" << vehicleID;

              return 0;
          }

          int err = pthread_mutex_trylock( &mutex );
          if( err )
          {
              logger << "Failed to lock mutex: "
                     << strerror(err);

              return 0;
          }

          const double velocityMPS = vehicles[vehicleID].at(velocity);

          err = pthread_mutex_unlock( &mutex );
          if( err )
          {
              logger << "Failed to unlock mutex: "
                     << strerror(err);
          }

          return velocityMPS;
      };

      void setLongByVehicle( const unsigned int vehicleID, const double value )
      {
          int err = pthread_mutex_trylock( &mutex );
          if( err )
          {
              logger << "Failed to lock mutex: "
                     << strerror(err);

              return;
          }

          vehicles[vehicleID][longitude] = value;

          err = pthread_mutex_unlock( &mutex );
          if( err )
          {
              logger << "Failed to unlock mutex: "
                     << strerror(err);
          }
      };

      void setLatByVehicle( const unsigned int vehicleID, const double value )
      {
          int err = pthread_mutex_trylock( &mutex );
          if( err )
          {
              logger << "Failed to lock mutex: "
                     << strerror(err);

              return;
          }

          vehicles[vehicleID][latitude] = value;

          err = pthread_mutex_unlock( &mutex );
          if( err )
          {
              logger << "Failed to unlock mutex: "
                     << strerror(err);
          }
      };

      void setVelocityByVehicle( const unsigned int vehicleID, const double value )
      {
          int err = pthread_mutex_trylock( &mutex );
          if( err )
          {
              logger << "Failed to lock mutex: "
                     << strerror(err);

              return;
          }

          vehicles[vehicleID][velocity] = value;

          err = pthread_mutex_unlock( &mutex );
          if( err )
          {
              logger << "Failed to unlock mutex: "
                     << strerror(err);
          }
      };

      private:
          enum infos {
              latitude = 0,
              longitude,
              velocity
          };

      vehicleInfoList vehicles;
      pthread_mutex_t mutex;
  };
  
  //...
  
};
 
Zuletzt bearbeitet von einem Moderator:
Ich bin jetzt grad etwas zu faul den gesamten Quellcode zu lesen, aber wie initialisierst du die Lock?

Schau dir vielleicht mal eine Semaphore an, die du mit einem Platz initialisierst, dadurch erzielst du nichts anderes, als ein Mutex.


Hier etwas Quellcode, sehr spartanisch, aber überschaubar ;)
Code:
#ifndef CMUTEX_H_
#define CMUTEX_H_


#include <semaphore.h>
#include <errno.h>

class CMutex {
public:
    CMutex();
    ~CMutex();

    void lock();
    void unlock();
    bool tryLock();

private:
    sem_t _sem;

};

#endif /* CMUTEX_H_ */

#include "CMutex.h"

CMutex::CMutex() {
    sem_init(&_sem, 0, 1);
}

CMutex::~CMutex() {
    sem_destroy(&_sem);
}

void CMutex::lock() {
    sem_wait(&_sem);
}

void CMutex::unlock() {
    sem_post(&_sem);
}

bool CMutex::tryLock() {
    if (sem_trywait(&_sem) == EAGAIN
        )
        return false;
    return true;
}
 
Ich initialisiere den Mutex im Konstruktor, wie im Code oben geschrieben.

Code:
pthread_mutexattr_t attr;
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

int err = pthread_mutex_init( &mutex, &attr );
if( err )
{
          logger << "Failed to init mutex: "
                 << strerror(err);
}

Ich habe es auch mit PTHREAD_MUTEX_ERRORCHECK (brachte keine weiteren Erkenntnisse) oder einfach mit
Code:
pthread_mutex_init( &mutex, NULL );
versucht. Immer das selbe Problem.

Übrigens habe ich mich evtl. etwas missverständlich ausgedrückt. Direkt nach der Initialisierung ist der Mutex nicht gesperrt. Ein Entsperren wirft einen entsprechenden Fehler.

Außerdem scheint der Mainthread, der nur lesend auf die Daten zugreift (also nur die Getter aufruft) das Problem nicht zu haben. Scheinbar kann dieser problemlos den Mutex sperren und entsperren.


~~EDIT~~

Je dummer der Fehler, desto länger sucht man ihn :rolleyes:
Beim erzeugen des Threads wende ich den Adressoperator auf das Argument an, obwohl es ja bereits ein Zeiger ist. Wenn ich das & entferne funktioniert alles, wie es soll:

Code:
int err = pthread_create( gpsReceiverThread, NULL, Executor::gpsReceivingFunc, gpsInfos);
 
Zuletzt bearbeitet von einem Moderator:
Zurück
Oben