2 * Copyright 2013 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "folly/experimental/EventCount.h"
21 #include <glog/logging.h>
22 #include <gtest/gtest.h>
24 #include "folly/Random.h"
25 #include "folly/Benchmark.h"
27 using namespace folly;
33 explicit Semaphore(int v=0) : value_(v) { }
36 ec_.await([this] { return tryDown(); });
55 if (value_.compare_exchange_weak(v, v-1)) {
61 std::atomic<int> value_;
65 template <class T, class Random>
66 void randomPartition(Random& random, T key, int n,
67 std::vector<std::pair<T, int>>& out) {
69 int m = std::min(n, 1000);
70 std::uniform_int_distribution<uint32_t> u(1, m);
72 out.push_back(std::make_pair(key, cut));
79 TEST(EventCount, Simple) {
80 // We're basically testing for no deadlock.
81 static const size_t count = 300000;
87 std::vector<std::pair<Op, int>> ops;
88 std::mt19937 rnd(randomNumberSeed());
89 randomPartition(rnd, Op::UP, count, ops);
90 size_t uppers = ops.size();
91 randomPartition(rnd, Op::DOWN, count, ops);
92 size_t downers = ops.size() - uppers;
93 VLOG(1) << "Using " << ops.size() << " threads: uppers=" << uppers
94 << " downers=" << downers << " sem_count=" << count;
96 std::random_shuffle(ops.begin(), ops.end());
98 std::vector<std::thread> threads;
99 threads.reserve(ops.size());
102 for (auto& op : ops) {
104 if (op.first == Op::UP) {
105 auto fn = [&sem, n] () mutable {
110 threads.push_back(std::thread(fn));
112 auto fn = [&sem, n] () mutable {
117 threads.push_back(std::thread(fn));
121 for (auto& thread : threads) {
125 EXPECT_EQ(0, sem.value());
128 int main(int argc, char *argv[]) {
129 testing::InitGoogleTest(&argc, argv);
130 google::ParseCommandLineFlags(&argc, &argv, true);
131 auto ret = RUN_ALL_TESTS();
133 folly::runBenchmarksOnFlag();