Revert D4805628: [folly] Suppress more warnings for MSVC
[folly.git] / folly / detail / SpinLockImpl.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #pragma once
17
18 /*
19  * This class provides a few spin lock implementations, depending on the
20  * platform.  folly/SpinLock.h will select one of these as the folly::SpinLock
21  * implementation.
22  *
23  * The main reason we keep these separated out here is so that we can run unit
24  * tests for all supported spin lock implementations, even though only one will
25  * be selected as the actual folly::SpinLock implemenatation for any given
26  * platform.
27  */
28
29 #include <boost/noncopyable.hpp>
30 #include <folly/Portability.h>
31
32 #if __x86_64__
33 #include <folly/SmallLocks.h>
34
35 namespace folly {
36
37 class SpinLockMslImpl {
38  public:
39   FOLLY_ALWAYS_INLINE SpinLockMslImpl() {
40     lock_.init();
41   }
42   FOLLY_ALWAYS_INLINE void lock() const {
43     lock_.lock();
44   }
45   FOLLY_ALWAYS_INLINE void unlock() const {
46     lock_.unlock();
47   }
48   FOLLY_ALWAYS_INLINE bool try_lock() const {
49     return lock_.try_lock();
50   }
51  private:
52   mutable folly::MicroSpinLock lock_;
53 };
54
55 }
56
57 #endif // __x86_64__
58
59 #if __APPLE__
60 #include <libkern/OSAtomic.h>
61
62 namespace folly {
63
64 class SpinLockAppleImpl {
65  public:
66   FOLLY_ALWAYS_INLINE SpinLockAppleImpl() : lock_(0) {}
67   FOLLY_ALWAYS_INLINE void lock() const {
68     OSSpinLockLock(&lock_);
69   }
70   FOLLY_ALWAYS_INLINE void unlock() const {
71     OSSpinLockUnlock(&lock_);
72   }
73   FOLLY_ALWAYS_INLINE bool try_lock() const {
74     return OSSpinLockTry(&lock_);
75   }
76  private:
77   mutable OSSpinLock lock_;
78 };
79
80 }
81
82 #endif // __APPLE__
83
84 #include <pthread.h>
85 #include <folly/Exception.h>
86
87 #if FOLLY_HAVE_PTHREAD_SPINLOCK_T
88
89 // Apple and Android systems don't have pthread_spinlock_t, so we can't support
90 // this version on those platforms.
91 namespace folly {
92
93 class SpinLockPthreadImpl {
94  public:
95   FOLLY_ALWAYS_INLINE SpinLockPthreadImpl() {
96     int rc = pthread_spin_init(&lock_, PTHREAD_PROCESS_PRIVATE);
97     checkPosixError(rc, "failed to initialize spinlock");
98   }
99   FOLLY_ALWAYS_INLINE ~SpinLockPthreadImpl() {
100     pthread_spin_destroy(&lock_);
101   }
102   void lock() const {
103     int rc = pthread_spin_lock(&lock_);
104     checkPosixError(rc, "error locking spinlock");
105   }
106   FOLLY_ALWAYS_INLINE void unlock() const {
107     int rc = pthread_spin_unlock(&lock_);
108     checkPosixError(rc, "error unlocking spinlock");
109   }
110   FOLLY_ALWAYS_INLINE bool try_lock() const {
111     int rc = pthread_spin_trylock(&lock_);
112     if (rc == 0) {
113       return true;
114     } else if (rc == EBUSY) {
115       return false;
116     }
117     throwSystemErrorExplicit(rc, "spinlock trylock error");
118   }
119  private:
120   mutable pthread_spinlock_t lock_;
121 };
122
123 }
124
125 #endif // FOLLY_HAVE_PTHREAD_SPINLOCK_T
126
127 namespace folly {
128
129 class SpinLockPthreadMutexImpl {
130  public:
131   FOLLY_ALWAYS_INLINE SpinLockPthreadMutexImpl() {
132     int rc = pthread_mutex_init(&lock_, nullptr);
133     checkPosixError(rc, "failed to initialize mutex");
134   }
135   FOLLY_ALWAYS_INLINE ~SpinLockPthreadMutexImpl() {
136     pthread_mutex_destroy(&lock_);
137   }
138   void lock() const {
139     int rc = pthread_mutex_lock(&lock_);
140     checkPosixError(rc, "error locking mutex");
141   }
142   FOLLY_ALWAYS_INLINE void unlock() const {
143     int rc = pthread_mutex_unlock(&lock_);
144     checkPosixError(rc, "error unlocking mutex");
145   }
146   FOLLY_ALWAYS_INLINE bool try_lock() const {
147     int rc = pthread_mutex_trylock(&lock_);
148     if (rc == 0) {
149       return true;
150     } else if (rc == EBUSY) {
151       return false;
152     }
153     throwSystemErrorExplicit(rc, "mutex trylock error");
154   }
155  private:
156   mutable pthread_mutex_t lock_;
157 };
158
159 }