1 // Copyright (C) 2014 The Android Open Source Project
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "emugl/common/lazy_instance.h"
17 #include "emugl/common/mutex.h"
18 #include "emugl/common/testing/test_thread.h"
20 #include <gtest/gtest.h>
29 int get() const { return mValue; }
30 void set(int value) { mValue = value; }
31 ~Foo() { mValue = 13; }
39 Mutex::AutoLock lock(mMutex);
43 int getValue() const {
44 Mutex::AutoLock lock(mMutex);
53 // NOTE: This introduces a static C++ constructor for this object file,
54 // but that's ok because a LazyInstance<Mutex> should not be used to
55 // test the behaviour of LazyInstance :-)
56 Mutex StaticCounter::mMutex;
57 int StaticCounter::mCounter = 0;
61 TEST(LazyInstance, HasInstance) {
62 LazyInstance<Foo> foo_instance = LAZY_INSTANCE_INIT;
63 EXPECT_FALSE(foo_instance.hasInstance());
64 EXPECT_FALSE(foo_instance.hasInstance());
66 EXPECT_TRUE(foo_instance.hasInstance());
69 TEST(LazyInstance, Simple) {
70 LazyInstance<Foo> foo_instance = LAZY_INSTANCE_INIT;
71 Foo* foo1 = foo_instance.ptr();
73 EXPECT_EQ(42, foo_instance->get());
75 EXPECT_EQ(10, foo_instance->get());
76 EXPECT_EQ(foo1, foo_instance.ptr());
79 // For the following test, launch 1000 threads that each try to get
80 // the instance pointer of a lazy instance. Then verify that they're all
83 // The lazy instance has a special constructor that will increment a
84 // global counter. This allows us to ensure that it is only called once.
89 // The following is the shared structure between all threads.
91 MultiState(LazyInstance<StaticCounter>* staticCounter) :
92 mMutex(), mStaticCounter(staticCounter), mCount(0) {}
99 LazyInstance<StaticCounter>* mStaticCounter;
101 void* mValues[kMaxThreads];
102 TestThread* mThreads[kMaxThreads];
105 // The thread function for the test below.
106 static void* threadFunc(void* param) {
107 MultiState* state = static_cast<MultiState*>(param);
108 Mutex::AutoLock lock(state->mMutex);
109 if (state->mCount < MultiState::kMaxThreads) {
110 state->mValues[state->mCount++] = state->mStaticCounter->ptr();
117 TEST(LazyInstance, MultipleThreads) {
118 LazyInstance<StaticCounter> counter_instance = LAZY_INSTANCE_INIT;
119 MultiState state(&counter_instance);
120 const size_t kNumThreads = MultiState::kMaxThreads;
122 // Create all threads.
123 for (size_t n = 0; n < kNumThreads; ++n) {
124 state.mThreads[n] = new TestThread(threadFunc, &state);
127 // Wait for their completion.
128 for (size_t n = 0; n < kNumThreads; ++n) {
129 state.mThreads[n]->join();
132 // Now check that the constructor was only called once.
133 EXPECT_EQ(1, counter_instance->getValue());
135 // Now compare all the store values, they should be the same.
136 StaticCounter* expectedValue = counter_instance.ptr();
137 for (size_t n = 0; n < kNumThreads; ++n) {
138 EXPECT_EQ(expectedValue, state.mValues[n]) << "For thread " << n;
141 for (size_t n = 0; n < kNumThreads; ++n) {
142 delete state.mThreads[n];