simple_thread_unittest.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "butil/atomic_sequence_num.h"
  5. #include "butil/strings/string_number_conversions.h"
  6. #include "butil/synchronization/waitable_event.h"
  7. #include "butil/threading/simple_thread.h"
  8. #include <gtest/gtest.h>
  9. namespace butil {
  10. namespace {
  11. class SetIntRunner : public DelegateSimpleThread::Delegate {
  12. public:
  13. SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { }
  14. virtual ~SetIntRunner() { }
  15. virtual void Run() OVERRIDE {
  16. *ptr_ = val_;
  17. }
  18. private:
  19. int* ptr_;
  20. int val_;
  21. };
  22. class WaitEventRunner : public DelegateSimpleThread::Delegate {
  23. public:
  24. explicit WaitEventRunner(WaitableEvent* event) : event_(event) { }
  25. virtual ~WaitEventRunner() { }
  26. virtual void Run() OVERRIDE {
  27. EXPECT_FALSE(event_->IsSignaled());
  28. event_->Signal();
  29. EXPECT_TRUE(event_->IsSignaled());
  30. }
  31. private:
  32. WaitableEvent* event_;
  33. };
  34. class SeqRunner : public DelegateSimpleThread::Delegate {
  35. public:
  36. explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { }
  37. virtual void Run() OVERRIDE {
  38. seq_->GetNext();
  39. }
  40. private:
  41. AtomicSequenceNumber* seq_;
  42. };
  43. // We count up on a sequence number, firing on the event when we've hit our
  44. // expected amount, otherwise we wait on the event. This will ensure that we
  45. // have all threads outstanding until we hit our expected thread pool size.
  46. class VerifyPoolRunner : public DelegateSimpleThread::Delegate {
  47. public:
  48. VerifyPoolRunner(AtomicSequenceNumber* seq,
  49. int total, WaitableEvent* event)
  50. : seq_(seq), total_(total), event_(event) { }
  51. virtual void Run() OVERRIDE {
  52. if (seq_->GetNext() == total_) {
  53. event_->Signal();
  54. } else {
  55. event_->Wait();
  56. }
  57. }
  58. private:
  59. AtomicSequenceNumber* seq_;
  60. int total_;
  61. WaitableEvent* event_;
  62. };
  63. } // namespace
  64. TEST(SimpleThreadTest, CreateAndJoin) {
  65. int stack_int = 0;
  66. SetIntRunner runner(&stack_int, 7);
  67. EXPECT_EQ(0, stack_int);
  68. DelegateSimpleThread thread(&runner, "int_setter");
  69. EXPECT_FALSE(thread.HasBeenStarted());
  70. EXPECT_FALSE(thread.HasBeenJoined());
  71. EXPECT_EQ(0, stack_int);
  72. thread.Start();
  73. EXPECT_TRUE(thread.HasBeenStarted());
  74. EXPECT_FALSE(thread.HasBeenJoined());
  75. thread.Join();
  76. EXPECT_TRUE(thread.HasBeenStarted());
  77. EXPECT_TRUE(thread.HasBeenJoined());
  78. EXPECT_EQ(7, stack_int);
  79. }
  80. TEST(SimpleThreadTest, WaitForEvent) {
  81. // Create a thread, and wait for it to signal us.
  82. WaitableEvent event(true, false);
  83. WaitEventRunner runner(&event);
  84. DelegateSimpleThread thread(&runner, "event_waiter");
  85. EXPECT_FALSE(event.IsSignaled());
  86. thread.Start();
  87. event.Wait();
  88. EXPECT_TRUE(event.IsSignaled());
  89. thread.Join();
  90. }
  91. TEST(SimpleThreadTest, NamedWithOptions) {
  92. WaitableEvent event(true, false);
  93. WaitEventRunner runner(&event);
  94. SimpleThread::Options options;
  95. DelegateSimpleThread thread(&runner, "event_waiter", options);
  96. EXPECT_EQ(thread.name_prefix(), "event_waiter");
  97. EXPECT_FALSE(event.IsSignaled());
  98. thread.Start();
  99. EXPECT_EQ(thread.name_prefix(), "event_waiter");
  100. EXPECT_EQ(thread.name(),
  101. std::string("event_waiter/") + IntToString(thread.tid()));
  102. event.Wait();
  103. EXPECT_TRUE(event.IsSignaled());
  104. thread.Join();
  105. // We keep the name and tid, even after the thread is gone.
  106. EXPECT_EQ(thread.name_prefix(), "event_waiter");
  107. EXPECT_EQ(thread.name(),
  108. std::string("event_waiter/") + IntToString(thread.tid()));
  109. }
  110. TEST(SimpleThreadTest, ThreadPool) {
  111. AtomicSequenceNumber seq;
  112. SeqRunner runner(&seq);
  113. DelegateSimpleThreadPool pool("seq_runner", 10);
  114. // Add work before we're running.
  115. pool.AddWork(&runner, 300);
  116. EXPECT_EQ(seq.GetNext(), 0);
  117. pool.Start();
  118. // Add work while we're running.
  119. pool.AddWork(&runner, 300);
  120. pool.JoinAll();
  121. EXPECT_EQ(seq.GetNext(), 601);
  122. // We can reuse our pool. Verify that all 10 threads can actually run in
  123. // parallel, so this test will only pass if there are actually 10 threads.
  124. AtomicSequenceNumber seq2;
  125. WaitableEvent event(true, false);
  126. // Changing 9 to 10, for example, would cause us JoinAll() to never return.
  127. VerifyPoolRunner verifier(&seq2, 9, &event);
  128. pool.Start();
  129. pool.AddWork(&verifier, 10);
  130. pool.JoinAll();
  131. EXPECT_EQ(seq2.GetNext(), 10);
  132. }
  133. } // namespace butil