Reland "Refactor the PlatformThread API."
This reverts commit 793bac569fdf1be16cbf24d7871d20d00bbec81b.
Reason for revert: rare compilation error fixed
Original change's description:
> Revert "Refactor the PlatformThread API."
>
> This reverts commit c89fdd716c4c8af608017c76f75bf27e4c3d602e.
>
> Reason for revert: Causes rare compilation error on win-libfuzzer-asan trybot.
> See https://ci.chromium.org/p/chromium/builders/try/win-libfuzzer-asan-rel/713745?
>
> Original change's description:
> > Refactor the PlatformThread API.
> >
> > PlatformThread's API is using old style function pointers, causes
> > casting, is unintuitive and forces artificial call sequences, and
> > is additionally possible to misuse in release mode.
> >
> > Fix this by an API face lift:
> > 1. The class is turned into a handle, which can be empty.
> > 2. The only way of getting a non-empty PlatformThread is by calling
> > SpawnJoinable or SpawnDetached, clearly conveying the semantics to the
> > code reader.
> > 3. Handles can be Finalized, which works differently for joinable and
> > detached threads:
> > a) Handles for detached threads are simply closed where applicable.
> > b) Joinable threads are joined before handles are closed.
> > 4. The destructor finalizes handles. No explicit call is needed.
> >
> > Fixed: webrtc:12727
> > Change-Id: Id00a0464edf4fc9e552b6a1fbb5d2e1280e88811
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/215075
> > Commit-Queue: Markus Handell <handellm@webrtc.org>
> > Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> > Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
> > Reviewed-by: Tommi <tommi@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#33923}
>
> # Not skipping CQ checks because original CL landed > 1 day ago.
>
> TBR=handellm@webrtc.org
>
> Bug: webrtc:12727
> Change-Id: Ic0146be8866f6dd3ad9c364fb8646650b8e07419
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/217583
> Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
> Reviewed-by: Markus Handell <handellm@webrtc.org>
> Commit-Queue: Guido Urdaneta <guidou@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#33936}
# Not skipping CQ checks because this is a reland.
Bug: webrtc:12727
Change-Id: Ifd6f44eac72fed84474277a1be03eb84d2f4376e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/217881
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Markus Handell <handellm@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33950}
diff --git a/rtc_base/platform_thread.h b/rtc_base/platform_thread.h
index 35c0e27..11ccfae 100644
--- a/rtc_base/platform_thread.h
+++ b/rtc_base/platform_thread.h
@@ -11,103 +11,101 @@
#ifndef RTC_BASE_PLATFORM_THREAD_H_
#define RTC_BASE_PLATFORM_THREAD_H_
-#ifndef WEBRTC_WIN
-#include <pthread.h>
-#endif
+#include <functional>
#include <string>
#include "absl/strings/string_view.h"
-#include "api/sequence_checker.h"
-#include "rtc_base/constructor_magic.h"
+#include "absl/types/optional.h"
#include "rtc_base/platform_thread_types.h"
namespace rtc {
-// Callback function that the spawned thread will enter once spawned.
-typedef void (*ThreadRunFunction)(void*);
-
-enum ThreadPriority {
-#ifdef WEBRTC_WIN
- kLowPriority = THREAD_PRIORITY_BELOW_NORMAL,
- kNormalPriority = THREAD_PRIORITY_NORMAL,
- kHighPriority = THREAD_PRIORITY_ABOVE_NORMAL,
- kHighestPriority = THREAD_PRIORITY_HIGHEST,
- kRealtimePriority = THREAD_PRIORITY_TIME_CRITICAL
-#else
- kLowPriority = 1,
- kNormalPriority = 2,
- kHighPriority = 3,
- kHighestPriority = 4,
- kRealtimePriority = 5
-#endif
+enum class ThreadPriority {
+ kLow = 1,
+ kNormal,
+ kHigh,
+ kRealtime,
};
struct ThreadAttributes {
- ThreadPriority priority = kNormalPriority;
- bool joinable = true;
-
+ ThreadPriority priority = ThreadPriority::kNormal;
ThreadAttributes& SetPriority(ThreadPriority priority_param) {
priority = priority_param;
return *this;
}
- ThreadAttributes& SetDetached() {
- joinable = false;
- return *this;
- }
};
-// Represents a simple worker thread. The implementation must be assumed
-// to be single threaded, meaning that all methods of the class, must be
-// called from the same thread, including instantiation.
-class PlatformThread {
+// Represents a simple worker thread.
+class PlatformThread final {
public:
- PlatformThread(ThreadRunFunction func,
- void* obj,
- absl::string_view thread_name,
- ThreadAttributes attributes = ThreadAttributes());
+ // Handle is the base platform thread handle.
+#if defined(WEBRTC_WIN)
+ using Handle = HANDLE;
+#else
+ using Handle = pthread_t;
+#endif // defined(WEBRTC_WIN)
+ // This ctor creates the PlatformThread with an unset handle (returning true
+ // in empty()) and is provided for convenience.
+ // TODO(bugs.webrtc.org/12727) Look into if default and move support can be
+ // removed.
+ PlatformThread() = default;
+
+ // Moves |rhs| into this, storing an empty state in |rhs|.
+ // TODO(bugs.webrtc.org/12727) Look into if default and move support can be
+ // removed.
+ PlatformThread(PlatformThread&& rhs);
+
+ // Moves |rhs| into this, storing an empty state in |rhs|.
+ // TODO(bugs.webrtc.org/12727) Look into if default and move support can be
+ // removed.
+ PlatformThread& operator=(PlatformThread&& rhs);
+
+ // For a PlatformThread that's been spawned joinable, the destructor suspends
+ // the calling thread until the created thread exits unless the thread has
+ // already exited.
virtual ~PlatformThread();
- const std::string& name() const { return name_; }
+ // Finalizes any allocated resources.
+ // For a PlatformThread that's been spawned joinable, Finalize() suspends
+ // the calling thread until the created thread exits unless the thread has
+ // already exited.
+ // empty() returns true after completion.
+ void Finalize();
- // Spawns a thread and tries to set thread priority according to the priority
- // from when CreateThread was called.
- // Start can only be called after the constructor or after a call to Stop().
- void Start();
+ // Returns true if default constructed, moved from, or Finalize()ed.
+ bool empty() const { return !handle_.has_value(); }
- bool IsRunning() const;
+ // Creates a started joinable thread which will be joined when the returned
+ // PlatformThread destructs or Finalize() is called.
+ static PlatformThread SpawnJoinable(
+ std::function<void()> thread_function,
+ absl::string_view name,
+ ThreadAttributes attributes = ThreadAttributes());
- // Returns an identifier for the worker thread that can be used to do
- // thread checks.
- PlatformThreadRef GetThreadRef() const;
+ // Creates a started detached thread. The caller has to use external
+ // synchronization as nothing is provided by the PlatformThread construct.
+ static PlatformThread SpawnDetached(
+ std::function<void()> thread_function,
+ absl::string_view name,
+ ThreadAttributes attributes = ThreadAttributes());
- // Stop() prepares the PlatformThread for destruction or another call to
- // Start(). For a PlatformThread that's been created with
- // ThreadAttributes::joinable true (the default), Stop() suspends the calling
- // thread until the created thread exits unless the thread has already exited.
- // Stop() can only be called after calling Start().
- void Stop();
+ // Returns the base platform thread handle of this thread.
+ absl::optional<Handle> GetHandle() const;
- protected:
#if defined(WEBRTC_WIN)
- // Exposed to derived classes to allow for special cases specific to Windows.
+ // Queue a Windows APC function that runs when the thread is alertable.
bool QueueAPC(PAPCFUNC apc_function, ULONG_PTR data);
#endif
private:
- ThreadRunFunction const run_function_ = nullptr;
- const ThreadAttributes attributes_;
- void* const obj_;
- // TODO(pbos): Make sure call sites use string literals and update to a const
- // char* instead of a std::string.
- const std::string name_;
- webrtc::SequenceChecker thread_checker_;
-#if defined(WEBRTC_WIN)
- HANDLE thread_ = nullptr;
- DWORD thread_id_ = 0;
-#else
- pthread_t thread_ = 0;
-#endif // defined(WEBRTC_WIN)
- RTC_DISALLOW_COPY_AND_ASSIGN(PlatformThread);
+ PlatformThread(Handle handle, bool joinable);
+ static PlatformThread SpawnThread(std::function<void()> thread_function,
+ absl::string_view name,
+ ThreadAttributes attributes,
+ bool joinable);
+
+ absl::optional<Handle> handle_;
+ bool joinable_ = false;
};
} // namespace rtc