/*
    PIP - Platform Independent Primitives
    Mutex
    Copyright (C) 2015  Ivan Pelipenko peri4ko@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "pimutex.h"


/** \class PIMutex
 * \brief Mutex
 * \details 
 * \section PIMutex_sec0 Synopsis
 * %PIMutex provides synchronization blocks between several threads.
 * Using mutex guarantees execution of some code only one of threads.
 * Mutex contains logic state and functions to change it: \a lock(),
 * \a unlock() and \a tryLock().
 * 
 * \section PIMutex_sec1 Usage
 * Block of code that should to be executed only one thread simultaniously
 * should to be started with \a lock() and ended with \a unlock().
 * \snippet pimutex.cpp main
 * "mutex" in this example is one for all threads.
 * 
 * */


PIMutex::PIMutex() {
#ifdef WINDOWS
	mutex = CreateMutex(0, false, 0);
#else
	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutex_init(&mutex, &attr);
	pthread_mutexattr_destroy(&attr);
#endif
	locked = false;
}


PIMutex::~PIMutex() {
#ifdef WINDOWS
	if (mutex != 0) CloseHandle(mutex);
#else
	pthread_mutex_destroy(&mutex);
#endif
	locked = false;
}


void PIMutex::lock() {
#ifdef WINDOWS
	WaitForSingleObject(mutex, INFINITE);
#else
	pthread_mutex_lock(&mutex);
#endif
	locked = true;
}


void PIMutex::unlock() {
#ifdef WINDOWS
	ReleaseMutex(mutex);
#else
	pthread_mutex_unlock(&mutex);
#endif
	locked = false;
}


bool PIMutex::tryLock() {
	bool ret =
#ifdef WINDOWS
			(WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0);
#else
			(pthread_mutex_trylock(&mutex) == 0);
#endif
	locked = true;
	return ret;
}


bool PIMutex::isLocked() const {
	return locked;
}
