home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Database Designers / Rational Rose 2000 / Rational Setup.EXE / common / lib / MSWin32-x86 / CORE / win32thread.h < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-26  |  6.1 KB  |  188 lines

  1. #ifndef _WIN32THREAD_H
  2. #define _WIN32THREAD_H
  3. typedef struct win32_cond { LONG waiters; HANDLE sem; } perl_cond;
  4. typedef DWORD perl_key;
  5. typedef HANDLE perl_os_thread;
  6.  
  7. #ifndef DONT_USE_CRITICAL_SECTION
  8.  
  9. /* Critical Sections used instead of mutexes: lightweight,
  10.  * but can't be communicated to child processes, and can't get
  11.  * HANDLE to it for use elsewhere.
  12.  */
  13. typedef CRITICAL_SECTION perl_mutex;
  14. #define MUTEX_INIT(m) InitializeCriticalSection(m)
  15. #define MUTEX_LOCK(m) EnterCriticalSection(m)
  16. #define MUTEX_UNLOCK(m) LeaveCriticalSection(m)
  17. #define MUTEX_DESTROY(m) DeleteCriticalSection(m)
  18.  
  19. #else
  20.  
  21. typedef HANDLE perl_mutex;
  22. #define MUTEX_INIT(m) \
  23.     STMT_START {                        \
  24.     if ((*(m) = CreateMutex(NULL,FALSE,NULL)) == NULL)    \
  25.         croak("panic: MUTEX_INIT");                \
  26.     } STMT_END
  27. #define MUTEX_LOCK(m) \
  28.     STMT_START {                        \
  29.     if (WaitForSingleObject(*(m),INFINITE) == WAIT_FAILED)    \
  30.         croak("panic: MUTEX_LOCK");                \
  31.     } STMT_END
  32. #define MUTEX_UNLOCK(m) \
  33.     STMT_START {                        \
  34.     if (ReleaseMutex(*(m)) == 0)                \
  35.         croak("panic: MUTEX_UNLOCK");            \
  36.     } STMT_END
  37. #define MUTEX_DESTROY(m) \
  38.     STMT_START {                        \
  39.     if (CloseHandle(*(m)) == 0)                \
  40.         croak("panic: MUTEX_DESTROY");            \
  41.     } STMT_END
  42.  
  43. #endif
  44.  
  45. /* These macros assume that the mutex associated with the condition
  46.  * will always be held before COND_{SIGNAL,BROADCAST,WAIT,DESTROY},
  47.  * so there's no separate mutex protecting access to (c)->waiters
  48.  */
  49. #define COND_INIT(c) \
  50.     STMT_START {                        \
  51.     (c)->waiters = 0;                    \
  52.     (c)->sem = CreateSemaphore(NULL,0,LONG_MAX,NULL);    \
  53.     if ((c)->sem == NULL)                    \
  54.         croak("panic: COND_INIT (%ld)",GetLastError());    \
  55.     } STMT_END
  56.  
  57. #define COND_SIGNAL(c) \
  58.     STMT_START {                        \
  59.     if ((c)->waiters > 0 &&                    \
  60.         ReleaseSemaphore((c)->sem,1,NULL) == 0)        \
  61.         croak("panic: COND_SIGNAL (%ld)",GetLastError());    \
  62.     } STMT_END
  63.  
  64. #define COND_BROADCAST(c) \
  65.     STMT_START {                        \
  66.     if ((c)->waiters > 0 &&                    \
  67.         ReleaseSemaphore((c)->sem,(c)->waiters,NULL) == 0)    \
  68.         croak("panic: COND_BROADCAST (%ld)",GetLastError());\
  69.     } STMT_END
  70.  
  71. #define COND_WAIT(c, m) \
  72.     STMT_START {                        \
  73.     (c)->waiters++;                        \
  74.     MUTEX_UNLOCK(m);                    \
  75.     /* Note that there's no race here, since a        \
  76.      * COND_BROADCAST() on another thread will have seen the\
  77.      * right number of waiters (i.e. including this one) */    \
  78.     if (WaitForSingleObject((c)->sem,INFINITE)==WAIT_FAILED)\
  79.         croak("panic: COND_WAIT (%ld)",GetLastError());    \
  80.     /* XXX there may be an inconsequential race here */    \
  81.     MUTEX_LOCK(m);                        \
  82.     (c)->waiters--;                        \
  83.     } STMT_END
  84.  
  85. #define COND_DESTROY(c) \
  86.     STMT_START {                        \
  87.     (c)->waiters = 0;                    \
  88.     if (CloseHandle((c)->sem) == 0)                \
  89.         croak("panic: COND_DESTROY (%ld)",GetLastError());    \
  90.     } STMT_END
  91.  
  92. #define DETACH(t) \
  93.     STMT_START {                        \
  94.     if (CloseHandle((t)->self) == 0) {            \
  95.         MUTEX_UNLOCK(&(t)->mutex);                \
  96.         croak("panic: DETACH");                \
  97.     }                            \
  98.     } STMT_END
  99.  
  100.  
  101. #define THREAD_CREATE(t, f)    Perl_thread_create(t, f)
  102. #define THREAD_POST_CREATE(t)    NOOP
  103.  
  104. /* XXX Docs mention that the RTL versions of thread creation routines
  105.  * should be used, but that advice only seems applicable when the RTL
  106.  * is not in a DLL.  RTL DLLs in both Borland and VC seem to do all of
  107.  * the init/deinit required upon DLL_THREAD_ATTACH/DETACH.  So we seem
  108.  * to be completely safe using straight Win32 API calls, rather than
  109.  * the much braindamaged RTL calls.
  110.  *
  111.  * _beginthread() in the RTLs call CloseHandle() just after the thread
  112.  * function returns, which means: 1) we have a race on our hands
  113.  * 2) it is impossible to implement join() semantics.
  114.  *
  115.  * IOW, do *NOT* turn on USE_RTL_THREAD_API!  It is here
  116.  * for experimental purposes only. GSAR 98-01-02
  117.  */
  118. #ifdef USE_RTL_THREAD_API
  119. #  include <process.h>
  120. #  if defined(__BORLANDC__)
  121.      /* Borland RTL doesn't allow a return value from thread function! */
  122. #    define THREAD_RET_TYPE    void _USERENTRY
  123. #    define THREAD_RET_CAST(p)    ((void)(thr->i.retv = (void *)(p)))
  124. #  elif defined (_MSC_VER)
  125. #    define THREAD_RET_TYPE    unsigned __stdcall
  126. #    define THREAD_RET_CAST(p)    ((unsigned)(p))
  127. #  else
  128.      /* CRTDLL.DLL doesn't allow a return value from thread function! */
  129. #    define THREAD_RET_TYPE    void __cdecl
  130. #    define THREAD_RET_CAST(p)    ((void)(thr->i.retv = (void *)(p)))
  131. #  endif
  132. #else    /* !USE_RTL_THREAD_API */
  133. #  define THREAD_RET_TYPE    DWORD WINAPI
  134. #  define THREAD_RET_CAST(p)    ((DWORD)(p))
  135. #endif    /* !USE_RTL_THREAD_API */
  136.  
  137. typedef THREAD_RET_TYPE thread_func_t(void *);
  138.  
  139.  
  140. START_EXTERN_C
  141.  
  142. #if defined(PERLDLL) && defined(USE_DECLSPEC_THREAD) && (!defined(__BORLANDC__) || defined(_DLL))
  143. extern __declspec(thread) struct perl_thread *Perl_current_thread;
  144. #define SET_THR(t)           (Perl_current_thread = t)
  145. #define THR            Perl_current_thread
  146. #else
  147. #define THR            Perl_getTHR()
  148. #define SET_THR(t)        Perl_setTHR(t)
  149. #endif
  150. struct perl_thread;
  151.  
  152. void Perl_alloc_thread_key _((void));
  153. int Perl_thread_create _((struct perl_thread *thr, thread_func_t *fn));
  154. void Perl_set_thread_self _((struct perl_thread *thr));
  155. struct perl_thread *Perl_getTHR _((void));
  156. void Perl_setTHR _((struct perl_thread *t));
  157. void Perl_init_thread_intern _((struct perl_thread *t));
  158.  
  159. END_EXTERN_C
  160.  
  161. #define INIT_THREADS NOOP
  162. #define ALLOC_THREAD_KEY Perl_alloc_thread_key()
  163. #define SET_THREAD_SELF(thr) Perl_set_thread_self(thr)
  164.  
  165. #if defined(USE_RTL_THREAD_API) && !defined(_MSC_VER)
  166. #define JOIN(t, avp)                            \
  167.     STMT_START {                            \
  168.     if ((WaitForSingleObject((t)->self,INFINITE) == WAIT_FAILED)    \
  169.          || (GetExitCodeThread((t)->self,(LPDWORD)(avp)) == 0)    \
  170.          || (CloseHandle((t)->self) == 0))                \
  171.         croak("panic: JOIN");                    \
  172.     *avp = (AV *)((t)->i.retv);                    \
  173.     } STMT_END
  174. #else    /* !USE_RTL_THREAD_API || _MSC_VER */
  175. #define JOIN(t, avp)                            \
  176.     STMT_START {                            \
  177.     if ((WaitForSingleObject((t)->self,INFINITE) == WAIT_FAILED)    \
  178.          || (GetExitCodeThread((t)->self,(LPDWORD)(avp)) == 0)    \
  179.          || (CloseHandle((t)->self) == 0))                \
  180.         croak("panic: JOIN");                    \
  181.     } STMT_END
  182. #endif    /* !USE_RTL_THREAD_API || _MSC_VER */
  183.  
  184. #define YIELD            Sleep(0)
  185.  
  186. #endif /* _WIN32THREAD_H */
  187.  
  188.