mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-23 04:32:44 +00:00
Use native Win32 API instead of glib on Windows
- Don't look for PkgConfig on Win32. - Don't force glib and gthread on Win32. - Support finding libsndfile with vcpkg. - Add enable-static-msvcrt option to use the static VC runtime library. - Add stubs that define glib functions to Win32 equivalents.
This commit is contained in:
parent
85fcbde9e0
commit
32f4347d26
9 changed files with 466 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
build/
|
||||
.vs/
|
||||
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
|
|
|
@ -68,6 +68,9 @@ option ( enable-portaudio "compile PortAudio support" off )
|
|||
option ( enable-profiling "profile the dsp code" off )
|
||||
option ( enable-trap-on-fpe "enable SIGFPE trap on Floating Point Exceptions" off )
|
||||
option ( enable-ubsan "compile and link against UBSan (for debugging fluidsynth internals)" off )
|
||||
if ( MSVC )
|
||||
option ( enable-static-mscrt "use static MS Visual C++ runtime" off )
|
||||
endif ( MSVC )
|
||||
|
||||
# Options enabled by default
|
||||
option ( enable-aufile "compile support for sound file output" on )
|
||||
|
@ -319,6 +322,10 @@ if ( WIN32 )
|
|||
set ( CMAKE_DEBUG_POSTFIX "_debug" )
|
||||
endif ( NOT MSVC )
|
||||
|
||||
if ( enable-static-msvcrt )
|
||||
set ( CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" )
|
||||
endif ( enable-static-msvcrt )
|
||||
|
||||
# MinGW compiler (a Windows GCC port)
|
||||
if ( MINGW )
|
||||
set ( MINGW32 1 )
|
||||
|
@ -475,6 +482,7 @@ if ( ASTYLE )
|
|||
)
|
||||
endif(ASTYLE)
|
||||
|
||||
if ( NOT WIN32 )
|
||||
find_package ( PkgConfig REQUIRED )
|
||||
|
||||
# Mandatory libraries: glib and gthread
|
||||
|
@ -484,15 +492,42 @@ list( APPEND PC_REQUIRES_PRIV "glib-2.0" "gthread-2.0")
|
|||
if ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" )
|
||||
message ( WARNING "Your version of glib is very old. This may cause problems with fluidsynth's sample cache on Windows. Consider updating to glib 2.26 or newer!" )
|
||||
endif ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" )
|
||||
set ( WIN32_GLIBSTUBS OFF )
|
||||
set ( WITH_GLIB_STUBS 0 )
|
||||
else ( NOT WIN32 )
|
||||
set ( WIN32_GLIBSTUBS ON )
|
||||
set ( WITH_GLIB_STUBS 1 )
|
||||
endif ( NOT WIN32 )
|
||||
|
||||
include ( PkgConfigHelpers ) # has unset_pkg_config()
|
||||
|
||||
if ( NOT PkgConfig_FOUND )
|
||||
set ( enable-pulseaudio OFF )
|
||||
set ( enable-alsa OFF )
|
||||
set ( enable-portaudio OFF )
|
||||
set ( enable-jack OFF )
|
||||
set ( enable-pipewire OFF )
|
||||
set ( enable-lash OFF )
|
||||
set ( enable-systemd OFF )
|
||||
set ( enable-dbus OFF )
|
||||
set ( enable-ladspa OFF )
|
||||
set ( enable-libinstpatch OFF )
|
||||
set ( enable-sdl2 OFF )
|
||||
set ( enable-oboe OFF )
|
||||
set ( enable-readline OFF )
|
||||
endif ( NOT PkgConfig_FOUND )
|
||||
|
||||
# Optional features
|
||||
unset ( LIBSNDFILE_SUPPORT CACHE )
|
||||
unset ( LIBSNDFILE_HASVORBIS CACHE )
|
||||
if ( enable-libsndfile )
|
||||
if ( PkgConfig_FOUND )
|
||||
pkg_check_modules ( LIBSNDFILE sndfile>=1.0.0 IMPORTED_TARGET )
|
||||
set ( LIBSNDFILE_SUPPORT ${LIBSNDFILE_FOUND} )
|
||||
else ( PkgConfig_FOUND )
|
||||
find_package(SndFile CONFIG)
|
||||
set ( LIBSNDFILE_SUPPORT ${SNDFILE_FOUND} )
|
||||
endif ( PkgConfig_FOUND)
|
||||
if ( LIBSNDFILE_SUPPORT )
|
||||
#[[ cmake_print_variables (
|
||||
LIBSNDFILE_STATIC_LIBRARIES
|
||||
|
@ -501,6 +536,7 @@ if ( LIBSNDFILE_SUPPORT )
|
|||
LIBSNDFILE_STATIC_LDFLAGS_OTHER ) ]]
|
||||
list( APPEND PC_REQUIRES_PRIV "sndfile")
|
||||
if ( LIBSNDFILE_STATIC_LIBRARIES MATCHES "vorbis" OR
|
||||
SndFile_WITH_EXTERNAL_LIBS OR
|
||||
LIBSNDFILE_STATIC_LDFLAGS MATCHES "vorbis" OR
|
||||
LIBSNDFILE_STATIC_LDFLAGS_OTHER MATCHES "vorbis" )
|
||||
set ( LIBSNDFILE_HASVORBIS 1 )
|
||||
|
@ -835,9 +871,11 @@ else ()
|
|||
set ( includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}" )
|
||||
endif ()
|
||||
|
||||
if ( PkgConfig_FOUND )
|
||||
generate_pkgconfig_spec(fluidsynth.pc.in ${FluidSynth_BINARY_DIR}/fluidsynth.pc libfluidsynth-OBJ)
|
||||
install ( FILES ${FluidSynth_BINARY_DIR}/fluidsynth.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig )
|
||||
endif(PkgConfig_FOUND)
|
||||
|
||||
# Exported targets for cmake: find_package(FluidSynth)
|
||||
# when installed, use CMAKE_PREFIX_PATH=fluidsynth-prefix;...
|
||||
|
|
|
@ -246,6 +246,14 @@ else ( ENABLE_COVERAGE )
|
|||
set ( DEVEL_REPORT "${DEVEL_REPORT} Coverage: no\n" )
|
||||
endif ( ENABLE_COVERAGE )
|
||||
|
||||
if ( MSVC )
|
||||
if ( enable-static-msvcrt )
|
||||
set ( DEVEL_REPORT "${DEVEL_REPORT} Static MSVC Runtime: yes\n" )
|
||||
else ( enable-static-msvcrt )
|
||||
set ( DEVEL_REPORT "${DEVEL_REPORT} Static MSVC Runtime: no\n" )
|
||||
endif ( enable-static-msvcrt )
|
||||
endif ( MSVC )
|
||||
|
||||
message( STATUS
|
||||
"\n**************************************************************\n"
|
||||
"Build Summary:\n"
|
||||
|
|
|
@ -182,6 +182,14 @@ set ( libfluidsynth_SOURCES
|
|||
bindings/fluid_ladspa.h
|
||||
)
|
||||
|
||||
if ( WIN32_GLIBSTUBS )
|
||||
set( libfluidsynth_SOURCES
|
||||
${libfluidsynth_SOURCES}
|
||||
utils/win32_glibstubs.c
|
||||
utils/win32_glibstubs.h
|
||||
)
|
||||
endif ( WIN32_GLIBSTUBS )
|
||||
|
||||
set ( public_HEADERS
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/audio.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/event.h
|
||||
|
@ -358,6 +366,11 @@ if ( TARGET PkgConfig::LIBSNDFILE AND LIBSNDFILE_SUPPORT )
|
|||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::LIBSNDFILE )
|
||||
endif()
|
||||
|
||||
if ( TARGET SndFile::sndfile AND LIBSNDFILE_SUPPORT )
|
||||
target_include_directories ( libfluidsynth-OBJ PRIVATE ${SndFile_INCLUDE_DIR} )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC SndFile::sndfile )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::PULSE AND PULSE_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::PULSE )
|
||||
endif()
|
||||
|
@ -440,6 +453,10 @@ target_link_libraries ( libfluidsynth PRIVATE libfluidsynth-OBJ )
|
|||
|
||||
set ( fluidsynth_SOURCES fluidsynth.c )
|
||||
|
||||
if ( WIN32_GLIBSTUBS )
|
||||
set ( fluidsynth_SOURCES ${fluidsynth_SOURCES} utils/win32_glibstubs.c )
|
||||
endif ( WIN32_GLIBSTUBS )
|
||||
|
||||
if ( WASAPI_SUPPORT )
|
||||
set ( fluidsynth_SOURCES ${fluidsynth_SOURCES} fluid_wasapi_device_enumerate.c )
|
||||
endif ( WASAPI_SUPPORT )
|
||||
|
|
|
@ -268,4 +268,7 @@
|
|||
/* Define to 1 if you have the socklen_t type. */
|
||||
#cmakedefine HAVE_SOCKLEN_T @HAVE_SOCKLEN_T@
|
||||
|
||||
/* Define if using glib stubs instead of real glib. */
|
||||
#cmakedefine WITH_GLIB_STUBS
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
|
|
|
@ -132,6 +132,9 @@ typedef gintptr intptr_t;
|
|||
#if defined(WIN32) && HAVE_WINDOWS_H
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h> /* Provides also socklen_t */
|
||||
#ifdef WITH_GLIB_STUBS
|
||||
#include "win32_glibstubs.h"
|
||||
#endif
|
||||
|
||||
/* WIN32 special defines */
|
||||
#define STDIN_FILENO 0
|
||||
|
@ -157,7 +160,9 @@ typedef gintptr intptr_t;
|
|||
#include <gmodule.h>
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#include <glib/gstdio.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Macro used for safely accessing a message from a GError and using a default
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef WITH_GLIB_STUBS
|
||||
#include <glib.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h> // malloc, free
|
||||
|
@ -73,8 +75,13 @@ typedef double fluid_real_t;
|
|||
|
||||
|
||||
/** Atomic types */
|
||||
#if defined(WIN32) && defined(WITH_GLIB_STUBS)
|
||||
typedef long fluid_atomic_int_t;
|
||||
typedef unsigned long fluid_atomic_uint_t;
|
||||
#else
|
||||
typedef int fluid_atomic_int_t;
|
||||
typedef unsigned int fluid_atomic_uint_t;
|
||||
#endif
|
||||
typedef float fluid_atomic_float_t;
|
||||
|
||||
|
||||
|
|
250
src/utils/win32_glibstubs.c
Normal file
250
src/utils/win32_glibstubs.c
Normal file
|
@ -0,0 +1,250 @@
|
|||
#ifdef WIN32
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_sys.h"
|
||||
#include "win32_glibstubs.h"
|
||||
|
||||
#include <process.h>
|
||||
|
||||
static wchar_t *utf8_to_wc(const char *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
wchar_t *wstr = NULL;
|
||||
int length;
|
||||
|
||||
if ((length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, NULL, 0)) == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
wstr = malloc(length * sizeof(wchar_t));
|
||||
if (wstr == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, wstr, length);
|
||||
return wstr;
|
||||
}
|
||||
|
||||
BOOL fluid_g_file_test(const char *pathA, int flags)
|
||||
{
|
||||
wchar_t *path = utf8_to_wc(pathA);
|
||||
if (path == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
DWORD attributes = GetFileAttributesW(path);
|
||||
FLUID_FREE(path);
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (flags & G_FILE_TEST_EXISTS)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (flags & G_FILE_TEST_IS_REGULAR)
|
||||
{
|
||||
return (attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ParseCommandLine - Taken from ZDoom
|
||||
//
|
||||
// Parse a command line (passed in args). If argc is non-NULL, it will
|
||||
// be set to the number of arguments. If argv is non-NULL, it will be
|
||||
// filled with pointers to each argument; argv[0] should be initialized
|
||||
// to point to a buffer large enough to hold all the arguments. The
|
||||
// return value is the necessary size of this buffer.
|
||||
//
|
||||
// Special processing:
|
||||
// Inside quoted strings, \" becomes just "
|
||||
// \\ becomes just a single backslash
|
||||
|
||||
static long ParseCommandLine(const char *args, int *argc, char **argv)
|
||||
{
|
||||
int count;
|
||||
char *buffer;
|
||||
long buffplace;
|
||||
|
||||
count = 0;
|
||||
buffplace = 0;
|
||||
buffer = argv != NULL ? argv[0] : NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (*args <= ' ' && *args)
|
||||
{ // skip white space
|
||||
args++;
|
||||
}
|
||||
if (*args == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (*args == '\"')
|
||||
{ // read quoted string
|
||||
char stuff;
|
||||
if (argv != NULL)
|
||||
{
|
||||
argv[count] = buffer + buffplace;
|
||||
}
|
||||
count++;
|
||||
args++;
|
||||
do
|
||||
{
|
||||
stuff = *args++;
|
||||
if (stuff == '\\' && *args == '\"')
|
||||
{
|
||||
stuff = '\"';
|
||||
args++;
|
||||
}
|
||||
else if (stuff == '\\' && *args == '\\')
|
||||
{
|
||||
args++;
|
||||
}
|
||||
else if (stuff == '\"')
|
||||
{
|
||||
stuff = 0;
|
||||
}
|
||||
else if (stuff == 0)
|
||||
{
|
||||
args--;
|
||||
}
|
||||
if (argv != NULL)
|
||||
{
|
||||
buffer[buffplace] = stuff;
|
||||
}
|
||||
buffplace++;
|
||||
} while (stuff);
|
||||
}
|
||||
else
|
||||
{ // read unquoted string
|
||||
const char *start = args++, *end;
|
||||
|
||||
while (*args && *args > ' ' && *args != '\"')
|
||||
{
|
||||
args++;
|
||||
}
|
||||
end = args;
|
||||
if (argv != NULL)
|
||||
{
|
||||
argv[count] = buffer + buffplace;
|
||||
while (start < end)
|
||||
{
|
||||
buffer[buffplace++] = *start++;
|
||||
}
|
||||
buffer[buffplace++] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffplace += end - start + 1;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (argc != NULL)
|
||||
{
|
||||
*argc = count;
|
||||
}
|
||||
return buffplace;
|
||||
}
|
||||
|
||||
BOOL fluid_g_shell_parse_argv(const char *command_line, int *argcp, char ***argvp, void *_)
|
||||
{
|
||||
long argsize = ParseCommandLine(command_line, argcp, NULL);
|
||||
*argvp = NULL;
|
||||
if (*argcp != 0)
|
||||
{
|
||||
*argvp = (char **)malloc(*argcp * sizeof(char *) + argsize);
|
||||
if (!*argvp)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
**argvp = (char *)*argvp + *argcp * sizeof(char *);
|
||||
ParseCommandLine(command_line, NULL, *argvp);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
double fluid_g_get_monotonic_time(void)
|
||||
{
|
||||
static LARGE_INTEGER freq_cache = { 0, 0 }; /* Performance Frequency */
|
||||
LARGE_INTEGER perf_cpt;
|
||||
|
||||
if (!freq_cache.QuadPart)
|
||||
{
|
||||
QueryPerformanceFrequency(&freq_cache); /* Frequency value */
|
||||
}
|
||||
|
||||
QueryPerformanceCounter(&perf_cpt); /* Counter value */
|
||||
return perf_cpt.QuadPart * 1000000.0 / freq_cache.QuadPart; /* time in micros */
|
||||
}
|
||||
|
||||
/* Thread support */
|
||||
static unsigned __stdcall g_thread_wrapper(void *info_)
|
||||
{
|
||||
GThread *info = (GThread *)info_;
|
||||
info->func(info->data);
|
||||
/* Free the "GThread" now if it was detached. Otherwise, it's freed in fluid_g_thread_join. */
|
||||
if (info->handle == NULL)
|
||||
{
|
||||
free(info);
|
||||
}
|
||||
_endthreadex(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GThread *fluid_g_thread_create(GThreadFunc func, void *data, BOOL joinable, GError **error)
|
||||
{
|
||||
static GError error_container;
|
||||
|
||||
g_return_val_if_fail(func != NULL, NULL);
|
||||
|
||||
GThread *info = (GThread *)malloc(sizeof(GThread));
|
||||
if (info == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->func = func;
|
||||
info->data = data;
|
||||
info->handle = (HANDLE)_beginthreadex(NULL, 0, g_thread_wrapper, info, 0, NULL);
|
||||
if (error != NULL)
|
||||
{
|
||||
error_container.code = errno;
|
||||
if (errno != 0)
|
||||
{
|
||||
error_container.message = strerror(errno);
|
||||
}
|
||||
*error = &error_container;
|
||||
}
|
||||
if (info->handle == 0)
|
||||
{
|
||||
free(info);
|
||||
info = NULL;
|
||||
}
|
||||
else if (!joinable)
|
||||
{
|
||||
/* Release thread reference, if caller doesn't want to join */
|
||||
CloseHandle(info->handle);
|
||||
info->handle = NULL;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void fluid_g_thread_join(GThread *thread)
|
||||
{
|
||||
if (thread != NULL && thread->handle != NULL)
|
||||
{
|
||||
WaitForSingleObject(thread->handle, INFINITE);
|
||||
CloseHandle(thread->handle);
|
||||
free(thread);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
137
src/utils/win32_glibstubs.h
Normal file
137
src/utils/win32_glibstubs.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
#ifndef _GLIBSTUBS_H
|
||||
#define _GLIBSTUBS_H
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Windows.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Miscellaneous stubs */
|
||||
#define GLIB_CHECK_VERSION(x, y, z) 0 /* Evaluate to 0 to get FluidSynth to use the "old" thread API */
|
||||
#define GLIB_MAJOR_VERSION 2
|
||||
#define GLIB_MINOR_VERSION 29
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int code;
|
||||
const char *message;
|
||||
} GError;
|
||||
typedef void *gpointer;
|
||||
|
||||
#define g_new(s, c) FLUID_ARRAY(s, c)
|
||||
#define g_free(p) FLUID_FREE(p)
|
||||
#define g_strfreev FLUID_FREE
|
||||
#define g_newa(_type, _len) (_type *)_alloca(sizeof(_type) * (_len))
|
||||
#define g_assert(a) assert(a)
|
||||
#define G_LIKELY(expr) (expr)
|
||||
#define G_UNLIKELY(expr) (expr)
|
||||
#endif
|
||||
|
||||
#define g_return_val_if_fail(expr, val) if (expr) {} else { return val; }
|
||||
#define g_clear_error(err) do {} while (0)
|
||||
|
||||
#define G_FILE_TEST_EXISTS 1
|
||||
#define G_FILE_TEST_IS_REGULAR 2
|
||||
|
||||
#define g_file_test fluid_g_file_test
|
||||
#define g_shell_parse_argv fluid_g_shell_parse_argv
|
||||
BOOL fluid_g_file_test(const char *path, int flags);
|
||||
BOOL fluid_g_shell_parse_argv(const char *command_line, int *argcp, char ***argvp, void *dummy);
|
||||
|
||||
#define g_get_monotonic_time fluid_g_get_monotonic_time
|
||||
double fluid_g_get_monotonic_time(void);
|
||||
|
||||
/* Byte ordering */
|
||||
#ifdef __BYTE_ORDER__
|
||||
#define G_BYTE_ORDER __BYTE_ORDER__
|
||||
#define G_BIG_ENDIAN __ORDER_BIG_ENDIAN__
|
||||
#else
|
||||
// If __BYTE_ORDER__ isn't defined, assume little endian
|
||||
#define G_BYTE_ORDER 1234
|
||||
#define G_BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
#define GINT16_FROM_LE(x) (int16_t)(((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8))
|
||||
#define GINT32_FROM_LE(x) (int32_t)((FLUID_LE16TOH(x) << 16) | (FLUID16_LE16TOH(x >> 16)))
|
||||
#else
|
||||
#define GINT32_FROM_LE(x) (x)
|
||||
#define GINT16_FROM_LE(x) (x)
|
||||
|
||||
/* Thread support */
|
||||
#define g_thread_supported() 1
|
||||
#define g_thread_init(_) do {} while (0)
|
||||
#define g_usleep(usecs) Sleep((usecs) / 1000)
|
||||
|
||||
typedef gpointer (*GThreadFunc)(void *data);
|
||||
typedef struct
|
||||
{
|
||||
GThreadFunc func;
|
||||
void *data;
|
||||
HANDLE handle;
|
||||
} GThread;
|
||||
|
||||
#define g_thread_create fluid_g_thread_create
|
||||
#define g_thread_join fluid_g_thread_join
|
||||
GThread *fluid_g_thread_create(GThreadFunc func, void *data, BOOL joinable, GError **error);
|
||||
void fluid_g_thread_join(GThread *thread);
|
||||
|
||||
/* Regular mutex */
|
||||
typedef SRWLOCK GStaticMutex;
|
||||
#define G_STATIC_MUTEX_INIT SRWLOCK_INIT
|
||||
#define g_static_mutex_init(_m) InitializeSRWLock(_m)
|
||||
#define g_static_mutex_free(_m) do {} while (0)
|
||||
#define g_static_mutex_lock(_m) AcquireSRWLockExclusive(_m)
|
||||
#define g_static_mutex_unlock(_m) ReleaseSRWLockExclusive(_m)
|
||||
|
||||
/* Recursive lock capable mutex */
|
||||
typedef CRITICAL_SECTION GStaticRecMutex;
|
||||
#define g_static_rec_mutex_init(_m) InitializeCriticalSection(_m)
|
||||
#define g_static_rec_mutex_free(_m) DeleteCriticalSection(_m)
|
||||
#define g_static_rec_mutex_lock(_m) EnterCriticalSection(_m)
|
||||
#define g_static_rec_mutex_unlock(_m) LeaveCriticalSection(_m)
|
||||
|
||||
/* Dynamically allocated mutex suitable for fluid_cond_t use */
|
||||
typedef SRWLOCK GMutex;
|
||||
#define g_mutex_free(m) do { if (m != NULL) g_free(m); } while(0)
|
||||
#define g_mutex_lock(m) AcquireSRWLockExclusive(m)
|
||||
#define g_mutex_unlock(m) ReleaseSRWLockExclusive(m)
|
||||
|
||||
static inline GMutex *g_mutex_new(void)
|
||||
{
|
||||
GMutex *mutex = g_new(GMutex, 1);
|
||||
InitializeSRWLock(mutex);
|
||||
return mutex;
|
||||
}
|
||||
|
||||
/* Thread condition signaling */
|
||||
typedef CONDITION_VARIABLE GCond;
|
||||
#define g_cond_free(cond) do { if (cond != NULL) g_free(cond); } while (0)
|
||||
#define g_cond_signal(cond) WakeConditionVariable(cond)
|
||||
#define g_cond_broadcast(cond) WakeAllConditionVariable(cond)
|
||||
#define g_cond_wait(cond, mutex) SleepConditionVariableSRW(cond, mutex, INFINITE, 0)
|
||||
|
||||
static inline GCond *g_cond_new(void)
|
||||
{
|
||||
GCond *cond = g_new(GCond, 1);
|
||||
InitializeConditionVariable(cond);
|
||||
return cond;
|
||||
}
|
||||
|
||||
/* Thread private data */
|
||||
typedef DWORD GStaticPrivate;
|
||||
#define g_static_private_init(_priv) do { *_priv = TlsAlloc(); } while (0)
|
||||
#define g_static_private_get(_priv) TlsGetValue(*_priv)
|
||||
#define g_static_private_set(_priv, _data, _) TlsSetValue(*_priv, _data)
|
||||
#define g_static_private_free(_priv) TlsFree(*_priv)
|
||||
|
||||
/* Atomic operations */
|
||||
#define g_atomic_int_inc(_pi) InterlockedIncrement(_pi)
|
||||
#define g_atomic_int_get(_pi) (MemoryBarrier(), *_pi)
|
||||
#define g_atomic_int_set(_pi, _val) do { MemoryBarrier(); *_pi = _val; } while (0)
|
||||
#define g_atomic_int_dec_and_test(_pi) (InterlockedDecrement(_pi) == 0)
|
||||
#define g_atomic_int_compare_and_exchange(_pi, _old, _new) (InterlockedCompareExchange(_pi, _new, _old) == _old)
|
||||
#define g_atomic_int_exchange_and_add(_pi, _add) InterlockedExchangeAdd(_pi, _add)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue