thread.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #pragma once
  2. /// This code should not be used directly unless you really understand what you do.
  3. /// If you need threads, use thread pool functionality in <util/thread/factory.h>
  4. /// @see SystemThreadFactory()
  5. #include <util/generic/ptr.h>
  6. #include <util/generic/string.h>
  7. #include "defaults.h"
  8. #include "progname.h"
  9. bool SetHighestThreadPriority();
  10. bool SetLowestThreadPriority();
  11. class TThread {
  12. template <typename Callable>
  13. struct TCallableParams;
  14. struct TPrivateCtor {};
  15. public:
  16. using TThreadProc = void* (*)(void*);
  17. using TId = size_t;
  18. struct TParams {
  19. TThreadProc Proc;
  20. void* Data;
  21. size_t StackSize;
  22. void* StackPointer;
  23. // See comments for `SetCurrentThreadName`
  24. TString Name = GetProgramName();
  25. inline TParams()
  26. : Proc(nullptr)
  27. , Data(nullptr)
  28. , StackSize(0)
  29. , StackPointer(nullptr)
  30. {
  31. }
  32. inline TParams(TThreadProc proc, void* data)
  33. : Proc(proc)
  34. , Data(data)
  35. , StackSize(0)
  36. , StackPointer(nullptr)
  37. {
  38. }
  39. inline TParams(TThreadProc proc, void* data, size_t stackSize)
  40. : Proc(proc)
  41. , Data(data)
  42. , StackSize(stackSize)
  43. , StackPointer(nullptr)
  44. {
  45. }
  46. inline TParams& SetName(const TString& name) noexcept {
  47. Name = name;
  48. return *this;
  49. }
  50. inline TParams& SetStackSize(size_t size) noexcept {
  51. StackSize = size;
  52. return *this;
  53. }
  54. inline TParams& SetStackPointer(void* ptr) noexcept {
  55. StackPointer = ptr;
  56. return *this;
  57. }
  58. };
  59. TThread(const TParams& params);
  60. TThread(TThreadProc threadProc, void* param);
  61. template <typename Callable>
  62. TThread(Callable&& callable)
  63. : TThread(TPrivateCtor{},
  64. MakeHolder<TCallableParams<Callable>>(std::forward<Callable>(callable)))
  65. {
  66. }
  67. TThread(TParams&& params)
  68. : TThread((const TParams&)params)
  69. {
  70. }
  71. TThread(TParams& params)
  72. : TThread((const TParams&)params)
  73. {
  74. }
  75. ~TThread();
  76. void Start();
  77. void* Join();
  78. void Detach();
  79. bool Running() const noexcept;
  80. TId Id() const noexcept;
  81. static TId ImpossibleThreadId() noexcept;
  82. static TId CurrentThreadId() noexcept;
  83. /*
  84. * Returns numeric thread id, as visible in e. g. htop.
  85. * Consider using this value for logging.
  86. */
  87. static TId CurrentThreadNumericId() noexcept;
  88. // NOTE: Content of `name` will be copied.
  89. //
  90. // NOTE: On Linux thread name is limited to 15 symbols which is probably the smallest one among
  91. // all platforms. If you provide a name longer than 15 symbols it will be cut. So if you expect
  92. // `CurrentThreadName` to return the same name as `name` make sure it's not longer than 15
  93. // symbols.
  94. static void SetCurrentThreadName(const char* name);
  95. // NOTE: Will return empty string where CanGetCurrentThreadName() returns false.
  96. static TString CurrentThreadName();
  97. // NOTE: Depends on a platform version.
  98. // Will return true for Darwin, Linux or fresh Windows 10.
  99. static bool CanGetCurrentThreadName();
  100. private:
  101. struct TCallableBase {
  102. virtual ~TCallableBase() = default;
  103. virtual void run() = 0;
  104. static void* ThreadWorker(void* arg) {
  105. static_cast<TCallableBase*>(arg)->run();
  106. return nullptr;
  107. }
  108. };
  109. template <typename Callable>
  110. struct TCallableParams: public TCallableBase {
  111. TCallableParams(Callable&& callable)
  112. : Callable_(std::forward<Callable>(callable))
  113. {
  114. }
  115. Callable Callable_;
  116. void run() override {
  117. Callable_();
  118. }
  119. };
  120. TThread(TPrivateCtor, THolder<TCallableBase> callable);
  121. private:
  122. class TImpl;
  123. THolder<TImpl> Impl_;
  124. };
  125. class ISimpleThread: public TThread {
  126. public:
  127. ISimpleThread(size_t stackSize = 0);
  128. virtual ~ISimpleThread() = default;
  129. virtual void* ThreadProc() = 0;
  130. };
  131. struct TCurrentThreadLimits {
  132. TCurrentThreadLimits() noexcept;
  133. const void* StackBegin;
  134. size_t StackLength;
  135. };