- /**
- * @file kc_thread.c
- * @brief スレッドモジュール
- * @copyright 2020 - 2024 Nomura Kei
- */
- #include <stdio.h>
-
- #include <kc_threads.h>
- #include <kc_threads_win.h>
-
- #if (KC_IS_WINDOWS)
-
- int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
- {
- if ((thr == NULL) || (func == NULL))
- {
- return thrd_error;
- }
-
- thr->handle = CreateThread(
- NULL, // セキュリティ属性
- 0, // スタックサイズ
- (LPTHREAD_START_ROUTINE)func, // スレッド関数
- arg, // 引数
- 0, // 作成フラグ
- &(thr->thread_id) // スレッドID
- );
-
- if (thr->handle == NULL)
- {
- return thrd_error;
- }
- return thrd_success;
- }
- int thrd_join(thrd_t thr, int *res)
- {
- if (WaitForSingleObject(thr.handle, INFINITE) != WAIT_OBJECT_0)
- {
- return thrd_error;
- }
- if (res != NULL)
- {
- DWORD retcode;
- if (GetExitCodeThread(thr.handle, &retcode) == 0)
- {
- return thrd_error;
- }
- *res = (int)retcode;
- }
- CloseHandle(thr.handle);
- return thrd_success;
- }
-
- int thrd_detach(thrd_t thr)
- {
- if (thr.handle == NULL)
- {
- return thrd_error;
- }
- if (CloseHandle(thr.handle) == 0)
- {
- return thrd_error;
- }
- return thrd_success;
- }
-
- thrd_t thrd_current(void)
- {
- thrd_t current;
- current.handle = GetCurrentThread();
- current.thread_id = GetThreadId(current.handle);
- return current;
- }
-
- int thrd_equal(thrd_t lhs, thrd_t rhs)
- {
- return (lhs.thread_id == rhs.thread_id);
- }
-
- void thrd_yield(void)
- {
- SwitchToThread();
- }
-
- int thrd_sleep(const struct timespec *duration, struct timespec *remaining)
- {
- if (duration == NULL)
- {
- return thrd_error;
- }
-
- // Windows の Sleep は、ms 単位
- DWORD msec = (DWORD)(duration->tv_sec * 1000 + duration->tv_nsec / 1000000);
- Sleep(msec);
-
- // 常に成功したものとして、remaining は 0 に設定する。
- if (remaining != NULL)
- {
- remaining->tv_sec = 0;
- remaining->tv_nsec = 0;
- }
- return thrd_success;
- }
-
- /**
- * 指定されたミューテックスを初期化します。
- * Windows の場合、常に mtx_recursive が有効となります。
- *
- * @param mtx 初期化するミューテックスの識別子
- * @param type タイプ (mtx_plain, mtx_timed, mtx_plain|mtx_recursive, mtx_timed|mtx_recursive)
- * @return thrd_success/thrd_error (成功/失敗)
- */
- int mtx_init(mtx_t *mtx, int type)
- {
- if (mtx == NULL)
- {
- return thrd_error;
- }
- mtx->type = type;
- InitializeCriticalSection(&mtx->cs);
- return thrd_success;
- }
-
- /**
- * ミューテックスを破棄します。
- *
- * @param mtx 破棄するミューテックス識別子
- */
- void mtx_destroy(mtx_t *mtx)
- {
- printf("mtx_destroy: mtx->cs:%p\n", &mtx->cs);
- DeleteCriticalSection(&mtx->cs);
- }
-
- /**
- * 指定されたミューテックスがロックされるまで現在のスレッドをロックします。
- *
- * @param mtx ミューテックス識別子
- * @return thrd_success/thrd_error (成功/失敗)
- */
- int mtx_lock(mtx_t *mtx)
- {
- EnterCriticalSection(&mtx->cs);
- return thrd_success;
- }
-
- /**
- *
- */
- int mtx_unlock(mtx_t *mtx)
- {
- LeaveCriticalSection(&mtx->cs);
- return thrd_success;
- }
-
- int cnd_init(cnd_t *cond)
- {
- if (cond == NULL)
- {
- return thrd_error;
- }
- InitializeConditionVariable(&cond->cond);
- return thrd_success;
- }
-
- int cnd_signal(cnd_t *cond)
- {
- if (cond == NULL)
- {
- return thrd_error;
- }
- WakeConditionVariable(&cond->cond);
- return thrd_success;
- }
- int cnd_broadcast(cnd_t *cond)
- {
- if (cond == NULL)
- {
- return thrd_error;
- }
- WakeAllConditionVariable(&cond->cond);
- return thrd_success;
- }
- int cnd_wait(cnd_t *cond, mtx_t *mtx)
- {
- if ((cond == NULL) || (mtx == NULL))
- {
- return thrd_error;
- }
- if (SleepConditionVariableCS(&cond->cond, &mtx->cs, INFINITE))
- {
- return thrd_success;
- }
- return thrd_error;
- }
-
- int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
- {
- if ((cond == NULL) || (mtx == NULL) || (ts == NULL))
- {
- return thrd_error;
- }
- DWORD msec = (DWORD)(ts->tv_sec * 1000 + ts->tv_nsec / 1000000);
- if (SleepConditionVariableCS(&cond->cond, &mtx->cs, msec))
- {
- return thrd_timedout;
- }
- return thrd_error;
- }
-
- void cnd_destroy(cnd_t *cond)
- {
- // Nothing to do
- UNUSED_VARIABLE(cond);
- }
-
- #endif