Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / Synchronized.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 /**
18  * This module implements a Synchronized abstraction useful in
19  * mutex-based concurrency.
20  *
21  * @author: Andrei Alexandrescu (andrei.alexandrescu@fb.com)
22  */
23
24 #ifndef SYNCHRONIZED_H_
25 #define SYNCHRONIZED_H_
26
27 #include <type_traits>
28 #include <mutex>
29 #include <boost/thread.hpp>
30 #include <folly/Preprocessor.h>
31 #include <folly/Traits.h>
32
33 namespace folly {
34
35 namespace detail {
36 enum InternalDoNotUse {};
37
38 /**
39  * Free function adaptors for std:: and boost::
40  */
41
42 /**
43  * Yields true iff T has .lock() and .unlock() member functions. This
44  * is done by simply enumerating the mutexes with this interface in
45  * std and boost.
46  */
47 template <class T>
48 struct HasLockUnlock {
49   enum { value = IsOneOf<T,
50          std::mutex, std::recursive_mutex,
51          boost::mutex, boost::recursive_mutex, boost::shared_mutex
52 #ifndef __APPLE__ // OSX doesn't have timed mutexes
53         ,std::timed_mutex, std::recursive_timed_mutex,
54          boost::timed_mutex, boost::recursive_timed_mutex
55 #endif
56          >::value };
57 };
58
59 /**
60  * Acquires a mutex for reading by calling .lock(). The exception is
61  * boost::shared_mutex, which has a special read-lock primitive called
62  * .lock_shared().
63  */
64 template <class T>
65 typename std::enable_if<
66   HasLockUnlock<T>::value && !std::is_same<T, boost::shared_mutex>::value>::type
67 acquireRead(T& mutex) {
68   mutex.lock();
69 }
70
71 /**
72  * Special case for boost::shared_mutex.
73  */
74 template <class T>
75 typename std::enable_if<std::is_same<T, boost::shared_mutex>::value>::type
76 acquireRead(T& mutex) {
77   mutex.lock_shared();
78 }
79
80 /**
81  * Acquires a mutex for reading with timeout by calling .timed_lock(). This
82  * applies to three of the boost mutex classes as enumerated below.
83  */
84 template <class T>
85 typename std::enable_if<std::is_same<T, boost::shared_mutex>::value, bool>::type
86 acquireRead(T& mutex,
87             unsigned int milliseconds) {
88   return mutex.timed_lock_shared(boost::posix_time::milliseconds(milliseconds));
89 }
90
91 /**
92  * Acquires a mutex for reading and writing by calling .lock().
93  */
94 template <class T>
95 typename std::enable_if<HasLockUnlock<T>::value>::type
96 acquireReadWrite(T& mutex) {
97   mutex.lock();
98 }
99
100 #ifndef __APPLE__ // OSX doesn't have timed mutexes
101 /**
102  * Acquires a mutex for reading and writing with timeout by calling
103  * .try_lock_for(). This applies to two of the std mutex classes as
104  * enumerated below.
105  */
106 template <class T>
107 typename std::enable_if<
108   IsOneOf<T, std::timed_mutex, std::recursive_timed_mutex>::value, bool>::type
109 acquireReadWrite(T& mutex,
110                  unsigned int milliseconds) {
111   // work around try_lock_for bug in some gcc versions, see
112   // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54562
113   return mutex.try_lock()
114       || (milliseconds > 0 &&
115           mutex.try_lock_until(std::chrono::system_clock::now() +
116                                std::chrono::milliseconds(milliseconds)));
117 }
118
119 /**
120  * Acquires a mutex for reading and writing with timeout by calling
121  * .timed_lock(). This applies to three of the boost mutex classes as
122  * enumerated below.
123  */
124 template <class T>
125 typename std::enable_if<
126   IsOneOf<T, boost::shared_mutex, boost::timed_mutex,
127           boost::recursive_timed_mutex>::value, bool>::type
128 acquireReadWrite(T& mutex,
129                  unsigned int milliseconds) {
130   return mutex.timed_lock(boost::posix_time::milliseconds(milliseconds));
131 }
132 #endif // __APPLE__
133
134 /**
135  * Releases a mutex previously acquired for reading by calling
136  * .unlock(). The exception is boost::shared_mutex, which has a
137  * special primitive called .unlock_shared().
138  */
139 template <class T>
140 typename std::enable_if<
141   HasLockUnlock<T>::value && !std::is_same<T, boost::shared_mutex>::value>::type
142 releaseRead(T& mutex) {
143   mutex.unlock();
144 }
145
146 /**
147  * Special case for boost::shared_mutex.
148  */
149 template <class T>
150 typename std::enable_if<std::is_same<T, boost::shared_mutex>::value>::type
151 releaseRead(T& mutex) {
152   mutex.unlock_shared();
153 }
154
155 /**
156  * Releases a mutex previously acquired for reading-writing by calling
157  * .unlock().
158  */
159 template <class T>
160 typename std::enable_if<HasLockUnlock<T>::value>::type
161 releaseReadWrite(T& mutex) {
162   mutex.unlock();
163 }
164
165 } // namespace detail
166
167 /**
168  * Synchronized<T> encapsulates an object of type T (a "datum") paired
169  * with a mutex. The only way to access the datum is while the mutex
170  * is locked, and Synchronized makes it virtually impossible to do
171  * otherwise. The code that would access the datum in unsafe ways
172  * would look odd and convoluted, thus readily alerting the human
173  * reviewer. In contrast, the code that uses Synchronized<T> correctly
174  * looks simple and intuitive.
175  *
176  * The second parameter must be a mutex type. Supported mutexes are
177  * std::mutex, std::recursive_mutex, std::timed_mutex,
178  * std::recursive_timed_mutex, boost::mutex, boost::recursive_mutex,
179  * boost::shared_mutex, boost::timed_mutex,
180  * boost::recursive_timed_mutex, and the folly/RWSpinLock.h
181  * classes.
182  *
183  * You may define Synchronized support by defining 4-6 primitives in
184  * the same namespace as the mutex class (found via ADL).  The
185  * primitives are: acquireRead, acquireReadWrite, releaseRead, and
186  * releaseReadWrite. Two optional primitives for timout operations are
187  * overloads of acquireRead and acquireReadWrite. For signatures,
188  * refer to the namespace detail below, which implements the
189  * primitives for mutexes in std and boost.
190  */
191 template <class T, class Mutex = boost::shared_mutex>
192 struct Synchronized {
193   /**
194    * Default constructor leaves both members call their own default
195    * constructor.
196    */
197   Synchronized() = default;
198
199   /**
200    * Copy constructor copies the data (with locking the source and
201    * all) but does NOT copy the mutex. Doing so would result in
202    * deadlocks.
203    */
204   Synchronized(const Synchronized& rhs) {
205     auto guard = rhs.operator->();
206     datum_ = rhs.datum_;
207   }
208
209   /**
210    * Move constructor moves the data (with locking the source and all)
211    * but does not move the mutex.
212    */
213   Synchronized(Synchronized&& rhs) {
214     auto guard = rhs.operator->();
215     datum_ = std::move(rhs.datum_);
216   }
217
218   /**
219    * Constructor taking a datum as argument copies it. There is no
220    * need to lock the constructing object.
221    */
222   explicit Synchronized(const T& rhs) : datum_(rhs) {}
223
224   /**
225    * Constructor taking a datum rvalue as argument moves it. Again,
226    * there is no need to lock the constructing object.
227    */
228   explicit Synchronized(T&& rhs) : datum_(std::move(rhs)) {}
229
230   /**
231    * The canonical assignment operator only assigns the data, NOT the
232    * mutex. It locks the two objects in ascending order of their
233    * addresses.
234    */
235   Synchronized& operator=(const Synchronized& rhs) {
236     if (this == &rhs) {
237       // Self-assignment, pass.
238     } else if (this < &rhs) {
239       auto guard1 = operator->();
240       auto guard2 = rhs.operator->();
241       datum_ = rhs.datum_;
242     } else {
243       auto guard1 = rhs.operator->();
244       auto guard2 = operator->();
245       datum_ = rhs.datum_;
246     }
247     return *this;
248   }
249
250   /**
251    * Move assignment operator, only assigns the data, NOT the
252    * mutex. It locks the two objects in ascending order of their
253    * addresses.
254    */
255   Synchronized& operator=(Synchronized&& rhs) {
256     if (this == &rhs) {
257       // Self-assignment, pass.
258     } else if (this < &rhs) {
259       auto guard1 = operator->();
260       auto guard2 = rhs.operator->();
261       datum_ = std::move(rhs.datum_);
262     } else {
263       auto guard1 = rhs.operator->();
264       auto guard2 = operator->();
265       datum_ = std::move(rhs.datum_);
266     }
267     return *this;
268   }
269
270   /**
271    * Lock object, assign datum.
272    */
273   Synchronized& operator=(const T& rhs) {
274     auto guard = operator->();
275     datum_ = rhs;
276     return *this;
277   }
278
279   /**
280    * Lock object, move-assign datum.
281    */
282   Synchronized& operator=(T&& rhs) {
283     auto guard = operator->();
284     datum_ = std::move(rhs);
285     return *this;
286   }
287
288   /**
289    * A LockedPtr lp keeps a modifiable (i.e. non-const)
290    * Synchronized<T> object locked for the duration of lp's
291    * existence. Because of this, you get to access the datum's methods
292    * directly by using lp->fun().
293    */
294   struct LockedPtr {
295     /**
296      * Found no reason to leave this hanging.
297      */
298     LockedPtr() = delete;
299
300     /**
301      * Takes a Synchronized and locks it.
302      */
303     explicit LockedPtr(Synchronized* parent) : parent_(parent) {
304       acquire();
305     }
306
307     /**
308      * Takes a Synchronized and attempts to lock it for some
309      * milliseconds. If not, the LockedPtr will be subsequently null.
310      */
311     LockedPtr(Synchronized* parent, unsigned int milliseconds) {
312       using namespace detail;
313       if (acquireReadWrite(parent->mutex_, milliseconds)) {
314         parent_ = parent;
315         return;
316       }
317       // Could not acquire the resource, pointer is null
318       parent_ = nullptr;
319     }
320
321     /**
322      * This is used ONLY inside SYNCHRONIZED_DUAL. It initializes
323      * everything properly, but does not lock the parent because it
324      * "knows" someone else will lock it. Please do not use.
325      */
326     LockedPtr(Synchronized* parent, detail::InternalDoNotUse)
327         : parent_(parent) {
328     }
329
330     /**
331      * Copy ctor adds one lock.
332      */
333     LockedPtr(const LockedPtr& rhs) : parent_(rhs.parent_) {
334       acquire();
335     }
336
337     /**
338      * Assigning from another LockedPtr results in freeing the former
339      * lock and acquiring the new one. The method works with
340      * self-assignment (does nothing).
341      */
342     LockedPtr& operator=(const LockedPtr& rhs) {
343       if (parent_ != rhs.parent_) {
344         if (parent_) parent_->mutex_.unlock();
345         parent_ = rhs.parent_;
346         acquire();
347       }
348       return *this;
349     }
350
351     /**
352      * Destructor releases.
353      */
354     ~LockedPtr() {
355       using namespace detail;
356       if (parent_) releaseReadWrite(parent_->mutex_);
357     }
358
359     /**
360      * Safe to access the data. Don't save the obtained pointer by
361      * invoking lp.operator->() by hand. Also, if the method returns a
362      * handle stored inside the datum, don't use this idiom - use
363      * SYNCHRONIZED below.
364      */
365     T* operator->() {
366       return parent_ ? &parent_->datum_ : nullptr;
367     }
368
369     /**
370      * This class temporarily unlocks a LockedPtr in a scoped
371      * manner. It is used inside of the UNSYNCHRONIZED macro.
372      */
373     struct Unsynchronizer {
374       explicit Unsynchronizer(LockedPtr* p) : parent_(p) {
375         using namespace detail;
376         releaseReadWrite(parent_->parent_->mutex_);
377       }
378       Unsynchronizer(const Unsynchronizer&) = delete;
379       Unsynchronizer& operator=(const Unsynchronizer&) = delete;
380       ~Unsynchronizer() {
381         parent_->acquire();
382       }
383       LockedPtr* operator->() const {
384         return parent_;
385       }
386     private:
387       LockedPtr* parent_;
388     };
389     friend struct Unsynchronizer;
390     Unsynchronizer typeHackDoNotUse();
391
392     template <class P1, class P2>
393     friend void lockInOrder(P1& p1, P2& p2);
394
395   private:
396     void acquire() {
397       using namespace detail;
398       if (parent_) acquireReadWrite(parent_->mutex_);
399     }
400
401     // This is the entire state of LockedPtr.
402     Synchronized* parent_;
403   };
404
405   /**
406    * ConstLockedPtr does exactly what LockedPtr does, but for const
407    * Synchronized objects. Of interest is that ConstLockedPtr only
408    * uses a read lock, which is faster but more restrictive - you only
409    * get to call const methods of the datum.
410    *
411    * Much of the code between LockedPtr and
412    * ConstLockedPtr is identical and could be factor out, but there
413    * are enough nagging little differences to not justify the trouble.
414    */
415   struct ConstLockedPtr {
416     ConstLockedPtr() = delete;
417     explicit ConstLockedPtr(const Synchronized* parent) : parent_(parent) {
418       acquire();
419     }
420     ConstLockedPtr(const Synchronized* parent, detail::InternalDoNotUse)
421         : parent_(parent) {
422     }
423     ConstLockedPtr(const ConstLockedPtr& rhs) : parent_(rhs.parent_) {
424       acquire();
425     }
426     explicit ConstLockedPtr(const LockedPtr& rhs) : parent_(rhs.parent_) {
427       acquire();
428     }
429     ConstLockedPtr(const Synchronized* parent, unsigned int milliseconds) {
430       if (parent->mutex_.timed_lock_shared(
431             boost::posix_time::milliseconds(milliseconds))) {
432         parent_ = parent;
433         return;
434       }
435       // Could not acquire the resource, pointer is null
436       parent_ = nullptr;
437     }
438
439     ConstLockedPtr& operator=(const ConstLockedPtr& rhs) {
440       if (parent_ != rhs.parent_) {
441         if (parent_) parent_->mutex_.unlock_shared();
442         parent_ = rhs.parent_;
443         acquire();
444       }
445     }
446     ~ConstLockedPtr() {
447       using namespace detail;
448       if (parent_) releaseRead(parent_->mutex_);
449     }
450
451     const T* operator->() const {
452       return parent_ ? &parent_->datum_ : nullptr;
453     }
454
455     struct Unsynchronizer {
456       explicit Unsynchronizer(ConstLockedPtr* p) : parent_(p) {
457         using namespace detail;
458         releaseRead(parent_->parent_->mutex_);
459       }
460       Unsynchronizer(const Unsynchronizer&) = delete;
461       Unsynchronizer& operator=(const Unsynchronizer&) = delete;
462       ~Unsynchronizer() {
463         using namespace detail;
464         acquireRead(parent_->parent_->mutex_);
465       }
466       ConstLockedPtr* operator->() const {
467         return parent_;
468       }
469     private:
470       ConstLockedPtr* parent_;
471     };
472     friend struct Unsynchronizer;
473     Unsynchronizer typeHackDoNotUse();
474
475     template <class P1, class P2>
476     friend void lockInOrder(P1& p1, P2& p2);
477
478   private:
479     void acquire() {
480       using namespace detail;
481       if (parent_) acquireRead(parent_->mutex_);
482     }
483
484     const Synchronized* parent_;
485   };
486
487   /**
488    * This accessor offers a LockedPtr. In turn. LockedPtr offers
489    * operator-> returning a pointer to T. The operator-> keeps
490    * expanding until it reaches a pointer, so syncobj->foo() will lock
491    * the object and call foo() against it.
492   */
493   LockedPtr operator->() {
494     return LockedPtr(this);
495   }
496
497   /**
498    * Same, for constant objects. You will be able to invoke only const
499    * methods.
500    */
501   ConstLockedPtr operator->() const {
502     return ConstLockedPtr(this);
503   }
504
505   /**
506    * Attempts to acquire for a given number of milliseconds. If
507    * acquisition is unsuccessful, the returned LockedPtr is NULL.
508    */
509   LockedPtr timedAcquire(unsigned int milliseconds) {
510     return LockedPtr(this, milliseconds);
511   }
512
513   /**
514    * As above, for a constant object.
515    */
516   ConstLockedPtr timedAcquire(unsigned int milliseconds) const {
517     return ConstLockedPtr(this, milliseconds);
518   }
519
520   /**
521    * Used by SYNCHRONIZED_DUAL.
522    */
523   LockedPtr internalDoNotUse() {
524     return LockedPtr(this, detail::InternalDoNotUse());
525   }
526
527   /**
528    * ditto
529    */
530   ConstLockedPtr internalDoNotUse() const {
531     return ConstLockedPtr(this, detail::InternalDoNotUse());
532   }
533
534   /**
535    * Sometimes, although you have a mutable object, you only want to
536    * call a const method against it. The most efficient way to achieve
537    * that is by using a read lock. You get to do so by using
538    * obj.asConst()->method() instead of obj->method().
539    */
540   const Synchronized& asConst() const {
541     return *this;
542   }
543
544   /**
545    * Swaps with another Synchronized. Protected against
546    * self-swap. Only data is swapped. Locks are acquired in increasing
547    * address order.
548    */
549   void swap(Synchronized& rhs) {
550     if (this == &rhs) {
551       return;
552     }
553     if (this > &rhs) {
554       return rhs.swap(*this);
555     }
556     auto guard1 = operator->();
557     auto guard2 = rhs.operator->();
558
559     using std::swap;
560     swap(datum_, rhs.datum_);
561   }
562
563   /**
564    * Swap with another datum. Recommended because it keeps the mutex
565    * held only briefly.
566    */
567   void swap(T& rhs) {
568     LockedPtr guard = operator->();
569
570     using std::swap;
571     swap(datum_, rhs);
572   }
573
574   /**
575    * Copies datum to a given target.
576    */
577   void copy(T* target) const {
578     ConstLockedPtr guard = operator->();
579     *target = datum_;
580   }
581
582   /**
583    * Returns a fresh copy of the datum.
584    */
585   T copy() const {
586     ConstLockedPtr guard = operator->();
587     return datum_;
588   }
589
590 private:
591   T datum_;
592   mutable Mutex mutex_;
593 };
594
595 // Non-member swap primitive
596 template <class T, class M>
597 void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) {
598   lhs.swap(rhs);
599 }
600
601 /**
602  * SYNCHRONIZED is the main facility that makes Synchronized<T>
603  * helpful. It is a pseudo-statement that introduces a scope where the
604  * object is locked. Inside that scope you get to access the unadorned
605  * datum.
606  *
607  * Example:
608  *
609  * Synchronized<vector<int>> svector;
610  * ...
611  * SYNCHRONIZED (svector) { ... use svector as a vector<int> ... }
612  * or
613  * SYNCHRONIZED (v, svector) { ... use v as a vector<int> ... }
614  *
615  * Refer to folly/docs/Synchronized.md for a detailed explanation and more
616  * examples.
617  */
618 #define SYNCHRONIZED(...)                                       \
619   if (bool SYNCHRONIZED_state = false) {} else                  \
620     for (auto SYNCHRONIZED_lockedPtr =                          \
621            (FB_ARG_2_OR_1(__VA_ARGS__)).operator->();           \
622          !SYNCHRONIZED_state; SYNCHRONIZED_state = true)        \
623       for (auto& FB_ARG_1(__VA_ARGS__) =                        \
624              *SYNCHRONIZED_lockedPtr.operator->();              \
625            !SYNCHRONIZED_state; SYNCHRONIZED_state = true)
626
627 #define TIMED_SYNCHRONIZED(timeout, ...)                           \
628   if (bool SYNCHRONIZED_state = false) {} else                     \
629     for (auto SYNCHRONIZED_lockedPtr =                             \
630            (FB_ARG_2_OR_1(__VA_ARGS__)).timedAcquire(timeout);     \
631          !SYNCHRONIZED_state; SYNCHRONIZED_state = true)           \
632       for (auto FB_ARG_1(__VA_ARGS__) =                            \
633              SYNCHRONIZED_lockedPtr.operator->();                  \
634            !SYNCHRONIZED_state; SYNCHRONIZED_state = true)
635
636 /**
637  * Similar to SYNCHRONIZED, but only uses a read lock.
638  */
639 #define SYNCHRONIZED_CONST(...)                         \
640   SYNCHRONIZED(FB_ARG_1(__VA_ARGS__),                   \
641                (FB_ARG_2_OR_1(__VA_ARGS__)).asConst())
642
643 /**
644  * Similar to TIMED_SYNCHRONIZED, but only uses a read lock.
645  */
646 #define TIMED_SYNCHRONIZED_CONST(timeout, ...)                  \
647   TIMED_SYNCHRONIZED(timeout, FB_ARG_1(__VA_ARGS__),            \
648                      (FB_ARG_2_OR_1(__VA_ARGS__)).asConst())
649
650 /**
651  * Temporarily disables synchronization inside a SYNCHRONIZED block.
652  */
653 #define UNSYNCHRONIZED(name)                                    \
654   for (decltype(SYNCHRONIZED_lockedPtr.typeHackDoNotUse())      \
655          SYNCHRONIZED_state3(&SYNCHRONIZED_lockedPtr);          \
656        !SYNCHRONIZED_state; SYNCHRONIZED_state = true)          \
657     for (auto name = *SYNCHRONIZED_state3.operator->();         \
658          !SYNCHRONIZED_state; SYNCHRONIZED_state = true)
659
660 /**
661  * Locks two objects in increasing order of their addresses.
662  */
663 template <class P1, class P2>
664 void lockInOrder(P1& p1, P2& p2) {
665   if (static_cast<const void*>(p1.operator->()) >
666       static_cast<const void*>(p2.operator->())) {
667     p2.acquire();
668     p1.acquire();
669   } else {
670     p1.acquire();
671     p2.acquire();
672   }
673 }
674
675 /**
676  * Synchronizes two Synchronized objects (they may encapsulate
677  * different data). Synchronization is done in increasing address of
678  * object order, so there is no deadlock risk.
679  */
680 #define SYNCHRONIZED_DUAL(n1, e1, n2, e2)                       \
681   if (bool SYNCHRONIZED_state = false) {} else                  \
682     for (auto SYNCHRONIZED_lp1 = (e1).internalDoNotUse();       \
683          !SYNCHRONIZED_state; SYNCHRONIZED_state = true)        \
684       for (auto& n1 = *SYNCHRONIZED_lp1.operator->();           \
685            !SYNCHRONIZED_state;  SYNCHRONIZED_state = true)     \
686         for (auto SYNCHRONIZED_lp2 = (e2).internalDoNotUse();   \
687              !SYNCHRONIZED_state;  SYNCHRONIZED_state = true)   \
688           for (auto& n2 = *SYNCHRONIZED_lp2.operator->();       \
689                !SYNCHRONIZED_state; SYNCHRONIZED_state = true)  \
690             if ((::folly::lockInOrder(                          \
691                    SYNCHRONIZED_lp1, SYNCHRONIZED_lp2),         \
692                  false)) {}                                     \
693             else
694
695 } /* namespace folly */
696
697 #endif // SYNCHRONIZED_H_