1 /****************************************************************************
2  *
3  *  Copyright (C) 2000-2001 RealNetworks, Inc. All rights reserved.
4  *
5  *  This program is free software.  It may be distributed under the terms
6  *  in the file LICENSE, found in the top level of the source distribution.
7  *
8  */
9 
10 #ifndef _THREAD_H
11 #define _THREAD_H
12 
13 #include "types.h"
14 
15 #ifdef _UNIX
16 #include <pthread.h>
17 typedef pthread_t       threadobj_t;
18 typedef int             waittimer_t;
19 #ifndef INFTIM
20 #define INFTIM (-1) /* Linux uses -1 but doesn't define INFTIM */
21 #endif
22 #endif
23 #ifdef _WIN32
24 typedef HANDLE  threadobj_t;
25 typedef DWORD   waittimer_t;
26 #define INFTIM  INFINITE
27 #endif
28 
29 #include "types.h"
30 #include "tlist.h"
31 #include "stream.h"
32 #include "sock.h"
33 #include "timer.h"
34 
35 class CMutex
36 {
37 private: // Unimplemented
38     CMutex( const CMutex& );
39     CMutex& operator=( const CMutex& );
40 
41 public:
42     CMutex( void );
43     virtual ~CMutex( void );
44 
45     void Lock( void );
46     void Unlock( void );
47 
48 private:
49 #ifdef _UNIX
50     pthread_mutex_t m_mutex;
51 #endif
52 #ifdef _WIN32
53     HANDLE          m_mutex;
54 #endif
55 };
56 
57 class CSemaphore
58 {
59 private: // Unimplemented
60     CSemaphore( const CSemaphore& );
61     CSemaphore& operator=( const CSemaphore& );
62 
63 public:
64     CSemaphore( UINT nCount );
65     virtual ~CSemaphore( void );
66 
67     void Lock( void );
68     void Unlock( void );
69 
70 private:
71 #ifdef _UNIX
72     pthread_mutex_t m_mutex;
73     pthread_cond_t  m_cond;
74     UINT            m_count;
75 #endif
76 #ifdef _WIN32
77     HANDLE          m_semaphore;
78 #endif
79 };
80 
81 /*
82  * Initializing a C++ thread object must involve two steps: creating the
83  * C++ object and creating the thread.  If we create the thread in the
84  * ctor, we are courting disaster because the C++ object is not fully
85  * constructed until after the ctor finishes.  If you think this is all
86  * theoretical and doesn't apply in real life, consider this:
87  *
88  *   - GNU g++ will not call a derived virtual function until after
89  *     the ctor is done -- it will *always* call the function defined in
90  *     the current class.  Been there, done that, spent hours debugging.
91  *
92  *   - MS Visual C++ warns about using 'this' in the ctor.  Probably
93  *     because more than one programmer has been bitten doing it.
94  */
95 
96 class CThread
97 {
98 #ifdef _UNIX
99     friend void* thread_start( void* );
100 #endif
101 #ifdef _WIN32
102     friend DWORD WINAPI thread_start( LPVOID );
103 #endif
104 
105 private: // Unimplemented
106     CThread( const CThread& );
107     CThread& operator=( const CThread& );
108 
109 public:
110     CThread( void );
111     virtual ~CThread( void );
112 
113     void Create( void );
114 
115 //    void Suspend( void );
116 //    void Resume( void );
117 
118     static CThread* This( void );
119 
120 protected:
121     virtual bool Init( void );
122     virtual void Run( void );
123     virtual int  Exit( void );
124 
125 private:
126     threadobj_t m_thread;
127     int         m_retval;
128 };
129 
130 /*
131  * CEventThread -- the scheduler
132  */
133 
134 class CEventThread : public CThread
135 {
136 public:
137     CEventThread( void );
138     ~CEventThread( void );
139 
140 protected:
141     virtual void Run( void );
142     virtual bool Init( void );
143     virtual int  Exit( void );
144 
145 private:
146     friend class CSocket;
147     friend class CTimer;
148     bool AddStream( CSocket* pSock );
149     void DelStream( CSocket* pSock );
150     void SetStreamSelect( CSocket* pSock, UINT nWhich );
151     void AddTimer( CTimer* pTimer );
152     void DelTimer( CTimer* pTimer );
153 
154     void    Heapify( UINT32 now, UINT n );
155 
156 private:
157     UINT        m_nSocks;
158     UINT        m_nSockAlloc;
159     CSocket**   m_ppSocks;
160     waitobj_t*  m_pWaitObjs;
161     UINT        m_nTimers;
162     UINT        m_nTimerAlloc;
163     CTimer**    m_ppTimers;
164 };
165 
166 #endif //ndef _THREAD_H
167