#line 1 "/build/ecl/src/ecl-26.3.27/src/c/threads/rwlock.d"
/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* vim: set filetype=c tabstop=2 shiftwidth=2 expandtab: */

/*
 * rwlock.d - POSIX read-write locks
 *
 * Copyright (c) 2003 Juan Jose Garcia Ripoll
 *
 * See file 'LICENSE' for the copyright details.
 *
 */

#ifndef __sun__ /* See unixinit.d for this */
#define _XOPEN_SOURCE 600       /* For pthread mutex attributes */
#endif
#include <errno.h>
#include <ecl/ecl.h>
#ifdef ECL_WINDOWS_THREADS
# include <windows.h>
#else
# include <pthread.h>
#endif
#include <ecl/internal.h>

/*----------------------------------------------------------------------
 * READ/WRITE LOCKS
 */

cl_object
ecl_make_rwlock(cl_object name)
{
  cl_env_ptr env = ecl_process_env();
  cl_object output = ecl_alloc_object(t_rwlock);
  output->rwlock.name = name;
  ecl_disable_interrupts_env(env);
  ecl_rwlock_init(&output->rwlock.mutex);
  ecl_set_finalizer_unprotected(output, ECL_T);
  ecl_enable_interrupts_env(env);
  return output;
}

#line 42
cl_object mp_make_rwlock(cl_narg narg, ...)
{
#line 42

  #line 44
#if defined(__clang__) || defined(__GNUC__)
	__attribute__((unused)) const cl_env_ptr the_env = ecl_process_env();
#else
	const cl_env_ptr the_env = ecl_process_env();
#endif
#line 44
	static cl_object KEYS[1] = {(cl_object)(cl_symbols+1309)};
	cl_object name;
#line 44
	cl_object KEY_VARS[2];
#line 44
	ecl_va_list ARGS;
	ecl_va_start(ARGS, narg, narg, 0);
#line 44
	if (ecl_unlikely(narg < 0)) FEwrong_num_arguments(ecl_make_fixnum(1481));
#line 44
	cl_parse_key(ARGS, 1, KEYS, KEY_VARS, NULL, 0);
#line 44
	if (KEY_VARS[1]==ECL_NIL) {
#line 44
	  name = ECL_NIL;
	} else {
#line 44
	  name = KEY_VARS[0];
	}
#line 44
  {
#line 44
	#line 44
	cl_object __value0 = ecl_make_rwlock(name);
#line 44
	the_env->nvalues = 1;
#line 44
	the_env->values[0] = __value0;
#line 44
	ecl_va_end(ARGS);
#line 44
	return __value0;
#line 44
}
;
  }

cl_object
mp_rwlock_name(cl_object lock)
{
  const cl_env_ptr env = ecl_process_env();
  if (ecl_unlikely(ecl_t_of(lock) != t_rwlock)) {
    FEwrong_type_only_arg(ecl_make_fixnum(/*MP::RWLOCK-NAME*/1483), lock, ecl_make_fixnum(/*MP::RWLOCK*/1482));
  }
  ecl_return1(env, lock->rwlock.name);
}

cl_object
mp_giveup_rwlock_read(cl_object lock)
{
  const cl_env_ptr env = ecl_process_env();
  int rc;
  if (ecl_unlikely(ecl_t_of(lock) != t_rwlock)) {
    FEwrong_type_only_arg(ecl_make_fixnum(/*MP::GIVEUP-RWLOCK-READ*/1486), lock, ecl_make_fixnum(/*MP::RWLOCK*/1482));
  }
  rc = ecl_rwlock_unlock_read(&lock->rwlock.mutex);
  if (ecl_likely(rc == ECL_MUTEX_SUCCESS)) {
    ecl_return1(env, ECL_T);
  } else if (rc == ECL_MUTEX_NOT_OWNED) {
    FEerror_not_owned(lock);
  } else {
    FEunknown_lock_error(lock);
  }
}

cl_object
mp_giveup_rwlock_write(cl_object lock)
{
  const cl_env_ptr env = ecl_process_env();
  int rc;
  if (ecl_unlikely(ecl_t_of(lock) != t_rwlock)) {
    FEwrong_type_only_arg(ecl_make_fixnum(/*MP::GIVEUP-RWLOCK-WRITE*/1487), lock, ecl_make_fixnum(/*MP::RWLOCK*/1482));
  }
  rc = ecl_rwlock_unlock_write(&lock->rwlock.mutex);
  if (ecl_likely(rc == ECL_MUTEX_SUCCESS)) {
    ecl_return1(env, ECL_T);
  } else if (rc == ECL_MUTEX_NOT_OWNED) {
    FEerror_not_owned(lock);
  } else {
    FEunknown_lock_error(lock);
  }
}

cl_object
mp_get_rwlock_read_nowait(cl_object lock)
{
  const cl_env_ptr env = ecl_process_env();
  int rc;
  if (ecl_unlikely(ecl_t_of(lock) != t_rwlock)) {
    FEwrong_type_only_arg(ecl_make_fixnum(/*MP::GET-RWLOCK-READ*/1484), lock, ecl_make_fixnum(/*MP::RWLOCK*/1482));
  }
  rc = ecl_rwlock_trylock_read(&lock->rwlock.mutex);
  if (rc == ECL_MUTEX_SUCCESS) {
    ecl_return1(env, ECL_T);
  } else if (rc == ECL_MUTEX_LOCKED) {
    ecl_return1(env, ECL_NIL);
  } else {
    FEunknown_lock_error(lock);
  }
}

cl_object
mp_get_rwlock_read_wait(cl_object lock)
{
  const cl_env_ptr env = ecl_process_env();
  int rc;
  if (ecl_unlikely(ecl_t_of(lock) != t_rwlock)) {
    FEwrong_type_only_arg(ecl_make_fixnum(/*MP::GET-RWLOCK-READ*/1484), lock, ecl_make_fixnum(/*MP::RWLOCK*/1482));
  }
  rc = ecl_rwlock_lock_read(&lock->rwlock.mutex);
  if (ecl_likely(rc == ECL_MUTEX_SUCCESS)) {
    ecl_return1(env, ECL_T);
  } else {
    FEunknown_lock_error(lock);
  }
}

#line 127
cl_object mp_get_rwlock_read(cl_narg narg, cl_object lock, ...)
{
#line 127

  #line 129
#if defined(__clang__) || defined(__GNUC__)
	__attribute__((unused)) const cl_env_ptr the_env = ecl_process_env();
#else
	const cl_env_ptr the_env = ecl_process_env();
#endif
#line 129
	cl_object wait;
#line 129
	va_list ARGS;
	va_start(ARGS, lock);
#line 129
	if (ecl_unlikely(narg < 1|| narg > 2)) FEwrong_num_arguments(ecl_make_fixnum(1484));
#line 129
	if (narg > 1) {
#line 129
		wait = va_arg(ARGS,cl_object);
#line 129
	} else {
#line 129
		wait = ECL_T;
#line 129
	}
#line 129
  if (Null(wait)) {
    return mp_get_rwlock_read_nowait(lock);
  } else {
    return mp_get_rwlock_read_wait(lock);
  }
  }

cl_object
mp_get_rwlock_write_nowait(cl_object lock)
{
  const cl_env_ptr env = ecl_process_env();
  int rc;
  if (ecl_unlikely(ecl_t_of(lock) != t_rwlock)) {
    FEwrong_type_only_arg(ecl_make_fixnum(/*MP::GET-RWLOCK-WRITE*/1485), lock, ecl_make_fixnum(/*MP::RWLOCK*/1482));
  }
  rc = ecl_rwlock_trylock_write(&lock->rwlock.mutex);
  if (rc == ECL_MUTEX_SUCCESS) {
    ecl_return1(env, ECL_T);
  } else if (rc == ECL_MUTEX_LOCKED) {
    ecl_return1(env, ECL_NIL);
  } else {
    FEunknown_lock_error(lock);
  }
}

cl_object
mp_get_rwlock_write_wait(cl_object lock)
{
  const cl_env_ptr env = ecl_process_env();
  int rc;
  if (ecl_unlikely(ecl_t_of(lock) != t_rwlock)) {
    FEwrong_type_only_arg(ecl_make_fixnum(/*MP::GET-RWLOCK-WRITE*/1485), lock, ecl_make_fixnum(/*MP::RWLOCK*/1482));
  }
  rc = ecl_rwlock_lock_write(&lock->rwlock.mutex);
  if (ecl_likely(rc == ECL_MUTEX_SUCCESS)) {
    ecl_return1(env, ECL_T);
  } else {
    FEunknown_lock_error(lock);
  }
}

#line 170
cl_object mp_get_rwlock_write(cl_narg narg, cl_object lock, ...)
{
#line 170

  #line 172
#if defined(__clang__) || defined(__GNUC__)
	__attribute__((unused)) const cl_env_ptr the_env = ecl_process_env();
#else
	const cl_env_ptr the_env = ecl_process_env();
#endif
#line 172
	cl_object wait;
#line 172
	va_list ARGS;
	va_start(ARGS, lock);
#line 172
	if (ecl_unlikely(narg < 1|| narg > 2)) FEwrong_num_arguments(ecl_make_fixnum(1485));
#line 172
	if (narg > 1) {
#line 172
		wait = va_arg(ARGS,cl_object);
#line 172
	} else {
#line 172
		wait = ECL_T;
#line 172
	}
#line 172
  if (Null(wait)) {
    return mp_get_rwlock_write_nowait(lock);
  } else {
    return mp_get_rwlock_write_wait(lock);
  }
  }
