You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
6.2 KiB

5 years ago
/***************************************************************************
*
* _thread.h - Class encapsulating portable thread primitives
*
* This is an internal header file used to implement the C++ Standard
* Library. It should never be #included directly by a program.
*
* $Id: _thread.h 172106 2011-11-02 17:04:12Z statham $
*
***************************************************************************
*
* Copyright (c) 1994-2001 Rogue Wave Software, Inc. All Rights Reserved.
*
* This computer software is owned by Rogue Wave Software, Inc. and is
* protected by U.S. copyright laws and other laws and by international
* treaties. This computer software is furnished by Rogue Wave Software,
* Inc. pursuant to a written license agreement and may be used, copied,
* transmitted, and stored only in accordance with the terms of such
* license and with the inclusion of the above copyright notice. This
* computer software or any other copies thereof may not be provided or
* otherwise made available to any other person.
*
* U.S. Government Restricted Rights. This computer software is provided
* with Restricted Rights. Use, duplication, or disclosure by the
* Government is subject to restrictions as set forth in subparagraph (c)
* (1) (ii) of The Rights in Technical Data and Computer Software clause
* at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
* Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19,
* as applicable. Manufacturer is Rogue Wave Software, Inc., 5500
* Flatiron Parkway, Boulder, Colorado 80301 USA.
*
**************************************************************************/
#ifndef _RWSTD_THREAD_H_INCLUDED
#define _RWSTD_THREAD_H_INCLUDED
#include <rw/_defs.h>
#if defined (_RWSTD_SOLARIS_THREADS)
# include <thread.h>
# include <unistd.h> // for sleep()
# define _RWSTD_THREAD_ID thread_t
# define _RWSTD_THREAD_PROC(name) void* name (void *arg)
# define _RWSTD_THREAD_CREATE(tid, proc, arg) \
thr_create (0, 0, proc, arg, 0, &tid)
# define _RWSTD_THREAD_JOIN(tid) thr_join (tid, 0, 0)
# define _RWSTD_SLEEP(nsec) sleep (nsec)
# define _RWSTD_THREAD_GETID(tid) tid
#elif defined (_RWSTD_POSIX_D10_THREADS)
# include <pthread.h>
# include <unistd.h> // for sleep()
# define _RWSTD_THREAD_ID pthread_t
# define _RWSTD_THREAD_PROC(name) void* name (void *arg)
# define _RWSTD_THREAD_CREATE(tid, proc, arg) \
pthread_create (&tid, 0, proc, arg)
# define _RWSTD_THREAD_JOIN(tid) pthread_join (tid, 0)
# define _RWSTD_SLEEP(nsec) sleep (nsec)
# define _RWSTD_THREAD_GETID(tid) tid
#elif defined (_RWSTD_DCE_THREADS)
# if defined (_RWSTD_NO_DCE_PTHREAD_H)
# include <pthread.h>
# else
# include <dce/pthread.h>
# endif
# include <unistd.h>
# define _RWSTD_THREAD_ID pthread_t
# define _RWSTD_THREAD_PROC(name) void* name (void *arg)
# define _RWSTD_THREAD_CREATE(tid, proc, arg) \
pthread_create (&tid, pthread_attr_default, proc, arg)
# define _RWSTD_THREAD_JOIN(tid) pthread_join (tid, 0)
# define _RWSTD_SLEEP(nsec) sleep (nsec)
# define _RWSTD_THREAD_GETID(tid) pthread_getunique_np(&tid)
#elif defined(_WIN32)
# include <windows.h>
# define _RWSTD_THREAD_ID HANDLE
# define _RWSTD_THREAD_PROC(name) DWORD name (void *arg)
# define _RWSTD_THREAD_CREATE(tid, proc, arg) \
((tid = CreateThread (0, 0, (DWORD(__stdcall*)(void*))proc, \
arg, 0, 0)) ? 0 : -1)
# define _RWSTD_THREAD_JOIN(tid) WaitForSingleObject (tid, INFINITE)
# define _RWSTD_SLEEP(nsec) Sleep (nsec)
# define _RWSTD_THREAD_GETID(tid) tid
#else
# error "unknown thread environment"
#endif
_RWSTD_NAMESPACE_BEGIN (__rw)
extern "C" {
#if ( !defined (__sgi) \
|| !defined (_COMPILER_VERSION) || _COMPILER_VERSION > 730) \
&& (!defined (__HP_aCC) || __HP_aCC > 32700)
// working around a bug in HP aCC +w (bogus future error 503)
// working around a bug in MIPSpro 7.3.1.1m
inline
#endif // !__sgi || !_COMPILER_VERSION || _COMPILER_VERSION > 730
void* __rw_run_thread (void*);
}
class __rw_thread
{
public:
enum _C_state_t {
_C_created, _C_error, _C_suspended, _C_running, _C_exited
};
enum _C_attr_t { _C_attr_default, _C_attr_detached };
__rw_thread (int __attr = _C_attr_default)
#if defined(_RWSTD_DCE_THREADS)
: _C_state (_C_created),
_C_attr (__attr) { }
#else
: _C_tid (0),
_C_state (_C_created),
_C_attr (__attr) { }
#endif
unsigned long _C_get_tid () const {
typedef unsigned long ulong;
return ulong(_RWSTD_THREAD_GETID(_C_tid));
}
_C_state_t _C_get_state () const {
return _C_state;
}
void _C_run () {
_C_state = _RWSTD_THREAD_CREATE (_C_tid, __rw_run_thread, this)
? _C_error : _C_running;
}
void _C_join () {
if (_C_running == _C_state && !(_C_attr & _C_attr_detached))
_C_state = _RWSTD_THREAD_JOIN (_C_tid) ? _C_error : _C_exited;
}
static void _C_sleep (unsigned __nsec) {
_RWSTD_SLEEP (__nsec);
}
#if !defined (__EDG_VERSION__) || __EDG_VERSION__ > 240
// edg (and derivatives) gets confused after seeing the friend
// declaration and forgets about the C linkage of the function
protected:
friend void* __rw_run_thread (void*);
#else // if defined (__EDG_VERSION__) && __EDG_VERSION__ <= 240
public:
#endif // !defined (__EDG_VERSION__) || __EDG_VERSION__ > 240
virtual void _C_do_run () = 0;
protected:
operator void* () {
return _C_join (), _C_result;
}
_RWSTD_THREAD_ID _C_tid; // thread id
_C_state_t _C_state; // thread state
int _C_attr; // thread attributes
void *_C_result; // result of thread function
};
extern "C" {
void* __rw_run_thread (void *__arg)
{
#if defined (sun) || defined (__sun) || defined (__sun__)
// necessary to allow other threads to finish creation
// (otherwise all threads will run in serially)
sleep (1);
#endif // defined (sun) || defined (__sun) || defined (__sun__)
((__rw_thread*)__arg)->_C_do_run ();
return 0;
}
}
_RWSTD_NAMESPACE_END // __rw
#endif // _RWSTD_THREAD_H_INCLUDED