<commit_before>/*
 * Copyright (C) 2010-2016 <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

/* Taken from "Strategies for Implementing POSIX Condition Variables on Win32"
 * by <NAME> and <NAME>.
 * See: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
 * See: https://github.com/python/cpython/blob/master/Python/condvar.h
 */

#include "pmem.h"
#include "pcondvariable.h"

#include <stdlib.h>

typedef VOID (WINAPI * InitializeConditionVariableFunc) (ppointer cv);
typedef BOOL (WINAPI * SleepConditionVariableCSFunc)    (ppointer cv, PCRITICAL_SECTION cs, DWORD ms);
typedef VOID (WINAPI * WakeConditionVariableFunc)       (ppointer cv);
typedef VOID (WINAPI * WakeAllConditionVariableFunc)    (ppointer cv);

typedef pboolean (* PWin32CondInit)    (PCondVariable *cond);
typedef void     (* PWin32CondClose)   (PCondVariable *cond);
typedef pboolean (* PWin32CondWait)    (PCondVariable *cond, PMutex *mutex);
typedef pboolean (* PWin32CondSignal)  (PCondVariable *cond);
typedef pboolean (* PWin32CondBrdcast) (PCondVariable *cond);

static PWin32CondInit    pp_cond_variable_init_func    = NULL;
static PWin32CondClose   pp_cond_variable_close_func   = NULL;
static PWin32CondWait    pp_cond_variable_wait_func    = NULL;
static PWin32CondSignal  pp_cond_variable_signal_func  = NULL;
static PWin32CondBrdcast pp_cond_variable_brdcast_func = NULL;

typedef struct PCondVariableVistaTable_ {
	InitializeConditionVariableFunc	cv_init;
	SleepConditionVariableCSFunc	cv_wait;
	WakeConditionVariableFunc	cv_wake;
	WakeAllConditionVariableFunc	cv_brdcast;
} PCondVariableVistaTable;

typedef struct PCondVariableXP_ {
	HANDLE	waiters_sema;
	pint	waiters_count;
} PCondVariableXP;

struct PCondVariable_ {
	ppointer cv;
};

static PCondVariableVistaTable pp_cond_variable_vista_table = {NULL, NULL, NULL, NULL};

/* CONDITION_VARIABLE routines */
static pboolean pp_cond_variable_init_vista (PCondVariable *cond);
static void pp_cond_variable_close_vista (PCondVariable *cond);
static pboolean pp_cond_variable_wait_vista (PCondVariable *cond, PMutex *mutex);
static pboolean pp_cond_variable_signal_vista (PCondVariable *cond);
static pboolean pp_cond_variable_broadcast_vista (PCondVariable *cond);

/* Windows XP emulation routines */
static pboolean pp_cond_variable_init_xp (PCondVariable *cond);
static void pp_cond_variable_close_xp (PCondVariable *cond);
static pboolean pp_cond_variable_wait_xp (PCondVariable *cond, PMutex *mutex);
static pboolean pp_cond_variable_signal_xp (PCondVariable *cond);
static pboolean pp_cond_variable_broadcast_xp (PCondVariable *cond);

/* CONDITION_VARIABLE routines */

static pboolean
pp_cond_variable_init_vista (PCondVariable *cond)
{
	pp_cond_variable_vista_table.cv_init (cond);

	return TRUE;
}

static void
pp_cond_variable_close_vista (PCondVariable *cond)
{
	P_UNUSED (cond);
}

static pboolean
pp_cond_variable_wait_vista (PCondVariable *cond, PMutex *mutex)
{
	return pp_cond_variable_vista_table.cv_wait (cond,
						     (PCRITICAL_SECTION) mutex,
						     INFINITE) != 0 ? TRUE : FALSE;
}

static pboolean
pp_cond_variable_signal_vista (PCondVariable *cond)
{
	pp_cond_variable_vista_table.cv_wake (cond);

	return TRUE;
}

static pboolean
pp_cond_variable_broadcast_vista (PCondVariable *cond)
{
	pp_cond_variable_vista_table.cv_brdcast (cond);

	return TRUE;
}

/* Windows XP emulation routines */

static pboolean
pp_cond_variable_init_xp (PCondVariable *cond)
{
	PCondVariableXP *cv_xp;

	if ((cond->cv = p_malloc0 (sizeof (PCondVariableXP))) == NULL) {
		P_ERROR ("PCondVariable::pp_cond_variable_init_xp: failed to allocate memory (internal)");
		return FALSE;
	}

	cv_xp = ((PCondVariableXP *) cond->cv);

	cv_xp->waiters_count = 0;
	cv_xp->waiters_sema  = CreateSemaphoreA (NULL, 0, MAXLONG, NULL);

	if (P_UNLIKELY (cv_xp->waiters_sema == NULL)) {
		P_ERROR ("PCondVariable::pp_cond_variable_init_xp: failed to initialize semaphore");
		p_free (cond->cv);
		cond->cv = NULL;
		return FALSE;
	}

	return TRUE;
}

static void
pp_cond_variable_close_xp (PCondVariable *cond)
{
	CloseHandle (((PCondVariableXP *) cond->cv)->waiters_sema);
	p_free (cond->cv);
}

static pboolean
pp_cond_variable_wait_xp (PCondVariable *cond, PMutex *mutex)
{
	PCondVariableXP	*cv_xp = ((PCondVariableXP *) cond->cv);
	DWORD		wait;

	cv_xp->waiters_count++;

	p_mutex_unlock (mutex);
	wait = WaitForSingleObjectEx (cv_xp->waiters_sema, INFINITE, FALSE);
	p_mutex_lock (mutex);

	if (wait != WAIT_OBJECT_0)
		--cv_xp->waiters_count;

	if (wait == WAIT_FAILED)
		return FALSE;

	return wait == WAIT_OBJECT_0 ? TRUE : FALSE;
}

static pboolean
pp_cond_variable_signal_xp (PCondVariable *cond)
{
	PCondVariableXP *cv_xp = ((PCondVariableXP *) cond->cv);

	if (cv_xp->waiters_count > 0) {<commit_msg>win: Simplify return result condition<commit_after>/*
 * Copyright (C) 2010-2017 <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

/* Taken from "Strategies for Implementing POSIX Condition Variables on Win32"
 * by <NAME> and <NAME>.
 * See: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
 * See: https://github.com/python/cpython/blob/master/Python/condvar.h
 */

#include "pmem.h"
#include "pcondvariable.h"

#include <stdlib.h>

typedef VOID (WINAPI * InitializeConditionVariableFunc) (ppointer cv);
typedef BOOL (WINAPI * SleepConditionVariableCSFunc)    (ppointer cv, PCRITICAL_SECTION cs, DWORD ms);
typedef VOID (WINAPI * WakeConditionVariableFunc)       (ppointer cv);
typedef VOID (WINAPI * WakeAllConditionVariableFunc)    (ppointer cv);

typedef pboolean (* PWin32CondInit)    (PCondVariable *cond);
typedef void     (* PWin32CondClose)   (PCondVariable *cond);
typedef pboolean (* PWin32CondWait)    (PCondVariable *cond, PMutex *mutex);
typedef pboolean (* PWin32CondSignal)  (PCondVariable *cond);
typedef pboolean (* PWin32CondBrdcast) (PCondVariable *cond);

static PWin32CondInit    pp_cond_variable_init_func    = NULL;
static PWin32CondClose   pp_cond_variable_close_func   = NULL;
static PWin32CondWait    pp_cond_variable_wait_func    = NULL;
static PWin32CondSignal  pp_cond_variable_signal_func  = NULL;
static PWin32CondBrdcast pp_cond_variable_brdcast_func = NULL;

typedef struct PCondVariableVistaTable_ {
	InitializeConditionVariableFunc	cv_init;
	SleepConditionVariableCSFunc	cv_wait;
	WakeConditionVariableFunc	cv_wake;
	WakeAllConditionVariableFunc	cv_brdcast;
} PCondVariableVistaTable;

typedef struct PCondVariableXP_ {
	HANDLE	waiters_sema;
	pint	waiters_count;
} PCondVariableXP;

struct PCondVariable_ {
	ppointer cv;
};

static PCondVariableVistaTable pp_cond_variable_vista_table = {NULL, NULL, NULL, NULL};

/* CONDITION_VARIABLE routines */
static pboolean pp_cond_variable_init_vista (PCondVariable *cond);
static void pp_cond_variable_close_vista (PCondVariable *cond);
static pboolean pp_cond_variable_wait_vista (PCondVariable *cond, PMutex *mutex);
static pboolean pp_cond_variable_signal_vista (PCondVariable *cond);
static pboolean pp_cond_variable_broadcast_vista (PCondVariable *cond);

/* Windows XP emulation routines */
static pboolean pp_cond_variable_init_xp (PCondVariable *cond);
static void pp_cond_variable_close_xp (PCondVariable *cond);
static pboolean pp_cond_variable_wait_xp (PCondVariable *cond, PMutex *mutex);
static pboolean pp_cond_variable_signal_xp (PCondVariable *cond);
static pboolean pp_cond_variable_broadcast_xp (PCondVariable *cond);

/* CONDITION_VARIABLE routines */

static pboolean
pp_cond_variable_init_vista (PCondVariable *cond)
{
	pp_cond_variable_vista_table.cv_init (cond);

	return TRUE;
}

static void
pp_cond_variable_close_vista (PCondVariable *cond)
{
	P_UNUSED (cond);
}

static pboolean
pp_cond_variable_wait_vista (PCondVariable *cond, PMutex *mutex)
{
	return pp_cond_variable_vista_table.cv_wait (cond,
						     (PCRITICAL_SECTION) mutex,
						     INFINITE) != 0 ? TRUE : FALSE;
}

static pboolean
pp_cond_variable_signal_vista (PCondVariable *cond)
{
	pp_cond_variable_vista_table.cv_wake (cond);

	return TRUE;
}

static pboolean
pp_cond_variable_broadcast_vista (PCondVariable *cond)
{
	pp_cond_variable_vista_table.cv_brdcast (cond);

	return TRUE;
}

/* Windows XP emulation routines */

static pboolean
pp_cond_variable_init_xp (PCondVariable *cond)
{
	PCondVariableXP *cv_xp;

	if ((cond->cv = p_malloc0 (sizeof (PCondVariableXP))) == NULL) {
		P_ERROR ("PCondVariable::pp_cond_variable_init_xp: failed to allocate memory (internal)");
		return FALSE;
	}

	cv_xp = ((PCondVariableXP *) cond->cv);

	cv_xp->waiters_count = 0;
	cv_xp->waiters_sema  = CreateSemaphoreA (NULL, 0, MAXLONG, NULL);

	if (P_UNLIKELY (cv_xp->waiters_sema == NULL)) {
		P_ERROR ("PCondVariable::pp_cond_variable_init_xp: failed to initialize semaphore");
		p_free (cond->cv);
		cond->cv = NULL;
		return FALSE;
	}

	return TRUE;
}

static void
pp_cond_variable_close_xp (PCondVariable *cond)
{
	CloseHandle (((PCondVariableXP *) cond->cv)->waiters_sema);
	p_free (cond->cv);
}

static pboolean
pp_cond_variable_wait_xp (PCondVariable *cond, PMutex *mutex)
{
	PCondVariableXP	*cv_xp = ((PCondVariableXP *) cond->cv);
	DWORD		wait;

	cv_xp->waiters_count++;

	p_mutex_unlock (mutex);
	wait = WaitForSingleObjectEx (cv_xp->waiters_sema, INFINITE, FALSE);
	p_mutex_lock (mutex);

	if (wait != WAIT_OBJECT_0)
		--cv_xp->waiters_count;

	return wait == WAIT_OBJECT_0 ? TRUE : FALSE;
}

static pboolean
pp_cond_variable_signal_xp (PCondVariable *cond)
{
	PCondVariableXP *cv_xp = ((PCondVariableXP *) cond->cv);

	if (cv_xp->waiters_count > 0) {
{'fraction_non_alphanumeric': 0.0924737184854405, 'fraction_numerical': 0.0076286166154991165, 'mean_word_length': 5.714553404122423, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 51, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7285059', 'n_tokens_mistral': 3810, 'n_tokens_neox': 3595, 'n_words': 927}