Have EventBase implement wangle::Executor
[folly.git] / folly / io / PortableSpinLock.h
1 /*
2  * Copyright 2014 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
17 #pragma once
18
19 #include <boost/noncopyable.hpp>
20
21 // This is a wrapper SpinLock implementation that works around the
22 // x64 limitation of the base folly MicroSpinLock. If that is available, this
23 // simply thinly wraps it. Otherwise, it uses the simplest analog available on
24 // iOS (or 32-bit Mac) or, failing that, POSIX (on Android et. al.)
25
26 #if __x86_64__
27 #include <folly/SmallLocks.h>
28
29 namespace folly { namespace io {
30
31 class PortableSpinLock {
32  public:
33   FOLLY_ALWAYS_INLINE PortableSpinLock() {
34     lock_.init();
35   }
36   FOLLY_ALWAYS_INLINE void lock() const {
37     lock_.lock();
38   }
39   FOLLY_ALWAYS_INLINE void unlock() const {
40     lock_.unlock();
41   }
42   FOLLY_ALWAYS_INLINE bool trylock() const {
43     return lock_.try_lock();
44   }
45  private:
46   mutable folly::MicroSpinLock lock_;
47 };
48
49 }}
50
51 #elif __APPLE__
52 #include <libkern/OSAtomic.h>
53
54 namespace folly { namespace io {
55
56 class PortableSpinLock {
57  public:
58   FOLLY_ALWAYS_INLINE PortableSpinLock() : lock_(0) {}
59   FOLLY_ALWAYS_INLINE void lock() const {
60     OSSpinLockLock(&lock_);
61   }
62   FOLLY_ALWAYS_INLINE void unlock() const {
63     OSSpinLockUnlock(&lock_);
64   }
65   FOLLY_ALWAYS_INLINE bool trylock() const {
66     return OSSpinLockTry(&lock_);
67   }
68  private:
69   mutable OSSpinLock lock_;
70 };
71
72 }}
73
74 #else
75 #include <pthread.h>
76
77 namespace folly { namespace io {
78
79 class PortableSpinLock {
80  public:
81   FOLLY_ALWAYS_INLINE PortableSpinLock() {
82     pthread_mutex_init(&lock_, nullptr);
83   }
84   void lock() const {
85     int rc = pthread_mutex_lock(&lock_);
86     CHECK_EQ(0, rc);
87   }
88   FOLLY_ALWAYS_INLINE void unlock() const {
89     int rc = pthread_mutex_unlock(&lock_);
90     CHECK_EQ(0, rc);
91   }
92   FOLLY_ALWAYS_INLINE bool trylock() const {
93     int rc = pthread_mutex_trylock(&lock_);
94     CHECK_GE(rc, 0);
95     return rc == 0;
96   }
97  private:
98   mutable pthread_mutex_t lock_;
99 };
100
101 }}
102
103 #endif
104
105 namespace folly { namespace io {
106
107 class PortableSpinLockGuard : private boost::noncopyable {
108  public:
109   FOLLY_ALWAYS_INLINE explicit PortableSpinLockGuard(PortableSpinLock& lock) :
110     lock_(lock) {
111     lock_.lock();
112   }
113   FOLLY_ALWAYS_INLINE ~PortableSpinLockGuard() {
114     lock_.unlock();
115   }
116  private:
117   PortableSpinLock& lock_;
118 };
119
120 }}