#pragma once

namespace std {

  template <class Mutex>
  class unique_lock {

    Mutex *the_mutex;
    bool has_locked;

  public:
    inline unique_lock() noexcept : the_mutex(0) {}

    unique_lock(const unique_lock &other) = delete;

    inline unique_lock(unique_lock &&other) noexcept
    : the_mutex(other.the_mutex), has_locked(other.has_locked) {
      other.the_mutex = 0;
    }

    inline explicit unique_lock(Mutex &m)
    : the_mutex(&m), has_locked(true) {
      the_mutex->lock();
    }

    inline ~unique_lock() {
      if (the_mutex && has_locked)
        the_mutex->unlock();
    }

    unique_lock &operator =(const unique_lock &other) = delete;

    inline unique_lock &operator =(unique_lock &&other) {
      if (the_mutex && has_locked)
        the_mutex->unlock();
      the_mutex = other.the_mutex;
      has_locked = other.has_locked;
      other.the_mutex = 0;
    }

    inline void lock() {
      the_mutex->lock();
      has_locked = true;
    }

    inline void unlock() {
      the_mutex->unlock();
      has_locked = false;
    }

  };

}
