Added FOLLY_IGNORE and FOLLY_SEMICOLON helper macros
[folly.git] / folly / SpinLock.h
index 2747a4dbfbef86cb947eca95f1f19b93e08a7bf0..6d10df4ad4e032aab207d52068a5ffbd9bc59a08 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-#pragma once
+/*
+ * N.B. You most likely do _not_ want to use SpinLock or any other
+ * kind of spinlock.  Use std::mutex instead.
+ *
+ * In short, spinlocks in preemptive multi-tasking operating systems
+ * have serious problems and fast mutexes like std::mutex are almost
+ * certainly the better choice, because letting the OS scheduler put a
+ * thread to sleep is better for system responsiveness and throughput
+ * than wasting a timeslice repeatedly querying a lock held by a
+ * thread that's blocked, and you can't prevent userspace
+ * programs blocking.
+ *
+ * Spinlocks in an operating system kernel make much more sense than
+ * they do in userspace.
+ */
 
-#include <boost/noncopyable.hpp>
-#include <folly/Portability.h>
+#pragma once
 
-// This is a wrapper SpinLock implementation that works around the
-// x64 limitation of the base folly MicroSpinLock. If that is available, this
-// simply thinly wraps it. Otherwise, it uses the simplest analog available on
-// iOS (or 32-bit Mac) or, failing that, POSIX (on Android et. al.)
-
-#if __x86_64__
-#include <folly/SmallLocks.h>
+#include <folly/detail/SpinLockImpl.h>
 
 namespace folly {
 
-class SpinLock {
- public:
-  FOLLY_ALWAYS_INLINE SpinLock() {
-    lock_.init();
-  }
-  FOLLY_ALWAYS_INLINE void lock() const {
-    lock_.lock();
-  }
-  FOLLY_ALWAYS_INLINE void unlock() const {
-    lock_.unlock();
-  }
-  FOLLY_ALWAYS_INLINE bool trylock() const {
-    return lock_.try_lock();
-  }
- private:
-  mutable folly::MicroSpinLock lock_;
-};
-
-}
-
+#if __x86_64__
+typedef SpinLockMslImpl SpinLock;
 #elif __APPLE__
-#include <libkern/OSAtomic.h>
-
-namespace folly {
-
-class SpinLock {
- public:
-  FOLLY_ALWAYS_INLINE SpinLock() : lock_(0) {}
-  FOLLY_ALWAYS_INLINE void lock() const {
-    OSSpinLockLock(&lock_);
-  }
-  FOLLY_ALWAYS_INLINE void unlock() const {
-    OSSpinLockUnlock(&lock_);
-  }
-  FOLLY_ALWAYS_INLINE bool trylock() const {
-    return OSSpinLockTry(&lock_);
-  }
- private:
-  mutable OSSpinLock lock_;
-};
-
-}
-
+typedef SpinLockAppleImpl SpinLock;
+#elif FOLLY_HAVE_PTHREAD_SPINLOCK_T
+typedef SpinLockPthreadImpl SpinLock;
 #else
-#include <pthread.h>
-#include <glog/logging.h>
-
-namespace folly {
-
-class SpinLock {
- public:
-  FOLLY_ALWAYS_INLINE SpinLock() {
-    pthread_mutex_init(&lock_, nullptr);
-  }
-  void lock() const {
-    int rc = pthread_mutex_lock(&lock_);
-    CHECK_EQ(0, rc);
-  }
-  FOLLY_ALWAYS_INLINE void unlock() const {
-    int rc = pthread_mutex_unlock(&lock_);
-    CHECK_EQ(0, rc);
-  }
-  FOLLY_ALWAYS_INLINE bool trylock() const {
-    int rc = pthread_mutex_trylock(&lock_);
-    CHECK_GE(rc, 0);
-    return rc == 0;
-  }
- private:
-  mutable pthread_mutex_t lock_;
-};
-
-}
-
+typedef SpinLockPthreadMutexImpl SpinLock;
 #endif
 
-namespace folly {
-
-class SpinLockGuard : private boost::noncopyable {
+template <typename LOCK>
+class SpinLockGuardImpl : private boost::noncopyable {
  public:
-  FOLLY_ALWAYS_INLINE explicit SpinLockGuard(SpinLock& lock) :
+  FOLLY_ALWAYS_INLINE explicit SpinLockGuardImpl(LOCK& lock) :
     lock_(lock) {
     lock_.lock();
   }
-  FOLLY_ALWAYS_INLINE ~SpinLockGuard() {
+  FOLLY_ALWAYS_INLINE ~SpinLockGuardImpl() {
     lock_.unlock();
   }
  private:
-  SpinLock& lock_;
+  LOCK& lock_;
 };
 
+typedef SpinLockGuardImpl<SpinLock> SpinLockGuard;
+
 }