/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include TEST(ConcurrentLazy, Simple) { int computeCount = 0; auto const val = folly::concurrent_lazy([&]() -> int { ++computeCount; EXPECT_EQ(computeCount, 1); return 12; }); EXPECT_EQ(computeCount, 0); for (int i = 0; i < 100; ++i) { if (i > 50) { EXPECT_EQ(val(), 12); EXPECT_EQ(computeCount, 1); } else { EXPECT_EQ(computeCount, 0); } } EXPECT_EQ(val(), 12); EXPECT_EQ(computeCount, 1); } TEST(ConcurrentLazy, MultipleReaders) { std::atomic_int computeCount = 0; std::mutex m; auto const val = folly::concurrent_lazy([&]() -> int { ++computeCount; EXPECT_EQ(computeCount, 1); // Block here so that we can wait for threads to pile up. m.lock(); m.unlock(); return 12; }); EXPECT_EQ(computeCount, 0); // Lock the mutex while we create the readers, which will prevent the // instantiation from completing until we've created all our readers. m.lock(); std::vector readers; for (int i = 0; i < 10; ++i) { readers.push_back(std::thread([&] { for (int j = 0; j < 1000; ++j) { EXPECT_EQ(val(), 12); } })); } m.unlock(); for (auto& reader : readers) { reader.join(); } EXPECT_EQ(val(), 12); EXPECT_EQ(computeCount, 1); } struct CopyCount { CopyCount() = default; CopyCount(const CopyCount&) { ++count; } CopyCount(CopyCount&&) = default; CopyCount& operator=(const CopyCount&) = default; CopyCount& operator=(CopyCount&&) = default; static int count; bool operator()() const { return true; } }; int CopyCount::count = 0; TEST(ConcurrentLazy, NonLambda) { auto const rval = folly::concurrent_lazy(CopyCount()); EXPECT_EQ(CopyCount::count, 0); EXPECT_EQ(rval(), true); EXPECT_EQ(CopyCount::count, 0); CopyCount cpy; auto const lval = folly::concurrent_lazy(cpy); EXPECT_EQ(CopyCount::count, 1); EXPECT_EQ(lval(), true); EXPECT_EQ(CopyCount::count, 1); std::function f = [&] { return 12; }; auto const lazyF = folly::concurrent_lazy(f); EXPECT_EQ(lazyF(), true); }