Classe Mutex, implémentation au choix

Pour comprendre le code qui suit, il serait préférable de lire au préalable :

Ce qui suit est une ébauche de texte contenant un exemple par lequel il est possible de développer une classe Mutex maison telle que :

Des explications viendront quand j'en aurai le temps.

Le code suit :

Fichier Mutex.h

Explications à venir

#ifndef MUTEX_H
#define MUTEX_H
#include <memory>
class SorteIllegale {};
class Mutex {
public:
   struct Impl;
private:
   std::unique_ptr<Impl> p;
public:
   class Systeme {};
   class Usager {};
   Mutex(); // choix par défaut (local au processus)
   Mutex(Systeme);
   Mutex(Usager);
   ~Mutex();
   void obtenir() const volatile;
   void relacher() const volatile;
};
class Autoverrou {
   const volatile Mutex &m;
public:
   // Incopiable
   Autoverrou(const Autoverrou&) = delete;
   Autoverrou& operator=(const Autoverrou&) = delete;
   Autoverrou(const volatile Mutex &m) : m{ m } {
      m.obtenir();
   }
   ~Autoverrou() {
      m.relacher();
   }
};
#endif
Fichier Mutex.cpp

Explications à venir

#include "Mutex.h"
#include <windows.h>
struct Mutex::Impl {
   virtual void obtenir() const volatile = 0;
   virtual void relacher() const volatile = 0;
   virtual ~Impl() = default;
};
struct ImplUsager : Mutex::Impl {
   mutable CRITICAL_SECTION cs;
   ImplUsager() {
      InitializeCriticalSection(&cs);
   }
   ~ImplUsager() {
      DeleteCriticalSection(&cs);
   }
   void obtenir() const volatile override {
      EnterCriticalSection(&const_cast<ImplUsager*>(this)->cs);
   }
   void relacher() const volatile override {
      LeaveCriticalSection(&const_cast<ImplUsager*>(this)->cs);
   }
};
struct ImplSysteme : Mutex::Impl {
   void obtenir() const volatile override {
      WaitForSingleObject(h, INFINITE);
   }
   void relacher() const volatile override {
      ReleaseMutex(h);
   }
   HANDLE h;
   ImplSysteme() : h{ CreateMutex(0, FALSE, 0) } {
   }
   ~ImplSysteme() {
      CloseHandle(h);
   }
};
Mutex::Mutex() : Mutex{ Usager{} } {
}
Mutex::Mutex(Systeme) : p{ new ImplSysteme } {
}
Mutex::Mutex(Usager) : p{ new ImplUsager } {
}
Mutex::~Mutex() = default;
void Mutex::obtenir() const volatile {
   const_cast<unique_ptr<Impl>&>(p)->obtenir();
}
void Mutex::relacher() const volatile {
   const_cast<unique_ptr<Impl>&>(p)->relacher();
}
Fichier Principal.cpp

Explications à venir

#include "mutex.h"
#include <iostream>
#include <atomic>
#include <thread>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main() {
   Mutex m{  };
   atomic<bool> fin{ false };
   thread th{ [&m, &fin] {
      while(!fin) {
         this_thread::sleep_for(500ms);
         Autoverrou av{ m };
         cout << '.' << flush;
      }
   } };
   this_thread::sleep_for(2s);
   {
      Autoverrou av{ m };
      cout << "Appuyez sur une touche puis <enter>" << endl;
      char c;
      cin.get(c);
      fin = true;
   }
   th.join();
}

Valid XHTML 1.0 Transitional

CSS Valide !