blob: ad9fa20e2ea67be39cfa28c5ed346b63ac03c959 [file] [log] [blame]
/*
This file is part of libmicrohttpd
Copyright (C) 2016 Karlson2k (Evgeny Grin)
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.1 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file microhttpd/mhd_locks.h
* @brief Header for platform-independent locks abstraction
* @author Karlson2k (Evgeny Grin)
* @author Christian Grothoff
*
* Provides basic abstraction for locks/mutex.
* Any functions can be implemented as macro on some platforms
* unless explicitly marked otherwise.
* Any function argument can be skipped in macro, so avoid
* variable modification in function parameters.
*
* @warning Unlike pthread functions, most of functions return
* nonzero on success.
*/
#ifndef MHD_LOCKS_H
#define MHD_LOCKS_H 1
#include "mhd_options.h"
#ifdef MHD_USE_THREADS
#if defined(MHD_USE_W32_THREADS)
# define MHD_W32_MUTEX_ 1
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN 1
# endif /* !WIN32_LEAN_AND_MEAN */
# include <windows.h>
#elif defined(HAVE_PTHREAD_H) && defined(MHD_USE_POSIX_THREADS)
# define MHD_PTHREAD_MUTEX_ 1
# undef HAVE_CONFIG_H
# include <pthread.h>
# define HAVE_CONFIG_H 1
#else
# error No base mutex API is available.
#endif
#ifndef MHD_PANIC
# include <stdio.h>
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif /* HAVE_STDLIB_H */
/* Simple implementation of MHD_PANIC, to be used outside lib */
# define MHD_PANIC(msg) \
do { fprintf (stderr, \
"Abnormal termination at %d line in file %s: %s\n", \
(int) __LINE__, __FILE__, msg); abort (); \
} while (0)
#endif /* ! MHD_PANIC */
#if defined(MHD_PTHREAD_MUTEX_)
typedef pthread_mutex_t MHD_mutex_;
#elif defined(MHD_W32_MUTEX_)
typedef CRITICAL_SECTION MHD_mutex_;
#endif
#if defined(MHD_PTHREAD_MUTEX_)
/**
* Initialise new mutex.
* @param pmutex pointer to the mutex
* @return nonzero on success, zero otherwise
*/
#define MHD_mutex_init_(pmutex) (! (pthread_mutex_init ((pmutex), NULL)))
#elif defined(MHD_W32_MUTEX_)
/**
* Initialise new mutex.
* @param pmutex pointer to mutex
* @return nonzero on success, zero otherwise
*/
#define MHD_mutex_init_(pmutex) \
(InitializeCriticalSectionAndSpinCount ((pmutex),16))
#endif
#if defined(MHD_PTHREAD_MUTEX_)
# if defined(PTHREAD_MUTEX_INITIALIZER)
/**
* Define static mutex and statically initialise it.
*/
# define MHD_MUTEX_STATIC_DEFN_INIT_(m) \
static MHD_mutex_ m = PTHREAD_MUTEX_INITIALIZER
# endif /* PTHREAD_MUTEX_INITIALIZER */
#endif
#if defined(MHD_PTHREAD_MUTEX_)
/**
* Destroy previously initialised mutex.
* @param pmutex pointer to mutex
* @return nonzero on success, zero otherwise
*/
#define MHD_mutex_destroy_(pmutex) (! (pthread_mutex_destroy ((pmutex))))
#elif defined(MHD_W32_MUTEX_)
/**
* Destroy previously initialised mutex.
* @param pmutex pointer to mutex
* @return Always nonzero
*/
#define MHD_mutex_destroy_(pmutex) (DeleteCriticalSection ((pmutex)), ! 0)
#endif
/**
* Destroy previously initialised mutex and abort execution
* if error is detected.
* @param pmutex pointer to mutex
*/
#define MHD_mutex_destroy_chk_(pmutex) do { \
if (! MHD_mutex_destroy_ (pmutex)) \
MHD_PANIC (_ ("Failed to destroy mutex.\n")); \
} while (0)
#if defined(MHD_PTHREAD_MUTEX_)
/**
* Acquire lock on previously initialised mutex.
* If mutex was already locked by other thread, function
* blocks until mutex becomes available.
* @param pmutex pointer to mutex
* @return nonzero on success, zero otherwise
*/
#define MHD_mutex_lock_(pmutex) (! (pthread_mutex_lock ((pmutex))))
#elif defined(MHD_W32_MUTEX_)
/**
* Acquire lock on previously initialised mutex.
* If mutex was already locked by other thread, function
* blocks until mutex becomes available.
* @param pmutex pointer to mutex
* @return Always nonzero
*/
#define MHD_mutex_lock_(pmutex) (EnterCriticalSection ((pmutex)), ! 0)
#endif
/**
* Acquire lock on previously initialised mutex.
* If mutex was already locked by other thread, function
* blocks until mutex becomes available.
* If error is detected, execution will be aborted.
* @param pmutex pointer to mutex
*/
#define MHD_mutex_lock_chk_(pmutex) do { \
if (! MHD_mutex_lock_ (pmutex)) \
MHD_PANIC (_ ("Failed to lock mutex.\n")); \
} while (0)
#if defined(MHD_PTHREAD_MUTEX_)
/**
* Unlock previously initialised and locked mutex.
* @param pmutex pointer to mutex
* @return nonzero on success, zero otherwise
*/
#define MHD_mutex_unlock_(pmutex) (! (pthread_mutex_unlock ((pmutex))))
#elif defined(MHD_W32_MUTEX_)
/**
* Unlock previously initialised and locked mutex.
* @param pmutex pointer to mutex
* @return Always nonzero
*/
#define MHD_mutex_unlock_(pmutex) (LeaveCriticalSection ((pmutex)), ! 0)
#endif
/**
* Unlock previously initialised and locked mutex.
* If error is detected, execution will be aborted.
* @param pmutex pointer to mutex
*/
#define MHD_mutex_unlock_chk_(pmutex) do { \
if (! MHD_mutex_unlock_ (pmutex)) \
MHD_PANIC (_ ("Failed to unlock mutex.\n")); \
} while (0)
#else /* ! MHD_USE_THREADS */
#define MHD_mutex_init_(ignore) (! 0)
#define MHD_mutex_destroy_(ignore) (! 0)
#define MHD_mutex_destroy_chk_(ignore) (void)0
#define MHD_mutex_lock_(ignore) (! 0)
#define MHD_mutex_lock_chk_(ignore) (void)0
#define MHD_mutex_unlock_(ignore) (! 0)
#define MHD_mutex_unlock_chk_(ignore) (void)0
#endif /* ! MHD_USE_THREADS */
#endif /* ! MHD_LOCKS_H */