--- /dev/null
+#include <folly/SmallLocks.h>
+#include <folly/RWSpinLock.h>
+#include <folly/SharedMutex.h>
+#include <folly/synchronization/Rcu.h>
+
+#include <gtest/gtest.h>
+
+#include <memory>
+
+namespace {
+
+// MicroLock
+const size_t kMicroLockPassCount = 2000000000;
+typedef folly::MicroLock MicroLock;
+
+// MicroSpinLock
+const size_t kMicroSpinLockPassCount = 1500000000;
+typedef folly::MicroSpinLock MicroSpinLock;
+
+// PicoSpinLock
+const size_t kPicoSpinLockPassCount = 2700000000;
+typedef folly::PicoSpinLock<size_t> PicoSpinLock;
+
+// SharedMutex
+const size_t kSharedMutexPassCount = 5000000;
+typedef folly::SharedMutexReadPriority SharedMutexReadPriority;
+typedef folly::SharedMutexWritePriority SharedMutexWritePriority;
+
+// RWSpinLock
+const size_t kRWSpinLockPassCount = 5000000;
+typedef folly::RWSpinLock RWSpinLock;
+
+// RWTicketSpinLock
+const size_t kRWTicketSpinLockPassCount = 5000000;
+typedef folly::RWTicketSpinLock32 RWTicketSpinLock32;
+typedef folly::RWTicketSpinLock64 RWTicketSpinLock64;
+
+// RCU
+const size_t kRcuSyncPassCount = 180000;
+const size_t kRcuNoSyncPassCount = 3500000;
+// Represent the RCU-protected data.
+struct RcuFoo {
+ size_t f1;
+ size_t f2;
+};
+
+}
+
+void run_rcu_sync(size_t pass_count) {
+ for (int write_percentage = 1; write_percentage <= 5; write_percentage += 1) {
+ for (size_t count = 0; count < pass_count; count++) {
+ for (int i = 0; i < 100; ++i) {
+ if (i < write_percentage) {
+ RcuFoo* f = new RcuFoo();
+ folly::rcu_retire(f);
+ folly::synchronize_rcu();
+ } else {
+ folly::rcu_reader g;
+ }
+ }
+ }
+ }
+}
+
+void run_rcu_no_sync(size_t pass_count) {
+ for (int write_percentage = 1; write_percentage <= 5; write_percentage += 1) {
+ for (size_t count = 0; count < pass_count; count++) {
+ for (int i = 0; i < 100; ++i) {
+ if (i < write_percentage) {
+ RcuFoo* f = new RcuFoo();
+ folly::rcu_retire(f);
+ } else {
+ folly::rcu_reader g;
+ }
+ }
+ }
+ }
+}
+
+template <typename Lock>
+void run_rw_lock(size_t pass_count) {
+ std::unique_ptr<Lock> l(new Lock());
+ for (int write_percentage = 5; write_percentage < 20; write_percentage += 5) {
+ for (size_t count = 0; count < pass_count; count++) {
+ for (int i = 0; i < 100; ++i) {
+ if (i < write_percentage) {
+ l->lock();
+ l->unlock();
+ } else {
+ l->lock_shared();
+ l->unlock_shared();
+ }
+ }
+ }
+ }
+}
+
+template <typename Lock>
+void run_small_lock(size_t pass_count) {
+ std::unique_ptr<Lock> l(new Lock());
+ l->init();
+ for (size_t count = 0; count < pass_count; count++) {
+ l->lock();
+ l->unlock();
+ }
+}
+
+class FollySyncTest: public ::testing::Test {
+
+};
+
+TEST_F(FollySyncTest, FollyRCU_Sync) {
+ run_rcu_sync(kRcuSyncPassCount);
+}
+
+TEST_F(FollySyncTest, FollyRCU_NoSync) {
+ run_rcu_no_sync(kRcuNoSyncPassCount);
+}
+
+TEST_F(FollySyncTest, FollyRWTicketSpinLock_32) {
+ run_rw_lock<RWTicketSpinLock32>(kRWTicketSpinLockPassCount);
+}
+
+TEST_F(FollySyncTest, FollyRWTicketSpinLock_64) {
+ run_rw_lock<RWTicketSpinLock64>(kRWTicketSpinLockPassCount);
+}
+
+TEST_F(FollySyncTest, FollyRWSpinLock) {
+ run_rw_lock<RWSpinLock>(kRWSpinLockPassCount);
+}
+
+TEST_F(FollySyncTest, FollySharedMutex_ReadPriority) {
+ run_rw_lock<SharedMutexReadPriority>(kSharedMutexPassCount);
+}
+
+TEST_F(FollySyncTest, FollySharedMutex_WritePriority) {
+ run_rw_lock<SharedMutexWritePriority>(kSharedMutexPassCount);
+}
+
+TEST_F(FollySyncTest, FollyMicroSpinLock) {
+ run_small_lock<MicroSpinLock>(kMicroSpinLockPassCount);
+}
+
+TEST_F(FollySyncTest, FollyPicoSpinLock) {
+ run_small_lock<PicoSpinLock>(kPicoSpinLockPassCount);
+}
+
+TEST_F(FollySyncTest, FollyMicroLock) {
+ run_small_lock<MicroLock>(kMicroLockPassCount);
+}
+
+int main(int argc, char** argv) {
+ // Init Google test
+ ::testing::InitGoogleTest(&argc, argv);
+ int result = RUN_ALL_TESTS();
+ return result;
+}