thread.h 4.1 KB

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