Replaced the Win32 threads with the proven to be better performing C++11 threads.
This commit is contained in:
@@ -34,7 +34,7 @@ endif()
|
|||||||
|
|
||||||
# WIN32 marks us as a GUI app on Windows
|
# WIN32 marks us as a GUI app on Windows
|
||||||
# MACOSX_BUNDLE prepares a macOS application bundle including with the app icon
|
# MACOSX_BUNDLE prepares a macOS application bundle including with the app icon
|
||||||
add_executable(86Box WIN32 MACOSX_BUNDLE 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c
|
add_executable(86Box WIN32 MACOSX_BUNDLE 86box.c config.c cpp11_thread.cpp log.c random.c timer.c io.c acpi.c apm.c
|
||||||
dma.c ddma.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c mca.c usb.c
|
dma.c ddma.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c mca.c usb.c
|
||||||
device.c nvr.c nvr_at.c nvr_ps2.c rtmidi_midi.cpp ${APP_ICON_MACOSX})
|
device.c nvr.c nvr_at.c nvr_ps2.c rtmidi_midi.cpp ${APP_ICON_MACOSX})
|
||||||
|
|
||||||
|
133
src/cpp11_thread.cpp
Normal file
133
src/cpp11_thread.cpp
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
#include <86box/plat.h>
|
||||||
|
|
||||||
|
struct event_cpp11_t
|
||||||
|
{
|
||||||
|
std::condition_variable cond;
|
||||||
|
std::mutex mutex;
|
||||||
|
bool state = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
thread_t *
|
||||||
|
thread_create(void (*thread_rout)(void *param), void *param)
|
||||||
|
{
|
||||||
|
auto thread = new std::thread([thread_rout, param] {
|
||||||
|
thread_rout(param);
|
||||||
|
});
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_t *
|
||||||
|
thread_create_mutex_with_spin_count(unsigned int spin_count)
|
||||||
|
{
|
||||||
|
/* Setting spin count of a mutex is not possible with pthreads. */
|
||||||
|
return thread_create_mutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
thread_wait(thread_t *arg, int timeout)
|
||||||
|
{
|
||||||
|
(void) timeout;
|
||||||
|
auto thread = reinterpret_cast<std::thread*>(arg);
|
||||||
|
thread->join();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_t *
|
||||||
|
thread_create_mutex(void)
|
||||||
|
{
|
||||||
|
auto mutex = new std::mutex;
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
thread_wait_mutex(mutex_t *_mutex)
|
||||||
|
{
|
||||||
|
if (_mutex == nullptr)
|
||||||
|
return(0);
|
||||||
|
auto mutex = reinterpret_cast<std::mutex*>(_mutex);
|
||||||
|
mutex->lock();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
thread_release_mutex(mutex_t *_mutex)
|
||||||
|
{
|
||||||
|
if (_mutex == nullptr)
|
||||||
|
return(0);
|
||||||
|
auto mutex = reinterpret_cast<std::mutex*>(_mutex);
|
||||||
|
mutex->unlock();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
thread_close_mutex(mutex_t *_mutex)
|
||||||
|
{
|
||||||
|
auto mutex = reinterpret_cast<std::mutex*>(_mutex);
|
||||||
|
delete mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_t *
|
||||||
|
thread_create_event()
|
||||||
|
{
|
||||||
|
auto ev = new event_cpp11_t;
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
thread_wait_event(event_t *handle, int timeout)
|
||||||
|
{
|
||||||
|
auto event = reinterpret_cast<event_cpp11_t*>(handle);
|
||||||
|
auto lock = std::unique_lock<std::mutex>(event->mutex);
|
||||||
|
|
||||||
|
if (timeout < 0) {
|
||||||
|
event->cond.wait(lock, [event] { return event->state; });
|
||||||
|
} else {
|
||||||
|
auto to = std::chrono::system_clock::now() + std::chrono::milliseconds(timeout);
|
||||||
|
std::cv_status status;
|
||||||
|
|
||||||
|
do {
|
||||||
|
status = event->cond.wait_until(lock, to);
|
||||||
|
} while ((status != std::cv_status::timeout) && !event->state);
|
||||||
|
|
||||||
|
if (status == std::cv_status::timeout) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
thread_set_event(event_t *handle)
|
||||||
|
{
|
||||||
|
auto event = reinterpret_cast<event_cpp11_t*>(handle);
|
||||||
|
{
|
||||||
|
auto lock = std::unique_lock<std::mutex>(event->mutex);
|
||||||
|
event->state = true;
|
||||||
|
}
|
||||||
|
event->cond.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
thread_reset_event(event_t *handle)
|
||||||
|
{
|
||||||
|
auto event = reinterpret_cast<event_cpp11_t*>(handle);
|
||||||
|
auto lock = std::unique_lock<std::mutex>(event->mutex);
|
||||||
|
event->state = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
thread_destroy_event(event_t *handle)
|
||||||
|
{
|
||||||
|
auto event = reinterpret_cast<event_cpp11_t*>(handle);
|
||||||
|
delete event;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
enable_language(RC)
|
enable_language(RC)
|
||||||
|
|
||||||
add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_thread.c
|
add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.c
|
||||||
win_keyboard.c win_crashdump.c win_mouse.c)
|
win_crashdump.c win_mouse.c)
|
||||||
|
|
||||||
add_library(ui OBJECT win_ui.c win_icon.c win_stbar.c win_sdl.c win_dialog.c win_about.c
|
add_library(ui OBJECT win_ui.c win_icon.c win_stbar.c win_sdl.c win_dialog.c win_about.c
|
||||||
win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c
|
win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c
|
||||||
|
@@ -464,7 +464,7 @@ CXXFLAGS := $(CFLAGS)
|
|||||||
#########################################################################
|
#########################################################################
|
||||||
# Create the (final) list of objects to build. #
|
# Create the (final) list of objects to build. #
|
||||||
#########################################################################
|
#########################################################################
|
||||||
MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
|
MAINOBJ := 86box.o config.o cpp11_thread.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
|
||||||
nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o \
|
nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o \
|
||||||
usb.o device.o nvr.o nvr_at.o nvr_ps2.o rtmidi_midi.o \
|
usb.o device.o nvr.o nvr_at.o nvr_ps2.o rtmidi_midi.o \
|
||||||
$(VNCOBJ)
|
$(VNCOBJ)
|
||||||
@@ -672,7 +672,7 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \
|
|||||||
vid_voodoo_texture.o
|
vid_voodoo_texture.o
|
||||||
|
|
||||||
PLATOBJ := win.o \
|
PLATOBJ := win.o \
|
||||||
win_dynld.o win_thread.o \
|
win_dynld.o \
|
||||||
win_cdrom.o win_keyboard.o \
|
win_cdrom.o win_keyboard.o \
|
||||||
win_crashdump.o \
|
win_crashdump.o \
|
||||||
win_mouse.o
|
win_mouse.o
|
||||||
|
@@ -1,183 +0,0 @@
|
|||||||
/*
|
|
||||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
||||||
* running old operating systems and software designed for IBM
|
|
||||||
* PC systems and compatibles from 1981 through fairly recent
|
|
||||||
* system designs based on the PCI bus.
|
|
||||||
*
|
|
||||||
* This file is part of the 86Box distribution.
|
|
||||||
*
|
|
||||||
* Implement threads and mutexes for the Win32 platform.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
|
||||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
|
||||||
*
|
|
||||||
* Copyright 2008-2018 Sarah Walker.
|
|
||||||
* Copyright 2017,2018 Fred N. van Kempen.
|
|
||||||
*/
|
|
||||||
#define UNICODE
|
|
||||||
#define BITMAP WINDOWS_BITMAP
|
|
||||||
#include <windows.h>
|
|
||||||
#include <windowsx.h>
|
|
||||||
#include <process.h>
|
|
||||||
#undef BITMAP
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <wchar.h>
|
|
||||||
#include <86box/86box.h>
|
|
||||||
#include <86box/plat.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
HANDLE handle;
|
|
||||||
} win_event_t;
|
|
||||||
|
|
||||||
|
|
||||||
thread_t *
|
|
||||||
thread_create(void (*func)(void *param), void *param)
|
|
||||||
{
|
|
||||||
uintptr_t bt = _beginthread(func, 0, param);
|
|
||||||
return((thread_t *)bt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
thread_wait(thread_t *arg, int timeout)
|
|
||||||
{
|
|
||||||
if (arg == NULL) return(0);
|
|
||||||
|
|
||||||
if (timeout == -1)
|
|
||||||
timeout = INFINITE;
|
|
||||||
|
|
||||||
if (WaitForSingleObject(arg, timeout)) return(1);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
event_t *
|
|
||||||
thread_create_event(void)
|
|
||||||
{
|
|
||||||
win_event_t *ev = malloc(sizeof(win_event_t));
|
|
||||||
|
|
||||||
ev->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
||||||
|
|
||||||
return((event_t *)ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
thread_set_event(event_t *arg)
|
|
||||||
{
|
|
||||||
win_event_t *ev = (win_event_t *)arg;
|
|
||||||
|
|
||||||
if (arg == NULL) return;
|
|
||||||
|
|
||||||
SetEvent(ev->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
thread_reset_event(event_t *arg)
|
|
||||||
{
|
|
||||||
win_event_t *ev = (win_event_t *)arg;
|
|
||||||
|
|
||||||
if (arg == NULL) return;
|
|
||||||
|
|
||||||
ResetEvent(ev->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
thread_wait_event(event_t *arg, int timeout)
|
|
||||||
{
|
|
||||||
win_event_t *ev = (win_event_t *)arg;
|
|
||||||
|
|
||||||
if (arg == NULL) return(0);
|
|
||||||
|
|
||||||
if (ev->handle == NULL) return(0);
|
|
||||||
|
|
||||||
if (timeout == -1)
|
|
||||||
timeout = INFINITE;
|
|
||||||
|
|
||||||
if (WaitForSingleObject(ev->handle, timeout)) return(1);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
thread_destroy_event(event_t *arg)
|
|
||||||
{
|
|
||||||
win_event_t *ev = (win_event_t *)arg;
|
|
||||||
|
|
||||||
if (arg == NULL) return;
|
|
||||||
|
|
||||||
CloseHandle(ev->handle);
|
|
||||||
|
|
||||||
free(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mutex_t *
|
|
||||||
thread_create_mutex(void)
|
|
||||||
{
|
|
||||||
mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION));
|
|
||||||
|
|
||||||
InitializeCriticalSection(mutex);
|
|
||||||
|
|
||||||
return mutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mutex_t *
|
|
||||||
thread_create_mutex_with_spin_count(unsigned int spin_count)
|
|
||||||
{
|
|
||||||
mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION));
|
|
||||||
|
|
||||||
InitializeCriticalSectionAndSpinCount(mutex, spin_count);
|
|
||||||
|
|
||||||
return mutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
thread_wait_mutex(mutex_t *mutex)
|
|
||||||
{
|
|
||||||
if (mutex == NULL) return(0);
|
|
||||||
|
|
||||||
LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex;
|
|
||||||
|
|
||||||
EnterCriticalSection(critsec);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
thread_release_mutex(mutex_t *mutex)
|
|
||||||
{
|
|
||||||
if (mutex == NULL) return(0);
|
|
||||||
|
|
||||||
LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex;
|
|
||||||
|
|
||||||
LeaveCriticalSection(critsec);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
thread_close_mutex(mutex_t *mutex)
|
|
||||||
{
|
|
||||||
if (mutex == NULL) return;
|
|
||||||
|
|
||||||
LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex;
|
|
||||||
|
|
||||||
DeleteCriticalSection(critsec);
|
|
||||||
|
|
||||||
free(critsec);
|
|
||||||
}
|
|
Reference in New Issue
Block a user