Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poco/Foundation/include/Poco/Thread_POSIX.h
Line
Count
Source
1
//
2
// Thread_POSIX.h
3
//
4
// Library: Foundation
5
// Package: Threading
6
// Module:  Thread
7
//
8
// Definition of the ThreadImpl class for POSIX Threads.
9
//
10
// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
11
// and Contributors.
12
//
13
// SPDX-License-Identifier: BSL-1.0
14
//
15
16
17
#ifndef Foundation_Thread_POSIX_INCLUDED
18
#define Foundation_Thread_POSIX_INCLUDED
19
20
21
#include "Poco/Foundation.h"
22
#include "Poco/Mutex.h"
23
#include "Poco/Runnable.h"
24
#include "Poco/SignalHandler.h"
25
#include "Poco/Event.h"
26
#include "Poco/RefCountedObject.h"
27
#include "Poco/AutoPtr.h"
28
#include "Poco/SharedPtr.h"
29
#include <pthread.h>
30
// must be limits.h (not <climits>) for PTHREAD_STACK_MIN on Solaris
31
#include <limits.h>
32
#if !defined(POCO_NO_SYS_SELECT_H)
33
#include <sys/select.h>
34
#endif
35
#if defined(POCO_VXWORKS)
36
#include <cstring>
37
#endif
38
39
namespace Poco {
40
41
class Foundation_API ThreadImpl
42
{
43
public:
44
  using TIDImpl = pthread_t;
45
  using Callable = void (*)(void *);
46
47
  enum Priority
48
  {
49
    PRIO_LOWEST_IMPL,
50
    PRIO_LOW_IMPL,
51
    PRIO_NORMAL_IMPL,
52
    PRIO_HIGH_IMPL,
53
    PRIO_HIGHEST_IMPL
54
  };
55
56
  enum Policy
57
  {
58
    POLICY_DEFAULT_IMPL = SCHED_OTHER
59
  };
60
61
  ThreadImpl();
62
  ~ThreadImpl();
63
64
  [[nodiscard]] TIDImpl tidImpl() const;
65
  void setNameImpl(const std::string& threadName);
66
  [[nodiscard]] std::string getNameImpl() const;
67
#ifndef POCO_NO_THREADNAME
68
  [[nodiscard]] std::string getOSThreadNameImpl();
69
    /// Returns the thread's name, expressed as an operating system
70
    /// specific name value. Return empty string if thread is not running.
71
    /// For test used only.
72
#endif
73
  void setPriorityImpl(int prio);
74
  [[nodiscard]] int getPriorityImpl() const;
75
  void setOSPriorityImpl(int prio, int policy = SCHED_OTHER);
76
  [[nodiscard]] int getOSPriorityImpl() const;
77
  [[nodiscard]] static int getMinOSPriorityImpl(int policy);
78
  [[nodiscard]] static int getMaxOSPriorityImpl(int policy);
79
  void setStackSizeImpl(int size);
80
  [[nodiscard]] int getStackSizeImpl() const;
81
  void setSignalMaskImpl(uint32_t sigMask);
82
  void startImpl(SharedPtr<Runnable> pTarget);
83
  void joinImpl();
84
  bool joinImpl(long milliseconds);
85
  [[nodiscard]] bool isRunningImpl() const;
86
  static void yieldImpl();
87
  [[nodiscard]] static ThreadImpl* currentImpl();
88
  [[nodiscard]] static TIDImpl currentTidImpl();
89
  [[nodiscard]] static long currentOsTidImpl();
90
#ifndef POCO_NO_THREADNAME
91
  static void setCurrentNameImpl(const std::string& name);
92
  [[nodiscard]] static std::string getCurrentNameImpl();
93
#endif
94
  bool setAffinityImpl(int coreID);
95
  [[nodiscard]] int getAffinityImpl() const;
96
97
protected:
98
  [[nodiscard]] static void* runnableEntry(void* pThread);
99
  [[nodiscard]] static int mapPrio(int prio, int policy = SCHED_OTHER);
100
  [[nodiscard]] static int reverseMapPrio(int osPrio, int policy = SCHED_OTHER);
101
102
private:
103
  class CurrentThreadHolder
104
  {
105
  public:
106
    CurrentThreadHolder()
107
0
    {
108
0
      if (pthread_key_create(&_key, nullptr))
109
0
        throw SystemException("cannot allocate thread context key");
110
0
    }
111
    ~CurrentThreadHolder()
112
0
    {
113
0
      pthread_key_delete(_key);
114
0
    }
115
    [[nodiscard]] ThreadImpl* get() const
116
0
    {
117
0
      return reinterpret_cast<ThreadImpl*>(pthread_getspecific(_key));
118
0
    }
119
    void set(ThreadImpl* pThread)
120
0
    {
121
0
      pthread_setspecific(_key, pThread);
122
0
    }
123
124
  private:
125
    pthread_key_t _key;
126
  };
127
128
  struct ThreadData: public RefCountedObject
129
  {
130
    ThreadData():
131
      thread{},
132
      prio(PRIO_NORMAL_IMPL),
133
      osPrio(),
134
      policy(SCHED_OTHER),
135
      done(Event::EVENT_MANUALRESET),
136
      stackSize(POCO_THREAD_STACK_SIZE),
137
      started(false),
138
      joined(false)
139
0
    {
140
0
    #if defined(POCO_VXWORKS)
141
0
      // This workaround is for VxWorks 5.x where
142
0
      // pthread_init() won't properly initialize the thread.
143
0
      std::memset(&thread, 0, sizeof(thread));
144
0
    #endif
145
0
    }
146
147
    SharedPtr<Runnable> pRunnableTarget;
148
    pthread_t     thread;
149
    int           prio;
150
    int           osPrio;
151
    int           policy;
152
    Event         done;
153
    std::size_t   stackSize;
154
    std::atomic<bool> started;
155
    std::atomic<bool> joined;
156
    std::string   name;
157
    int           affinity;
158
    mutable FastMutex mutex;
159
  };
160
161
  AutoPtr<ThreadData> _pData;
162
  static CurrentThreadHolder _currentThreadHolder;
163
164
#if defined(POCO_OS_FAMILY_UNIX) && !defined(POCO_VXWORKS)
165
  SignalHandler::JumpBufferVec _jumpBufferVec;
166
  friend class SignalHandler;
167
#endif
168
};
169
170
171
//
172
// inlines
173
//
174
inline int ThreadImpl::getPriorityImpl() const
175
0
{
176
0
  return _pData->prio;
177
0
}
178
179
180
inline int ThreadImpl::getOSPriorityImpl() const
181
0
{
182
0
  return _pData->osPrio;
183
0
}
184
185
186
inline bool ThreadImpl::isRunningImpl() const
187
0
{
188
0
  FastMutex::ScopedLock l(_pData->mutex);
189
0
  return !_pData->pRunnableTarget.isNull();
190
0
}
191
192
193
inline void ThreadImpl::yieldImpl()
194
0
{
195
0
  sched_yield();
196
0
}
197
198
199
inline int ThreadImpl::getStackSizeImpl() const
200
0
{
201
0
  return static_cast<int>(_pData->stackSize);
202
0
}
203
204
205
inline ThreadImpl::TIDImpl ThreadImpl::tidImpl() const
206
0
{
207
0
  return _pData->thread;
208
0
}
209
210
211
} // namespace Poco
212
213
214
#endif // Foundation_Thread_POSIX_INCLUDED