/src/resiprocate/rutil/ThreadIf.cxx
Line | Count | Source |
1 | | #include "rutil/ThreadIf.hxx" |
2 | | |
3 | | #if defined(WIN32) |
4 | | #include <stdio.h> |
5 | | #include <tchar.h> |
6 | | #include <time.h> |
7 | | #ifdef _WIN32_WCE |
8 | | typedef LPTHREAD_START_ROUTINE RESIP_THREAD_START_ROUTINE; |
9 | | #else |
10 | | #include <process.h> // for _beginthreadex() |
11 | | typedef unsigned(__stdcall *RESIP_THREAD_START_ROUTINE)(void*); |
12 | | #endif |
13 | | |
14 | | //from Random.cxx |
15 | | #include "rutil/Socket.hxx" |
16 | | #endif |
17 | | |
18 | | #include "rutil/ResipAssert.h" |
19 | | #include <iostream> |
20 | | #include "rutil/ThreadIf.hxx" |
21 | | #include "rutil/Mutex.hxx" |
22 | | #include "rutil/Lock.hxx" |
23 | | #include "rutil/Socket.hxx" |
24 | | #include "rutil/Logger.hxx" |
25 | | |
26 | | #define RESIPROCATE_SUBSYSTEM Subsystem::SIP |
27 | | |
28 | | using namespace resip; |
29 | | |
30 | | #ifdef WIN32 |
31 | | ThreadIf::TlsDestructorMap *ThreadIf::mTlsDestructors; |
32 | | Mutex *ThreadIf::mTlsDestructorsMutex; |
33 | | #endif |
34 | | |
35 | | std::thread::id noThread; |
36 | | |
37 | | #ifdef WIN32 |
38 | | unsigned int TlsDestructorInitializer::mInstanceCounter=0; |
39 | | TlsDestructorInitializer::TlsDestructorInitializer() |
40 | | { |
41 | | if (mInstanceCounter++ == 0) |
42 | | { |
43 | | ThreadIf::mTlsDestructorsMutex = new Mutex(); |
44 | | ThreadIf::mTlsDestructors = new ThreadIf::TlsDestructorMap; |
45 | | } |
46 | | } |
47 | | TlsDestructorInitializer::~TlsDestructorInitializer() |
48 | | { |
49 | | if (--mInstanceCounter == 0) |
50 | | { |
51 | | delete ThreadIf::mTlsDestructorsMutex; |
52 | | ThreadIf::mTlsDestructors->clear(); |
53 | | delete ThreadIf::mTlsDestructors; |
54 | | } |
55 | | } |
56 | | #endif |
57 | | |
58 | | |
59 | | ThreadIf::ThreadIf() : |
60 | 0 | mThreadObj(nullptr), |
61 | 0 | mId(), |
62 | 0 | mShutdown(false), |
63 | 0 | mShutdownMutex() |
64 | 0 | { |
65 | 0 | } |
66 | | |
67 | | |
68 | | ThreadIf::~ThreadIf() |
69 | 0 | { |
70 | 0 | shutdown(); |
71 | 0 | join(); |
72 | 0 | } |
73 | | |
74 | | void |
75 | | ThreadIf::run() |
76 | 0 | { |
77 | 0 | resip_assert(mId == noThread); |
78 | |
|
79 | 0 | mThreadObj = std::make_shared<std::thread>([this] |
80 | 0 | { |
81 | 0 | thread(); |
82 | | #ifdef WIN32 |
83 | | // Free data in TLS slots. |
84 | | ThreadIf::tlsDestroyAll(); |
85 | | #endif |
86 | 0 | }); |
87 | 0 | mId = mThreadObj->get_id(); |
88 | 0 | return; |
89 | 0 | } |
90 | | |
91 | | void |
92 | | ThreadIf::join() |
93 | 0 | { |
94 | | // !kh! |
95 | | // perhaps assert instead of returning when join()ed already? |
96 | | // programming error? |
97 | | //assert(mId == 0); |
98 | |
|
99 | 0 | if (!mThreadObj) |
100 | 0 | { |
101 | 0 | return; |
102 | 0 | } |
103 | | |
104 | 0 | if(!mThreadObj->joinable()) |
105 | 0 | { |
106 | 0 | return; |
107 | 0 | } |
108 | | |
109 | 0 | mThreadObj->join(); |
110 | |
|
111 | 0 | mThreadObj.reset(); |
112 | 0 | mId = noThread; |
113 | 0 | } |
114 | | |
115 | | void |
116 | | ThreadIf::detach() |
117 | 0 | { |
118 | 0 | mThreadObj->detach(); |
119 | 0 | mThreadObj.reset(); |
120 | 0 | mId = noThread; |
121 | 0 | } |
122 | | |
123 | | ThreadIf::Id |
124 | | ThreadIf::selfId() |
125 | 0 | { |
126 | 0 | return std::this_thread::get_id(); |
127 | 0 | } |
128 | | |
129 | | int |
130 | | ThreadIf::tlsKeyCreate(TlsKey &key, TlsDestructor *destructor) |
131 | 4 | { |
132 | | #if defined(WIN32) |
133 | | key = TlsAlloc(); |
134 | | if (key!=TLS_OUT_OF_INDEXES) |
135 | | { |
136 | | Lock lock(*mTlsDestructorsMutex); |
137 | | (*mTlsDestructors)[key] = destructor; |
138 | | return 0; |
139 | | } |
140 | | else |
141 | | { |
142 | | return GetLastError(); |
143 | | } |
144 | | #else |
145 | 4 | return pthread_key_create(&key, destructor); |
146 | 4 | #endif |
147 | 4 | } |
148 | | |
149 | | int |
150 | | ThreadIf::tlsKeyDelete(TlsKey key) |
151 | 0 | { |
152 | | #if defined(WIN32) |
153 | | if (TlsFree(key)>0) |
154 | | { |
155 | | Lock lock(*mTlsDestructorsMutex); |
156 | | mTlsDestructors->erase(key); |
157 | | return 0; |
158 | | } |
159 | | else |
160 | | { |
161 | | return GetLastError(); |
162 | | } |
163 | | #else |
164 | 0 | return pthread_key_delete(key); |
165 | 0 | #endif |
166 | 0 | } |
167 | | |
168 | | int |
169 | | ThreadIf::tlsSetValue(TlsKey key, const void *val) |
170 | 0 | { |
171 | | #if defined(WIN32) |
172 | | return TlsSetValue(key, (LPVOID)val)>0?0:GetLastError(); |
173 | | #else |
174 | 0 | return pthread_setspecific(key, val); |
175 | 0 | #endif |
176 | 0 | } |
177 | | |
178 | | void * |
179 | | ThreadIf::tlsGetValue(TlsKey key) |
180 | 2 | { |
181 | | #if defined(WIN32) |
182 | | return TlsGetValue(key); |
183 | | #else |
184 | 2 | return pthread_getspecific(key); |
185 | 2 | #endif |
186 | 2 | } |
187 | | |
188 | | |
189 | | void |
190 | | ThreadIf::shutdown() |
191 | 0 | { |
192 | 0 | Lock lock(mShutdownMutex); |
193 | 0 | if (!mShutdown) |
194 | 0 | { |
195 | 0 | mShutdown = true; |
196 | 0 | mShutdownCondition.notify_one(); |
197 | 0 | } |
198 | 0 | } |
199 | | |
200 | | bool |
201 | | ThreadIf::waitForShutdown(int ms) const |
202 | 0 | { |
203 | 0 | Lock lock(mShutdownMutex); |
204 | 0 | if(!mShutdown) |
205 | 0 | { |
206 | 0 | mShutdownCondition.wait_for(lock, std::chrono::milliseconds(ms)); |
207 | 0 | } |
208 | 0 | return mShutdown; |
209 | 0 | } |
210 | | |
211 | | bool |
212 | | ThreadIf::isShutdown() const |
213 | 0 | { |
214 | 0 | Lock lock(mShutdownMutex); |
215 | 0 | (void)lock; |
216 | 0 | return ( mShutdown ); |
217 | 0 | } |
218 | | |
219 | | #ifdef WIN32 |
220 | | void |
221 | | ThreadIf::tlsDestroyAll() |
222 | | { |
223 | | Lock lock(*mTlsDestructorsMutex); |
224 | | ThreadIf::TlsDestructorMap::const_iterator i = mTlsDestructors->begin(); |
225 | | while(i != mTlsDestructors->end()) |
226 | | { |
227 | | void *val = TlsGetValue(i->first); |
228 | | if (val != NULL) |
229 | | { |
230 | | (*(i->second))(val); |
231 | | } |
232 | | i++; |
233 | | } |
234 | | } |
235 | | #endif |
236 | | |
237 | | // End of File |
238 | | |
239 | | /* ==================================================================== |
240 | | * The Vovida Software License, Version 1.0 |
241 | | * |
242 | | * Copyright (c) 2000-2008 Vovida Networks, Inc. All rights reserved. |
243 | | * |
244 | | * Redistribution and use in source and binary forms, with or without |
245 | | * modification, are permitted provided that the following conditions |
246 | | * are met: |
247 | | * |
248 | | * 1. Redistributions of source code must retain the above copyright |
249 | | * notice, this list of conditions and the following disclaimer. |
250 | | * |
251 | | * 2. Redistributions in binary form must reproduce the above copyright |
252 | | * notice, this list of conditions and the following disclaimer in |
253 | | * the documentation and/or other materials provided with the |
254 | | * distribution. |
255 | | * |
256 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
257 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
258 | | * not be used to endorse or promote products derived from this |
259 | | * software without prior written permission. For written |
260 | | * permission, please contact vocal@vovida.org. |
261 | | * |
262 | | * 4. Products derived from this software may not be called "VOCAL", nor |
263 | | * may "VOCAL" appear in their name, without prior written |
264 | | * permission of Vovida Networks, Inc. |
265 | | * |
266 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
267 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
268 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
269 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
270 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
271 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
272 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
273 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
274 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
275 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
276 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
277 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
278 | | * DAMAGE. |
279 | | * |
280 | | * ==================================================================== |
281 | | * |
282 | | * This software consists of voluntary contributions made by Vovida |
283 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
284 | | * Inc. For more information on Vovida Networks, Inc., please see |
285 | | * <http://www.vovida.org/>. |
286 | | * |
287 | | */ |