Coverage Report

Created: 2025-11-16 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
 */