Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(748)

Unified Diff: base/threading/simple_thread_unittest.cc

Issue 2204333003: Add joinable option to SimpleThread::Options as was just done for Thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@b1_nonjoinable_thread
Patch Set: fix TSan and ASan Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/threading/simple_thread.cc ('k') | content/renderer/categorized_worker_pool.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/threading/simple_thread_unittest.cc
diff --git a/base/threading/simple_thread_unittest.cc b/base/threading/simple_thread_unittest.cc
index 14dd4591f1819d8e505911cd9f4cb9fb09cd54f2..97ebf8042e4a7472a2ee0175b31aabe649037911 100644
--- a/base/threading/simple_thread_unittest.cc
+++ b/base/threading/simple_thread_unittest.cc
@@ -2,9 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
+
#include "base/atomic_sequence_num.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/gtest_util.h"
#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -17,11 +21,49 @@ class SetIntRunner : public DelegateSimpleThread::Delegate {
SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { }
~SetIntRunner() override {}
+ private:
void Run() override { *ptr_ = val_; }
- private:
int* ptr_;
int val_;
+
+ DISALLOW_COPY_AND_ASSIGN(SetIntRunner);
+};
+
+// Signals |started_| when Run() is invoked and waits until |released_| is
+// signaled to return, signaling |done_| before doing so. Useful for tests that
+// care to control Run()'s flow.
+class ControlledRunner : public DelegateSimpleThread::Delegate {
+ public:
+ ControlledRunner()
+ : started_(WaitableEvent::ResetPolicy::MANUAL,
+ WaitableEvent::InitialState::NOT_SIGNALED),
+ released_(WaitableEvent::ResetPolicy::MANUAL,
+ WaitableEvent::InitialState::NOT_SIGNALED),
+ done_(WaitableEvent::ResetPolicy::MANUAL,
+ WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+ ~ControlledRunner() override { ReleaseAndWaitUntilDone(); }
+
+ void WaitUntilStarted() { started_.Wait(); }
+
+ void ReleaseAndWaitUntilDone() {
+ released_.Signal();
+ done_.Wait();
+ }
+
+ private:
+ void Run() override {
+ started_.Signal();
+ released_.Wait();
+ done_.Signal();
+ }
+
+ WaitableEvent started_;
+ WaitableEvent released_;
+ WaitableEvent done_;
+
+ DISALLOW_COPY_AND_ASSIGN(ControlledRunner);
};
class WaitEventRunner : public DelegateSimpleThread::Delegate {
@@ -29,22 +71,28 @@ class WaitEventRunner : public DelegateSimpleThread::Delegate {
explicit WaitEventRunner(WaitableEvent* event) : event_(event) { }
~WaitEventRunner() override {}
+ private:
void Run() override {
EXPECT_FALSE(event_->IsSignaled());
event_->Signal();
EXPECT_TRUE(event_->IsSignaled());
}
- private:
+
WaitableEvent* event_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaitEventRunner);
};
class SeqRunner : public DelegateSimpleThread::Delegate {
public:
explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { }
- void Run() override { seq_->GetNext(); }
private:
+ void Run() override { seq_->GetNext(); }
+
AtomicSequenceNumber* seq_;
+
+ DISALLOW_COPY_AND_ASSIGN(SeqRunner);
};
// We count up on a sequence number, firing on the event when we've hit our
@@ -56,6 +104,7 @@ class VerifyPoolRunner : public DelegateSimpleThread::Delegate {
int total, WaitableEvent* event)
: seq_(seq), total_(total), event_(event) { }
+ private:
void Run() override {
if (seq_->GetNext() == total_) {
event_->Signal();
@@ -64,10 +113,11 @@ class VerifyPoolRunner : public DelegateSimpleThread::Delegate {
}
}
- private:
AtomicSequenceNumber* seq_;
int total_;
WaitableEvent* event_;
+
+ DISALLOW_COPY_AND_ASSIGN(VerifyPoolRunner);
};
} // namespace
@@ -133,6 +183,46 @@ TEST(SimpleThreadTest, NamedWithOptions) {
std::string("event_waiter/") + IntToString(thread.tid()));
}
+TEST(SimpleThreadTest, NonJoinableStartAndDieOnJoin) {
+ ControlledRunner runner;
+
+ SimpleThread::Options options;
+ options.joinable = false;
+ DelegateSimpleThread thread(&runner, "non_joinable", options);
+
+ EXPECT_FALSE(thread.HasBeenStarted());
+ thread.Start();
+ EXPECT_TRUE(thread.HasBeenStarted());
+
+ // Note: this is not quite the same as |thread.HasBeenStarted()| which
+ // represents ThreadMain() getting ready to invoke Run() whereas
+ // |runner.WaitUntilStarted()| ensures Run() was actually invoked.
+ runner.WaitUntilStarted();
+
+ EXPECT_FALSE(thread.HasBeenJoined());
+ EXPECT_DCHECK_DEATH({ thread.Join(); });
+}
+
+TEST(SimpleThreadTest, NonJoinableInactiveDelegateDestructionIsOkay) {
+ std::unique_ptr<ControlledRunner> runner(new ControlledRunner);
+
+ SimpleThread::Options options;
+ options.joinable = false;
+ std::unique_ptr<DelegateSimpleThread> thread(
+ new DelegateSimpleThread(runner.get(), "non_joinable", options));
+
+ thread->Start();
+ runner->WaitUntilStarted();
+
+ // Deleting a non-joinable SimpleThread after Run() was invoked is okay.
+ thread.reset();
+
+ runner->WaitUntilStarted();
+ runner->ReleaseAndWaitUntilDone();
+ // It should be safe to destroy a Delegate after its Run() method completed.
+ runner.reset();
+}
+
TEST(SimpleThreadTest, ThreadPool) {
AtomicSequenceNumber seq;
SeqRunner runner(&seq);
« no previous file with comments | « base/threading/simple_thread.cc ('k') | content/renderer/categorized_worker_pool.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698