xref: /llvm-project-15.0.7/flang/runtime/lock.h (revision 99fe38a1)
1 //===-- runtime/lock.h ------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Wraps a mutex
10 
11 #ifndef FORTRAN_RUNTIME_LOCK_H_
12 #define FORTRAN_RUNTIME_LOCK_H_
13 
14 #include "terminator.h"
15 
16 // Avoid <mutex> if possible to avoid introduction of C++ runtime
17 // library dependence.
18 #ifndef _WIN32
19 #define USE_PTHREADS 1
20 #else
21 #undef USE_PTHREADS
22 #endif
23 
24 #if USE_PTHREADS
25 #include <pthread.h>
26 #elif defined(_WIN32)
27 // Do not define macros for "min" and "max"
28 #define NOMINMAX
29 #include <windows.h>
30 #else
31 #include <mutex>
32 #endif
33 
34 namespace Fortran::runtime {
35 
36 class Lock {
37 public:
38 #if USE_PTHREADS
Lock()39   Lock() { pthread_mutex_init(&mutex_, nullptr); }
~Lock()40   ~Lock() { pthread_mutex_destroy(&mutex_); }
Take()41   void Take() {
42     while (pthread_mutex_lock(&mutex_)) {
43     }
44   }
Try()45   bool Try() { return pthread_mutex_trylock(&mutex_) == 0; }
Drop()46   void Drop() { pthread_mutex_unlock(&mutex_); }
47 #elif defined(_WIN32)
48   Lock() { InitializeCriticalSection(&cs_); }
49   ~Lock() { DeleteCriticalSection(&cs_); }
50   void Take() { EnterCriticalSection(&cs_); }
51   bool Try() { return TryEnterCriticalSection(&cs_); }
52   void Drop() { LeaveCriticalSection(&cs_); }
53 #else
54   void Take() { mutex_.lock(); }
55   bool Try() { return mutex_.try_lock(); }
56   void Drop() { mutex_.unlock(); }
57 #endif
58 
CheckLocked(const Terminator & terminator)59   void CheckLocked(const Terminator &terminator) {
60     if (Try()) {
61       Drop();
62       terminator.Crash("Lock::CheckLocked() failed");
63     }
64   }
65 
66 private:
67 #if USE_PTHREADS
68   pthread_mutex_t mutex_{};
69 #elif defined(_WIN32)
70   CRITICAL_SECTION cs_;
71 #else
72   std::mutex mutex_;
73 #endif
74 };
75 
76 class CriticalSection {
77 public:
CriticalSection(Lock & lock)78   explicit CriticalSection(Lock &lock) : lock_{lock} { lock_.Take(); }
~CriticalSection()79   ~CriticalSection() { lock_.Drop(); }
80 
81 private:
82   Lock &lock_;
83 };
84 } // namespace Fortran::runtime
85 
86 #endif // FORTRAN_RUNTIME_LOCK_H_
87