Update PlatformThread to support a couple of new properties.
- name(): Returns the name of the thread (useful for debugging). - GetThreadRef(): Returns the ID of the worker thread (also useful for debugging). - QueueApc(): This is a Windows-only, protected function that allows derived classes on Windows to queue APCs to the worker thread. NOTRY=true (using notry since the patch has already passed the trybots and the cq is currently stalled) Review URL: https://codereview.webrtc.org/1908373002 Cr-Commit-Position: refs/heads/master@{#12472}
This commit is contained in:
parent
d98cf1ff1e
commit
845afa8a02
@ -99,7 +99,8 @@ PlatformThread::PlatformThread(ThreadRunFunction func,
|
||||
name_(thread_name ? thread_name : "webrtc"),
|
||||
#if defined(WEBRTC_WIN)
|
||||
stop_(false),
|
||||
thread_(NULL) {
|
||||
thread_(NULL),
|
||||
thread_id_(0) {
|
||||
#else
|
||||
stop_event_(false, false),
|
||||
thread_(0) {
|
||||
@ -112,6 +113,7 @@ PlatformThread::~PlatformThread() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
#if defined(WEBRTC_WIN)
|
||||
RTC_DCHECK(!thread_);
|
||||
RTC_DCHECK(!thread_id_);
|
||||
#endif // defined(WEBRTC_WIN)
|
||||
}
|
||||
|
||||
@ -136,10 +138,10 @@ void PlatformThread::Start() {
|
||||
// See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION.
|
||||
// Set the reserved stack stack size to 1M, which is the default on Windows
|
||||
// and Linux.
|
||||
DWORD thread_id;
|
||||
thread_ = ::CreateThread(NULL, 1024 * 1024, &StartThread, this,
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id);
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id_);
|
||||
RTC_CHECK(thread_) << "CreateThread failed";
|
||||
RTC_DCHECK(thread_id_);
|
||||
#else
|
||||
ThreadAttributes attr;
|
||||
// Set the stack stack size to 1M.
|
||||
@ -157,6 +159,14 @@ bool PlatformThread::IsRunning() const {
|
||||
#endif // defined(WEBRTC_WIN)
|
||||
}
|
||||
|
||||
PlatformThreadRef PlatformThread::GetThreadRef() const {
|
||||
#if defined(WEBRTC_WIN)
|
||||
return thread_id_;
|
||||
#else
|
||||
return thread_;
|
||||
#endif // defined(WEBRTC_WIN)
|
||||
}
|
||||
|
||||
void PlatformThread::Stop() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
if (!IsRunning())
|
||||
@ -164,10 +174,13 @@ void PlatformThread::Stop() {
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
// Set stop_ to |true| on the worker thread.
|
||||
QueueUserAPC(&RaiseFlag, thread_, reinterpret_cast<ULONG_PTR>(&stop_));
|
||||
bool queued = QueueAPC(&RaiseFlag, reinterpret_cast<ULONG_PTR>(&stop_));
|
||||
// Queuing the APC can fail if the thread is being terminated.
|
||||
RTC_CHECK(queued || GetLastError() == ERROR_GEN_FAILURE);
|
||||
WaitForSingleObject(thread_, INFINITE);
|
||||
CloseHandle(thread_);
|
||||
thread_ = nullptr;
|
||||
thread_id_ = 0;
|
||||
#else
|
||||
stop_event_.Set();
|
||||
RTC_CHECK_EQ(0, pthread_join(thread_, nullptr));
|
||||
@ -247,4 +260,13 @@ bool PlatformThread::SetPriority(ThreadPriority priority) {
|
||||
#endif // defined(WEBRTC_WIN)
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
bool PlatformThread::QueueAPC(PAPCFUNC function, ULONG_PTR data) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(IsRunning());
|
||||
|
||||
return QueueUserAPC(function, thread_, data) != FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
@ -59,18 +59,30 @@ class PlatformThread {
|
||||
PlatformThread(ThreadRunFunction func, void* obj, const char* thread_name);
|
||||
virtual ~PlatformThread();
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
|
||||
// Spawns a thread and tries to set thread priority according to the priority
|
||||
// from when CreateThread was called.
|
||||
void Start();
|
||||
|
||||
bool IsRunning() const;
|
||||
|
||||
// Returns an identifier for the worker thread that can be used to do
|
||||
// thread checks.
|
||||
PlatformThreadRef GetThreadRef() const;
|
||||
|
||||
// Stops (joins) the spawned thread.
|
||||
void Stop();
|
||||
|
||||
// Set the priority of the thread. Must be called when thread is running.
|
||||
bool SetPriority(ThreadPriority priority);
|
||||
|
||||
protected:
|
||||
#if defined(WEBRTC_WIN)
|
||||
// Exposed to derived classes to allow for special cases specific to Windows.
|
||||
bool QueueAPC(PAPCFUNC apc_function, ULONG_PTR data);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void Run();
|
||||
|
||||
@ -85,6 +97,7 @@ class PlatformThread {
|
||||
|
||||
bool stop_;
|
||||
HANDLE thread_;
|
||||
DWORD thread_id_;
|
||||
#else
|
||||
static void* StartThread(void* param);
|
||||
|
||||
|
||||
@ -14,31 +14,47 @@
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/system_wrappers/include/sleep.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace rtc {
|
||||
namespace {
|
||||
// Function that does nothing, and reports success.
|
||||
bool NullRunFunction(void* obj) {
|
||||
SleepMs(0); // Hand over timeslice, prevents busy looping.
|
||||
webrtc::SleepMs(0); // Hand over timeslice, prevents busy looping.
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(PlatformThreadTest, StartStop) {
|
||||
rtc::PlatformThread thread(&NullRunFunction, nullptr, "PlatformThreadTest");
|
||||
thread.Start();
|
||||
thread.Stop();
|
||||
}
|
||||
|
||||
// Function that sets a boolean.
|
||||
bool SetFlagRunFunction(void* obj) {
|
||||
bool* obj_as_bool = static_cast<bool*>(obj);
|
||||
*obj_as_bool = true;
|
||||
SleepMs(0); // Hand over timeslice, prevents busy looping.
|
||||
webrtc::SleepMs(0); // Hand over timeslice, prevents busy looping.
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(PlatformThreadTest, StartStop) {
|
||||
PlatformThread thread(&NullRunFunction, nullptr, "PlatformThreadTest");
|
||||
EXPECT_TRUE(thread.name() == "PlatformThreadTest");
|
||||
EXPECT_TRUE(thread.GetThreadRef() == 0);
|
||||
thread.Start();
|
||||
EXPECT_TRUE(thread.GetThreadRef() != 0);
|
||||
thread.Stop();
|
||||
EXPECT_TRUE(thread.GetThreadRef() == 0);
|
||||
}
|
||||
|
||||
TEST(PlatformThreadTest, StartStop2) {
|
||||
PlatformThread thread1(&NullRunFunction, nullptr, "PlatformThreadTest1");
|
||||
PlatformThread thread2(&NullRunFunction, nullptr, "PlatformThreadTest2");
|
||||
EXPECT_TRUE(thread1.GetThreadRef() == thread2.GetThreadRef());
|
||||
thread1.Start();
|
||||
thread2.Start();
|
||||
EXPECT_TRUE(thread1.GetThreadRef() != thread2.GetThreadRef());
|
||||
thread2.Stop();
|
||||
thread1.Stop();
|
||||
}
|
||||
|
||||
TEST(PlatformThreadTest, RunFunctionIsCalled) {
|
||||
bool flag = false;
|
||||
rtc::PlatformThread thread(&SetFlagRunFunction, &flag, "RunFunctionIsCalled");
|
||||
PlatformThread thread(&SetFlagRunFunction, &flag, "RunFunctionIsCalled");
|
||||
thread.Start();
|
||||
|
||||
// At this point, the flag may be either true or false.
|
||||
@ -47,5 +63,4 @@ TEST(PlatformThreadTest, RunFunctionIsCalled) {
|
||||
// We expect the thread to have run at least once.
|
||||
EXPECT_TRUE(flag);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
} // rtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user