86 lines
1.8 KiB
C
86 lines
1.8 KiB
C
// 28 april 2019
|
|
// TODO pin down minimum POSIX versions (depends on what macOS 10.8 conforms to and what GLib/GTK+ require)
|
|
// TODO also pin down which of these I should be defining, because apparently FreeBSD only checks for _XOPEN_SOURCE (and 2004 POSIX says that defining this as 600 *implies* _POSIX_C_SOURCE being 200112L so only _XOPEN_SOURCE is needed...)
|
|
#define _POSIX_C_SOURCE 200112L
|
|
#define _XOPEN_SOURCE 600
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
#include <time.h>
|
|
#include "thread.h"
|
|
|
|
// Do not put any test cases in this file; they will not be run.
|
|
|
|
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;
|
|
}
|
|
|
|
threadSysError threadSleep(threadDuration d)
|
|
{
|
|
struct timespec duration, remaining;
|
|
int err;
|
|
|
|
duration.tv_sec = d / threadSecond;
|
|
duration.tv_nsec = d % threadSecond;
|
|
for (;;) {
|
|
errno = 0;
|
|
if (nanosleep(&duration, &remaining) == 0)
|
|
return 0;
|
|
err = errno;
|
|
if (err != EINTR)
|
|
return (threadSysError) err;
|
|
duration = remaining;
|
|
}
|
|
}
|