#ifndef PTHREAD_COND_T
#define PTHREAD_COND_T

#define _WIN32_WINNT 0x0400
#include <windows.h>

#define PTHREAD_CREATE_DETACHED 69

typedef DWORD pthread_key_t;

typedef HANDLE pthread_mutex_t;

typedef HANDLE pthread_t;

typedef int pthread_attr_t;

extern void pthread_attr_init( pthread_attr_t *  pthread_attr );

extern void pthread_attr_setdetachstate( pthread_attr_t *  pthread_attr,
                                         int               detach_state );

extern int pthread_create( pthread_t *             pthread,
                           pthread_attr_t *        pthread_attr,
                           LPTHREAD_START_ROUTINE  thread_entry_point,
                           void *                  thread_entry_point_arg );

// !!!!! CHECK SIGNATURE !!!!!
extern int pthread_key_create( pthread_key_t *  key,
                               void *           initial_value );

// !!!!! CHECK SIGNATURE !!!!!
extern void * pthread_getspecific( pthread_key_t  key );

// !!!!! CHECK SIGNATURE AND RETURN VALUE SEMANTICS !!!!!
extern int pthread_setspecific( pthread_key_t  key,
                                void *         value );

extern int pthread_mutex_init( pthread_mutex_t *  mutex,
                               int                arg );

extern void pthread_mutex_lock( pthread_mutex_t *  mutex );

extern void pthread_mutex_unlock( pthread_mutex_t *  mutex );


// Strategies for Implementing POSIX Condition Variables on Win32
// Douglas C. Schmidt and Irfan Pyarali
// C++ Report, SIGS, Vol. 10, No. 5, June, 1998. 
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html

typedef struct
{
  int waiters_count_;
  // Number of waiting threads.

  CRITICAL_SECTION waiters_count_lock_;
  // Serialize access to <waiters_count_>.

  HANDLE sema_;
  // Semaphore used to queue up threads waiting for the condition to
  // become signaled. 

  HANDLE waiters_done_;
  // An auto-reset event used by the broadcast/signal thread to wait
  // for all the waiting thread(s) to wake up and be released from the
  // semaphore. 

  size_t was_broadcast_;
  // Keeps track of whether we were broadcasting or signaling.  This
  // allows us to optimize the code if we're just signaling.
} pthread_cond_t;

typedef void pthread_condattr_t;

extern int pthread_cond_init( pthread_cond_t *            cv,
                              const pthread_condattr_t *  condattr );

extern int pthread_cond_wait( pthread_cond_t *   cv, 
                              pthread_mutex_t *  external_mutex );

extern int pthread_cond_signal( pthread_cond_t *  cv );

extern int pthread_cond_broadcast( pthread_cond_t *  cv );


#endif
