And split all the thread stuff into their own file. Almost done with all this test library cleanup!
This commit is contained in:
parent
89e882c4a8
commit
57abc83fe3
|
@ -2,6 +2,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "test.h"
|
||||
#include "thread.h"
|
||||
|
||||
// TODO fix up the formatting of testing.c so we can use newlines on the got/want stuff
|
||||
|
||||
|
@ -137,12 +138,13 @@ static void queueThread(void *data)
|
|||
|
||||
testingTest(QueueMain_DifferentThread)
|
||||
{
|
||||
testingThread *thread;
|
||||
threadThread *thread;
|
||||
int flag = 0;
|
||||
|
||||
thread = testingNewThread(queueThread, &flag);
|
||||
// TODO check errors
|
||||
threadNewThread(queueThread, &flag, &thread);
|
||||
timeout_uiMain(t, 5 * timerSecond);
|
||||
testingThreadWaitAndFree(thread);
|
||||
threadThreadWaitAndFree(thread);
|
||||
if (flag != 1)
|
||||
testingTErrorf(t, "uiQueueMain() didn't set flag properly: got %d, want 1", flag);
|
||||
}
|
||||
|
@ -158,12 +160,13 @@ static void queueOrderThread(void *data)
|
|||
|
||||
testingTest(QueueMain_DifferentThreadSequence)
|
||||
{
|
||||
testingThread *thread;
|
||||
threadThread *thread;
|
||||
uint32_t flag = 1; // make sure it's initialized just in case
|
||||
|
||||
thread = testingNewThread(queueOrderThread, &flag);
|
||||
// TODO check errors
|
||||
threadNewThread(queueOrderThread, &flag, &thread);
|
||||
timeout_uiMain(t, 5 * timerSecond);
|
||||
testingThreadWaitAndFree(thread);
|
||||
threadThreadWaitAndFree(thread);
|
||||
checkOrder(t, flag);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,12 @@ libui_test_sources = [
|
|||
|
||||
if libui_OS == 'windows'
|
||||
libui_test_sources += [
|
||||
'testing_windows.c',
|
||||
'thread_windows.c',
|
||||
'timer_windows.c',
|
||||
]
|
||||
else
|
||||
libui_test_sources += [
|
||||
'testing_darwinunix.c',
|
||||
'thread_darwinunix.c',
|
||||
'timer_darwinunix.c'
|
||||
]
|
||||
endif
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <string.h>
|
||||
#include "timer.h"
|
||||
#include "testing.h"
|
||||
#include "testingpriv.h"
|
||||
|
||||
void testingprivInternalError(const char *fmt, ...)
|
||||
{
|
||||
|
@ -30,6 +29,9 @@ void *testingprivMalloc(size_t n, const char *what)
|
|||
return x;
|
||||
}
|
||||
|
||||
#define testingprivNew(T) ((T *) testingprivMalloc(sizeof (T), #T))
|
||||
#define testingprivNewArray(T, n) ((T *) testingprivMalloc(n * sizeof (T), #T "[" #n "]"))
|
||||
|
||||
void *testingprivRealloc(void *x, size_t n, const char *what)
|
||||
{
|
||||
void *y;
|
||||
|
@ -40,6 +42,8 @@ void *testingprivRealloc(void *x, size_t n, const char *what)
|
|||
return y;
|
||||
}
|
||||
|
||||
#define testingprivResizeArray(x, T, n) ((T *) testingprivRealloc(x, n * sizeof (T), #T "[" #n "]"))
|
||||
|
||||
void testingprivFree(void *x)
|
||||
{
|
||||
free(x);
|
||||
|
|
|
@ -64,11 +64,6 @@ extern void testingTFailNow(testingT *t);
|
|||
extern void testingTSkipNow(testingT *t);
|
||||
extern void testingTDefer(testingT *t, void (*f)(testingT *t, void *data), void *data);
|
||||
|
||||
// TODO I don't like this threading model, but let's use it for now so I can continue working
|
||||
typedef struct testingThread testingThread;
|
||||
extern testingThread *testingNewThread(void (*f)(void *data), void *data);
|
||||
extern void testingThreadWaitAndFree(testingThread *t);
|
||||
|
||||
extern void testingprivRegisterTest(const char *, void (*)(testingT *), const char *, long);
|
||||
extern void testingprivRegisterTestBefore(const char *, void (*)(testingT *), const char *, long);
|
||||
extern void testingprivRegisterTestAfter(const char *, void (*)(testingT *), const char *, long);
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
// 28 april 2019
|
||||
// TODO pin down minimum POSIX versions (depends on what macOS 10.8 conforms to and what GLib/GTK+ require)
|
||||
// TODO feature test macros for things like monotonic clocks?
|
||||
// TODO is this needed in this file specifically, or just in testing_unix.c?
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include "testing.h"
|
||||
#include "testingpriv.h"
|
||||
|
||||
// TODO don't start the timer on any platform until after we call setjmp(); also decide whether to start the timer before or after resuming the thread on Windows
|
||||
|
||||
struct testingThread {
|
||||
pthread_t thread;
|
||||
void (*f)(void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static void *threadThreadProc(void *data)
|
||||
{
|
||||
testingThread *t = (testingThread *) data;
|
||||
|
||||
(*(t->f))(t->data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
testingThread *testingNewThread(void (*f)(void *data), void *data)
|
||||
{
|
||||
testingThread *t;
|
||||
int err;
|
||||
|
||||
t = testingprivNew(testingThread);
|
||||
t->f = f;
|
||||
t->data = data;
|
||||
|
||||
err = pthread_create(&(t->thread), NULL, threadThreadProc, t);
|
||||
if (err != 0)
|
||||
testingprivInternalError("error creating thread: %s (%d)", strerror(err), err);
|
||||
return t;
|
||||
}
|
||||
|
||||
void testingThreadWaitAndFree(testingThread *t)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_join(t->thread, NULL);
|
||||
if (err != 0)
|
||||
testingprivInternalError("error waiting for thread to finish: %s (%d)", strerror(err), err);
|
||||
// TODO do we need to free t->thread somehow?
|
||||
testingprivFree(t);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// 29 april 2019
|
||||
|
||||
extern void testingprivInternalError(const char *fmt, ...);
|
||||
extern void *testingprivMalloc(size_t n, const char *what);
|
||||
#define testingprivNew(T) ((T *) testingprivMalloc(sizeof (T), #T))
|
||||
#define testingprivNewArray(T, n) ((T *) testingprivMalloc(n * sizeof (T), #T "[" #n "]"))
|
||||
extern void *testingprivRealloc(void *x, size_t n, const char *what);
|
||||
#define testingprivResizeArray(x, T, n) ((T *) testingprivRealloc(x, n * sizeof (T), #T "[" #n "]"))
|
||||
extern void testingprivFree(void *x);
|
|
@ -0,0 +1,20 @@
|
|||
// 4 may 2019
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// I don't like this threading model, but let's use it for now so I can continue working
|
||||
|
||||
typedef struct threadThread threadThread;
|
||||
|
||||
typedef uint64_t threadSysError;
|
||||
#ifdef _WIN32
|
||||
#define threadSysErrorFmt "0x%08I32X"
|
||||
#define threadSysErrorFmtArg(x) ((uint32_t) x)
|
||||
#else
|
||||
#include <string.h>
|
||||
#define threadSysErrorFmt "%s (%d)"
|
||||
#define threadSysErrorFmtArg(x) strerror((int) x), ((int) x)
|
||||
#endif
|
||||
|
||||
extern threadSysError threadNewThread(void (*f)(void *data), void *data, threadThread **t);
|
||||
extern threadSysError threadThreadWaitAndFree(threadThread *t);
|
|
@ -0,0 +1,61 @@
|
|||
// 28 april 2019
|
||||
// TODO pin down minimum POSIX versions (depends on what macOS 10.8 conforms to and what GLib/GTK+ require)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include "thread.h"
|
||||
|
||||
struct threadThread {
|
||||
pthread_t thread;
|
||||
void (*f)(void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static void *threadThreadProc(void *data)
|
||||
{
|
||||
threadThread *t = (threadThread *) data;
|
||||
|
||||
(*(t->f))(t->data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
threadSysError threadNewThread(void (*f)(void *data), void *data, threadThread **t)
|
||||
{
|
||||
threadThread *tout;
|
||||
int err;
|
||||
|
||||
*t = NULL;
|
||||
|
||||
errno = 0;
|
||||
tout = (threadThread *) malloc(sizeof (threadThread));
|
||||
if (tout == NULL) {
|
||||
err = errno;
|
||||
if (err == 0)
|
||||
err = ENOMEM;
|
||||
return (threadSysError) err;
|
||||
}
|
||||
tout->f = f;
|
||||
tout->data = data;
|
||||
|
||||
err = pthread_create(&(tout->thread), NULL, threadThreadProc, tout);
|
||||
if (err != 0) {
|
||||
free(tout);
|
||||
return (threadSysError) err;
|
||||
}
|
||||
|
||||
*t = tout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
threadSysError threadThreadWaitAndFree(threadThread *t)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_join(t->thread, NULL);
|
||||
if (err != 0)
|
||||
return (threadSysError) err;
|
||||
// TODO do we have to release t->thread somehow?
|
||||
free(t);
|
||||
return 0;
|
||||
}
|
|
@ -10,13 +10,8 @@
|
|||
#define NTDDI_VERSION 0x06000000
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "timer.h"
|
||||
#include "testing.h"
|
||||
#include "testingpriv.h"
|
||||
#include "thread.h"
|
||||
|
||||
static HRESULT lastErrorCodeToHRESULT(DWORD lastError)
|
||||
{
|
||||
|
@ -55,7 +50,7 @@ static HRESULT WINAPI hrWaitForSingleObject(HANDLE handle, DWORD timeout)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
struct testingThread {
|
||||
struct threadThread {
|
||||
uintptr_t handle;
|
||||
void (*f)(void *data);
|
||||
void *data;
|
||||
|
@ -63,34 +58,43 @@ struct testingThread {
|
|||
|
||||
static unsigned __stdcall threadThreadProc(void *data)
|
||||
{
|
||||
testingThread *t = (testingThread *) data;
|
||||
threadThread *t = (threadThread *) data;
|
||||
|
||||
(*(t->f))(t->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
testingThread *testingNewThread(void (*f)(void *data), void *data)
|
||||
threadSysError threadNewThread(void (*f)(void *data), void *data, threadThread **t)
|
||||
{
|
||||
testingThread *t;
|
||||
threadThread *tout;
|
||||
HRESULT hr;
|
||||
|
||||
t = testingprivNew(testingThread);
|
||||
t->f = f;
|
||||
t->data = data;
|
||||
*t = NULL;
|
||||
|
||||
hr = hr_beginthreadex(NULL, 0, threadThreadProc, t, 0, NULL, &(t->handle));
|
||||
if (hr != S_OK)
|
||||
testingprivInternalError("error creating thread: 0x%08I32X", hr);
|
||||
return t;
|
||||
tout = (threadThread *) malloc(sizeof (threadThread));
|
||||
if (tout == NULL)
|
||||
return (threadSysError) E_OUTOFMEMORY;
|
||||
tout->f = f;
|
||||
tout->data = data;
|
||||
|
||||
hr = hr_beginthreadex(NULL, 0, threadThreadProc, tout, 0, NULL, &(tout->handle));
|
||||
if (hr != S_OK) {
|
||||
free(tout);
|
||||
return (threadSysError) hr;
|
||||
}
|
||||
|
||||
*t = tout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void testingThreadWaitAndFree(testingThread *t)
|
||||
threadSysError threadThreadWaitAndFree(threadThread *t)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = hrWaitForSingleObject((HANDLE) (t->handle), INFINITE);
|
||||
if (hr != S_OK)
|
||||
testingprivInternalError("error waiting for thread to finish: 0x%08I32X", hr);
|
||||
return (threadSysError) hr;
|
||||
CloseHandle((HANDLE) (t->handle));
|
||||
testingprivFree(t);
|
||||
free(t);
|
||||
return 0;
|
||||
}
|
|
@ -206,6 +206,10 @@ struct timeoutParams {
|
|||
HRESULT hr;
|
||||
};
|
||||
|
||||
static DWORD timeoutParamsSlot;
|
||||
static HRESULT timeoutParamsHRESULT = S_OK;
|
||||
static INIT_ONCE timeoutParamsOnce = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
static void onTimeout(void)
|
||||
{
|
||||
struct timeoutParams *p;
|
||||
|
@ -214,10 +218,6 @@ static void onTimeout(void)
|
|||
longjmp(p->retpos, 1);
|
||||
}
|
||||
|
||||
static DWORD timeoutParamsSlot;
|
||||
static HRESULT timeoutParamsHRESULT = S_OK;
|
||||
static INIT_ONCE timeoutParamsOnce = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
static BOOL CALLBACK timeoutParamsSlotInit(PINIT_ONCE once, PVOID param, PVOID *ctx)
|
||||
{
|
||||
SetLastError(0);
|
||||
|
|
Loading…
Reference in New Issue