// @(#)root/thread
// Author: Danilo Piparo, 2016

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TSpinMutex
#define ROOT_TSpinMutex

#include <atomic>

namespace ROOT {

   /**
    * \class ROOT::TSpinMutex
    * \brief A spin mutex class which respects the STL interface for mutexes.
    * \ingroup Multicore
    * This class allows to acquire spin locks also in combination with templates in the STL such as
    * <a href="http://en.cppreference.com/w/cpp/thread/unique_lock">std::unique_lock</a> or
    * <a href="http://en.cppreference.com/w/cpp/thread/condition_variable_any">std::condition_variable_any</a>.
    * For example:
    * ~~~ {.cpp}
    * ROOT::TSpinMutex m;
    * std::condition_variable cv;
    * bool ready = false;
    *
    * void worker_thread()
    * {
    *    // Wait until main() sends data
    *    std::unique_lock<ROOT::TSpinMutex> lk(m);
    *    cv.wait(lk, []{return ready;});
    * [...]
    * ~~~ {.cpp}
    */
   class TSpinMutex {

   private:
      std::atomic_flag fAFlag = ATOMIC_FLAG_INIT;

   public:
      TSpinMutex() = default;
      TSpinMutex(const TSpinMutex&) = delete;
      ~TSpinMutex() = default;
      TSpinMutex& operator=(const TSpinMutex&) = delete;

      void lock() { while (fAFlag.test_and_set(std::memory_order_acquire)); }
      void unlock() { fAFlag.clear(std::memory_order_release); }
      bool try_lock() { return !fAFlag.test_and_set(std::memory_order_acquire); }

   };
}

#endif
 TSpinMutex.hxx:1
 TSpinMutex.hxx:2
 TSpinMutex.hxx:3
 TSpinMutex.hxx:4
 TSpinMutex.hxx:5
 TSpinMutex.hxx:6
 TSpinMutex.hxx:7
 TSpinMutex.hxx:8
 TSpinMutex.hxx:9
 TSpinMutex.hxx:10
 TSpinMutex.hxx:11
 TSpinMutex.hxx:12
 TSpinMutex.hxx:13
 TSpinMutex.hxx:14
 TSpinMutex.hxx:15
 TSpinMutex.hxx:16
 TSpinMutex.hxx:17
 TSpinMutex.hxx:18
 TSpinMutex.hxx:19
 TSpinMutex.hxx:20
 TSpinMutex.hxx:21
 TSpinMutex.hxx:22
 TSpinMutex.hxx:23
 TSpinMutex.hxx:24
 TSpinMutex.hxx:25
 TSpinMutex.hxx:26
 TSpinMutex.hxx:27
 TSpinMutex.hxx:28
 TSpinMutex.hxx:29
 TSpinMutex.hxx:30
 TSpinMutex.hxx:31
 TSpinMutex.hxx:32
 TSpinMutex.hxx:33
 TSpinMutex.hxx:34
 TSpinMutex.hxx:35
 TSpinMutex.hxx:36
 TSpinMutex.hxx:37
 TSpinMutex.hxx:38
 TSpinMutex.hxx:39
 TSpinMutex.hxx:40
 TSpinMutex.hxx:41
 TSpinMutex.hxx:42
 TSpinMutex.hxx:43
 TSpinMutex.hxx:44
 TSpinMutex.hxx:45
 TSpinMutex.hxx:46
 TSpinMutex.hxx:47
 TSpinMutex.hxx:48
 TSpinMutex.hxx:49
 TSpinMutex.hxx:50
 TSpinMutex.hxx:51
 TSpinMutex.hxx:52
 TSpinMutex.hxx:53
 TSpinMutex.hxx:54
 TSpinMutex.hxx:55
 TSpinMutex.hxx:56
 TSpinMutex.hxx:57
 TSpinMutex.hxx:58