/*******************************
**     Begin Thread Win32     **
*******************************/

#if OS_WINDOWS

////////////////////////////////
// Win32 Implementation: Thread Functions

MR4TH_SYMBOL void
th_thread_create(TH_Func *func, void *param, TH_Thread *thread_out){
  thread_out->thread = CreateThread(0, 0, (DWORD(*)(void*))func, param, 0, 0);
}

MR4TH_SYMBOL void
th_thread_force_stop(TH_Thread *thread){
  TerminateThread(thread->thread, 0);
}

MR4TH_SYMBOL void
th_mutex_init(TH_Mutex *mutex){
  InitializeCriticalSection(&mutex->crit);
}

MR4TH_SYMBOL void
th_mutex_release(TH_Mutex *mutex){
  DeleteCriticalSection(&mutex->crit);
}

MR4TH_SYMBOL void
th_mutex_wait_for_lock(TH_Mutex *mutex){
  EnterCriticalSection(&mutex->crit);
}

MR4TH_SYMBOL void
th_mutex_unlock(TH_Mutex *mutex){
  LeaveCriticalSection(&mutex->crit);
}

MR4TH_SYMBOL void
th_condvar_init(TH_CondVar *cv){
  InitializeConditionVariable(&cv->cv);
}

MR4TH_SYMBOL void
th_condvar_release(TH_CondVar *cv){
  // on windows condition variables require no release
}

MR4TH_SYMBOL void
th_condvar_wait_for_signal(TH_CondVar *cv, TH_Mutex *mutex){
  SleepConditionVariableCS(&cv->cv, &mutex->crit, INFINITE);
}

MR4TH_SYMBOL void
th_condvar_signal(TH_CondVar *cv){
  WakeConditionVariable(&cv->cv);
}

#endif

/*******************************
**      End Thread Win32      **
*******************************/


/*******************************
**     Begin Thread Linux     **
*******************************/

#if OS_LINUX

MR4TH_SYMBOL void
th_thread_create(TH_Func *func, void *param, TH_Thread *thread_out){
  pthread_create(&thread_out->thread, 0, (void*(*)(void*))func, param);
}

MR4TH_SYMBOL void
th_thread_force_stop(TH_Thread *thread){
  pthread_cancel(thread->thread);
}

MR4TH_SYMBOL void
th_mutex_init(TH_Mutex *mutex){
  pthread_mutex_init(&mutex->mutex, 0);
}

MR4TH_SYMBOL void
th_mutex_release(TH_Mutex *mutex){
  pthread_mutex_destroy(&mutex->mutex);
}

MR4TH_SYMBOL void
th_mutex_wait_for_lock(TH_Mutex *mutex){
  pthread_mutex_lock(&mutex->mutex);
}

MR4TH_SYMBOL void
th_mutex_unlock(TH_Mutex *mutex){
  pthread_mutex_unlock(&mutex->mutex);
}

MR4TH_SYMBOL void
th_condvar_init(TH_CondVar *cv){
  pthread_cond_init(&cv->cv, 0);
}

MR4TH_SYMBOL void
th_condvar_release(TH_CondVar *cv){
  pthread_cond_destroy(&cv->cv);
}

MR4TH_SYMBOL void
th_condvar_wait_for_signal(TH_CondVar *cv, TH_Mutex *mutex){
  pthread_cond_wait(&cv->cv, &mutex->mutex);
}

MR4TH_SYMBOL void
th_condvar_signal(TH_CondVar *cv){
  pthread_cond_signal(&cv->cv);
}

#endif

/*******************************
**      End Thread Linux      **
*******************************/
