1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc. All rights reserved. 3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/ 4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met: 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions of source code must retain the above copyright 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer. 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions in binary form must reproduce the above 12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer 13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the 14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution. 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Neither the name of Google Inc. nor the names of its 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission. 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda) 32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <windows.h> 35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <unistd.h> 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <pthread.h> 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/once.h> 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/testing/googletest.h> 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <gtest/gtest.h> 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google { 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf { 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace { 47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass OnceInitTest : public testing::Test { 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville protected: 50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void SetUp() { 51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville state_ = INIT_NOT_STARTED; 52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville current_test_ = this; 53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Since ProtobufOnceType is only allowed to be allocated in static storage, 56d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // each test must use a different pair of ProtobufOnceType objects which it 57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // must declare itself. 58d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville void SetOnces(ProtobufOnceType* once, ProtobufOnceType* recursive_once) { 59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville once_ = once; 60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville recursive_once_ = recursive_once; 61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void InitOnce() { 64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GoogleOnceInit(once_, &InitStatic); 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void InitRecursiveOnce() { 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GoogleOnceInit(recursive_once_, &InitRecursiveStatic); 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void BlockInit() { init_blocker_.Lock(); } 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void UnblockInit() { init_blocker_.Unlock(); } 72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville class TestThread { 74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public: 75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville TestThread(Closure* callback) 76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville : done_(false), joined_(false), callback_(callback) { 77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville thread_ = CreateThread(NULL, 0, &Start, this, 0, NULL); 79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville pthread_create(&thread_, NULL, &Start, this); 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ~TestThread() { 84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!joined_) Join(); 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool IsDone() { 88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MutexLock lock(&done_mutex_); 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return done_; 90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void Join() { 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville joined_ = true; 93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville WaitForSingleObject(thread_, INFINITE); 95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville CloseHandle(thread_); 96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville pthread_join(thread_, NULL); 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private: 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville HANDLE thread_; 104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville pthread_t thread_; 106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Mutex done_mutex_; 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool done_; 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool joined_; 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Closure* callback_; 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static DWORD WINAPI Start(LPVOID arg) { 115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static void* Start(void* arg) { 117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville reinterpret_cast<TestThread*>(arg)->Run(); 119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return 0; 120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void Run() { 123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville callback_->Run(); 124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MutexLock lock(&done_mutex_); 125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville done_ = true; 126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville }; 128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville TestThread* RunInitOnceInNewThread() { 130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return new TestThread(NewCallback(this, &OnceInitTest::InitOnce)); 131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville TestThread* RunInitRecursiveOnceInNewThread() { 133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return new TestThread(NewCallback(this, &OnceInitTest::InitRecursiveOnce)); 134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enum State { 137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville INIT_NOT_STARTED, 138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville INIT_STARTED, 139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville INIT_DONE 140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville }; 141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville State CurrentState() { 142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MutexLock lock(&mutex_); 143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return state_; 144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void WaitABit() { 147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Sleep(1000); 149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville sleep(1); 151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private: 155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Mutex mutex_; 156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Mutex init_blocker_; 157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville State state_; 158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ProtobufOnceType* once_; 159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ProtobufOnceType* recursive_once_; 160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void Init() { 162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MutexLock lock(&mutex_); 163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_NOT_STARTED, state_); 164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville state_ = INIT_STARTED; 165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville mutex_.Unlock(); 166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville init_blocker_.Lock(); 167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville init_blocker_.Unlock(); 168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville mutex_.Lock(); 169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville state_ = INIT_DONE; 170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static OnceInitTest* current_test_; 173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static void InitStatic() { current_test_->Init(); } 174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static void InitRecursiveStatic() { current_test_->InitOnce(); } 175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleOnceInitTest* OnceInitTest::current_test_ = NULL; 178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGOOGLE_PROTOBUF_DECLARE_ONCE(simple_once); 180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(OnceInitTest, Simple) { 182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetOnces(&simple_once, NULL); 183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); 185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville InitOnce(); 186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_DONE, CurrentState()); 187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Calling again has no effect. 189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville InitOnce(); 190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_DONE, CurrentState()); 191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once1); 194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once2); 195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(OnceInitTest, Recursive) { 197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetOnces(&recursive_once1, &recursive_once2); 198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); 200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville InitRecursiveOnce(); 201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_DONE, CurrentState()); 202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_once); 205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(OnceInitTest, MultipleThreads) { 207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetOnces(&multiple_threads_once, NULL); 208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scoped_ptr<TestThread> threads[4]; 210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); 211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < 4; i++) { 212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville threads[i].reset(RunInitOnceInNewThread()); 213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < 4; i++) { 215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville threads[i]->Join(); 216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_DONE, CurrentState()); 218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once1); 221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once2); 222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(OnceInitTest, MultipleThreadsBlocked) { 224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetOnces(&multiple_threads_blocked_once1, &multiple_threads_blocked_once2); 225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scoped_ptr<TestThread> threads[8]; 227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); 228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville BlockInit(); 230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < 4; i++) { 231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville threads[i].reset(RunInitOnceInNewThread()); 232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 4; i < 8; i++) { 234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville threads[i].reset(RunInitRecursiveOnceInNewThread()); 235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville WaitABit(); 238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We should now have one thread blocked inside Init(), four blocked waiting 240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // for Init() to complete, and three blocked waiting for InitRecursive() to 241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // complete. 242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_STARTED, CurrentState()); 243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville UnblockInit(); 244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < 8; i++) { 246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville threads[i]->Join(); 247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_EQ(INIT_DONE, CurrentState()); 249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // anonymous namespace 252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace protobuf 253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace google 254