Mal wieder Thread schlafen legen



  • Hallo zusammen,

    ich möchte einen thread 'a' von thread 'b' aus schlafen legen.
    Im Fall, dass 'a' nicht schlafen muss, soll die Überprüfung lockfrei gehen.

    Was haltet ihr von folgender Implementierung:

    class Event
    {
    public:
      Event() : mCond(false) {}
    
      void Set()
      {
        std::mutex::scoped_lock lock(mMutex);
        mCond = true;
        mCondVar.notify_all();
      }
    
      void WaitReset()
      {
        std::unique_lock<std::mutex> lock(mMutex);
        while (!mCond) mCondVar.wait(lock);
        mCond = false;
      }
    
    private:
      std::mutex              mMutex;
      std::condition_variable mCondVar;
      bool                    mCond;
    };
    
    class SleepFlag
    {
    public:  
      SleepFlag() : mSleep(false) {}
    
      // called by thread a
      void Check()
      {
        if (mSleep) {
          mWakeUp.WaitReset();
        }
      }
    
      // called by thread b
      void Sleep()
      {
        mSleep = true;
      }
    
      void WakeUp()
      {
        mSleep = false;
        mWakeUp.Set();
      }
    
    private:
      std::atomic<bool> mSleep;
      Event             mWakeUp;
    };
    


  • Wozu soll denn das gut sein?



  • Ich würde die beiden Klassen zu einer zusammenfassen, und dann "mCond" und "mSleep" zu einer Variable zusammenfassen.
    Dadurch ergibt sich das klassische "double checked locking" - was dank std::atomic in diesem Fall auch "sicher" ist.

    So wie du es geschrieben hast, könnte es nämlich Probleme geben, sobald es mehr als einen "Thread A" gibt.

    Was mMn. auch überhaupt keinen Sinn macht, ist dass du einen "auto reset event" implementierst, und dabei notify_all verwendest.
    Der zweite Thread der aufwacht sieht ja bereits wieder mCond == false , und legt sich daher gleich wieder heia. Wozu ihn dann überhaupt aufwecken?



  • Ok, danke für den Tipp hustbaer!


Log in to reply