15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/atomic_sequence_num.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/simple_thread.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SetIntRunner : public DelegateSimpleThread::Delegate { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { } 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SetIntRunner() { } 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr_ = val_; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* ptr_; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int val_; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WaitEventRunner : public DelegateSimpleThread::Delegate { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit WaitEventRunner(WaitableEvent* event) : event_(event) { } 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~WaitEventRunner() { } 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(event_->IsSignaled()); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_->Signal(); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(event_->IsSignaled()); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* event_; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SeqRunner : public DelegateSimpleThread::Delegate { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) seq_->GetNext(); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtomicSequenceNumber* seq_; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We count up on a sequence number, firing on the event when we've hit our 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expected amount, otherwise we wait on the event. This will ensure that we 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have all threads outstanding until we hit our expected thread pool size. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VerifyPoolRunner : public DelegateSimpleThread::Delegate { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyPoolRunner(AtomicSequenceNumber* seq, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int total, WaitableEvent* event) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : seq_(seq), total_(total), event_(event) { } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (seq_->GetNext() == total_) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_->Signal(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_->Wait(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtomicSequenceNumber* seq_; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int total_; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* event_; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(SimpleThreadTest, CreateAndJoin) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int stack_int = 0; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetIntRunner runner(&stack_int, 7); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, stack_int); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DelegateSimpleThread thread(&runner, "int_setter"); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(thread.HasBeenStarted()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(thread.HasBeenJoined()); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, stack_int); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.Start(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(thread.HasBeenStarted()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(thread.HasBeenJoined()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.Join(); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(thread.HasBeenStarted()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(thread.HasBeenJoined()); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(7, stack_int); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(SimpleThreadTest, WaitForEvent) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a thread, and wait for it to signal us. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent event(true, false); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitEventRunner runner(&event); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DelegateSimpleThread thread(&runner, "event_waiter"); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(event.IsSignaled()); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.Start(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.Wait(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(event.IsSignaled()); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.Join(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(SimpleThreadTest, NamedWithOptions) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent event(true, false); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitEventRunner runner(&event); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimpleThread::Options options; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DelegateSimpleThread thread(&runner, "event_waiter", options); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(thread.name_prefix(), "event_waiter"); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(event.IsSignaled()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.Start(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(thread.name_prefix(), "event_waiter"); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(thread.name(), 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string("event_waiter/") + IntToString(thread.tid())); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.Wait(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(event.IsSignaled()); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.Join(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We keep the name and tid, even after the thread is gone. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(thread.name_prefix(), "event_waiter"); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(thread.name(), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string("event_waiter/") + IntToString(thread.tid())); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(SimpleThreadTest, ThreadPool) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtomicSequenceNumber seq; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SeqRunner runner(&seq); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DelegateSimpleThreadPool pool("seq_runner", 10); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add work before we're running. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool.AddWork(&runner, 300); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(seq.GetNext(), 0); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool.Start(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add work while we're running. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool.AddWork(&runner, 300); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool.JoinAll(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(seq.GetNext(), 601); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can reuse our pool. Verify that all 10 threads can actually run in 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parallel, so this test will only pass if there are actually 10 threads. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtomicSequenceNumber seq2; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent event(true, false); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Changing 9 to 10, for example, would cause us JoinAll() to never return. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyPoolRunner verifier(&seq2, 9, &event); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool.Start(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool.AddWork(&verifier, 10); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool.JoinAll(); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(seq2.GetNext(), 10); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 171