Skip to content

Commit

Permalink
feat(thread): add pd_once
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldziuba03 committed Oct 24, 2024
1 parent ad1c2fc commit 3e02442
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 15 deletions.
9 changes: 9 additions & 0 deletions include/pandio/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ typedef HMODULE pd_dlib_t;
typedef CRITICAL_SECTION pd_mutex_t;
typedef CONDITION_VARIABLE pd_cond_t;
typedef HANDLE pd_thread_t;
typedef INIT_ONCE pd_once_t;
typedef DWORD pd_errno_t; // system error type
typedef DWORD pd_pid_t;

#define PD_ONCE_INIT INIT_ONCE_STATIC_INIT

#else
#include <pthread.h>
#include <errno.h>
Expand All @@ -29,8 +32,11 @@ typedef void* pd_dlib_t;
typedef pthread_mutex_t pd_mutex_t;
typedef pthread_cond_t pd_cond_t;
typedef pthread_t pd_thread_t;
typedef pthread_once_t pd_once_t;
typedef int pd_errno_t; // system error type
typedef pid_t pd_pid_t;

#define PD_ONCE_INIT PTHREAD_ONCE_INIT
#endif

int pd_random(void *, size_t);
Expand Down Expand Up @@ -59,6 +65,9 @@ void pd_thread_create(pd_thread_t*, void* (*)(void*), void *);

void pd_thread_join(pd_thread_t*);

/* call specific function only once in multithreaded environment */
int pd_once(pd_once_t*, void (*)(void));

struct pd_notifier_s;

struct pd_io_s {
Expand Down
18 changes: 15 additions & 3 deletions samples/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@

#define n 16

void print_bytes(unsigned char *bytes, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%02x ", bytes[i]);
}
printf("\n");
}

int main() {
unsigned char buf[n];
int status = pd_random(buf, 16);
Expand All @@ -12,10 +19,15 @@ int main() {
return 1;
}

for (size_t i = 0; i < n; i++) {
printf("%02x ", buf[i]);
print_bytes(buf, n);

unsigned char *buf2 = malloc(sizeof(unsigned char) * n);
if ((status = pd_random(buf2, n)) == 0) {
print_bytes(buf2, n);
} else {
printf("error: %s\n", pd_errstr(status));
return 1;
}
printf("\n");

return 0;
}
18 changes: 6 additions & 12 deletions src/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,14 @@

HCRYPTPROV hProv = 0;

bool initialized = false;
int pd__init_random_once() {
if (initialized)
return 0;

initialized = true;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
return -1;
}

return 0;
pd_once_t init_control = PD_ONCE_INIT;
void pd__init_random_once(void) {
// TODO: handle this error
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
}

int pd_random(void *bytes, size_t size) {
if (pd__init_random_once() == -1)
if (pd_once(&init_control, pd__init_random_once) == -1)
return PD_UNKNOWN;

if (size == 0)
Expand All @@ -60,6 +53,7 @@ int pd_random(void *bytes, size_t size) {
if (size == 0)
return 0;

// TODO: maybe use pd_once as well to get fd only once?
int fd = open("/dev/urandom", O_RDONLY);
if (fd == -1) {
return pd_errno();
Expand Down
8 changes: 8 additions & 0 deletions src/sys/thread_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,11 @@ void pd_thread_create(pd_thread_t *thread, void* (func)(void*), void *args) {
void pd_thread_join(pd_thread_t *thread) {
pthread_join(*thread, NULL);
}

int pd_once(pd_once_t *once_control, void (*init_routine)(void)) {
int errcode = pthread_once(once_control, init_routine);
if (errcode)
return pd_errmap(errcode);

return 0;
}
14 changes: 14 additions & 0 deletions src/sys/thread_win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

#include "pandio/core.h"
#include "pandio/err.h"
#include <process.h>


Expand Down Expand Up @@ -108,3 +109,16 @@ void pd_thread_create(pd_thread_t *thread, void* (func)(void*), void *arg) {
void pd_thread_join(pd_thread_t *thread) {
WaitForSingleObject(*thread, INFINITE);
}

BOOL pd__init_once(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) {
void (*init_routine)(void) = Parameter;
init_routine();
return TRUE;
}

int pd_once(pd_once_t *once_control, void (*init_routine)(void)) {
if (InitOnceExecuteOnce(once_control, pd__init_once, init_routine, NULL))
return 0;

return pd_errno();
}

0 comments on commit 3e02442

Please sign in to comment.