text: // license:BSD-3-Clause
  // copyright-holders:Olivier Galibert, R. Belmont
  //============================================================
  //
  //  osdsync.h - Core synchronization functions
  //
  //============================================================
  #ifndef MAME_OSD_OSDSYNC_H
  #define MAME_OSD_OSDSYNC_H
  
  #pragma once
  
  // C++ headers
  #include <mutex>
  #include <atomic>
  #include <condition_variable>
  
  #include "osdcomm.h"
  
  /***************************************************************************
      SYNCHRONIZATION INTERFACES - Events
  ***************************************************************************/
  
  #define OSD_EVENT_WAIT_INFINITE (~(osd_ticks_t)0)
  
  /* osd_event is an opaque type which represents a setable/resettable event */
  
  class osd_event
  {
  public:
  	/*-----------------------------------------------------------------------------
  	    constructor: allocate a new event
  
  	    Parameters:
  
  	        manualreset  - boolean. If true, the event will be automatically set
  	                       to non-signalled after a thread successfully waited for
  	                       it.
  	        initialstate - boolean. If true, the event is signalled initially.
  
  	    Return value:
  
  	        A pointer to the allocated event.
  	-----------------------------------------------------------------------------*/
  	osd_event(int manualreset, int initialstate)
  	{
  		m_signalled = initialstate;
  		m_autoreset = !manualreset;
  	}
  
  	~osd_event()
  	{
  	}
  
  	/*-----------------------------------------------------------------------------
  	    wait:   wait for an event to be signalled
  	            If the event is in signalled state, the
  	            function returns immediately. If not it will wait for the event
  	            to become signalled.
  
  	    Parameters:
  
  	        timeout - timeout in osd_ticks
  
  	    Return value:
  
  	        true:  The event was signalled
  	        false: A timeout occurred
  	-----------------------------------------------------------------------------*/
  
  	bool wait(osd_ticks_t timeout)
  	{
  		if (timeout == OSD_EVENT_WAIT_INFINITE)
  			timeout = osd_ticks_per_second() * (osd_ticks_t)10000;
  
  		std::unique_lock<std::mutex> lock(m_mutex);
  		if (!timeout)
  		{
  			if (!m_signalled)
  			{
  				return false;
  			}
  		}
  		else
  		{
  			if (!m_signalled)
  			{
  				uint64_t msec = timeout * 1000 / osd_ticks_per_second();
  
  				do {
  					if (m_cond.wait_for(lock, std::chrono::milliseconds(msec)) == std::cv_status::timeout)
  					{
  						if (!m_signalled)
  						{
  							return false;
  						}
  						else
  							break;
  					} else
  						break;
  
  				} while (true);
  			}
  		}
  
  		if (m_autoreset)
  			m_signalled = 0;
  
  		return true;
  	}
  
  	/*-----------------------------------------------------------------------------
  	    osd_event_reset: reset an event to non-signalled state
  
  	    Parameters:
  
  	        None
  
  	    Return value:
  
  	        None
  	-----------------------------------------------------------------------------*/
  	void reset()
  	{
  		m_mutex.lock();
  		m_signalled = false;
  		m_mutex.unlock();
  	}
  
  	/*-----------------------------------------------------------------------------
  	    osd_event_set: set an event to signalled state
  
  	    Parameters:
  
  	        None
  
  	    Return value:
  
  	        Whether or not the event was actually signalled (false if the event had already been signalled)
  
  	    Notes:
  
  	        All threads waiting for the event will be signalled.
  	-----------------------------------------------------------------------------*/
  	bool set()
  	{
  		m_mutex.lock();
  		bool needs_signal = !m_signalled;
  		if (needs_signal)
  		{
  			m_signalled = true;
  			if (m_autoreset)
  				m_cond.notify_one();
  			else
  				m_cond.notify_all();
  		}
  		m_mutex.unlock();
  		return needs_signal;
  	}
  
  private:
  	std::mutex               m_mutex;
  	std::condition_variable  m_cond;
  	int32_t                  m_autoreset;
  	int32_t                  m_signalled;
  
  };
  
  #endif // MAME_OSD_OSDSYNC_H
  