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 #else 27 #include <mutex> 28 #endif 29 30 namespace Fortran::runtime { 31 32 class Lock { 33 public: 34 #if USE_PTHREADS Lock()35 Lock() { pthread_mutex_init(&mutex_, nullptr); } ~Lock()36 ~Lock() { pthread_mutex_destroy(&mutex_); } Take()37 void Take() { 38 while (pthread_mutex_lock(&mutex_)) { 39 } 40 } Try()41 bool Try() { return pthread_mutex_trylock(&mutex_) == 0; } Drop()42 void Drop() { pthread_mutex_unlock(&mutex_); } 43 #else 44 void Take() { mutex_.lock(); } 45 bool Try() { return mutex_.try_lock(); } 46 void Drop() { mutex_.unlock(); } 47 #endif 48 CheckLocked(const Terminator & terminator)49 void CheckLocked(const Terminator &terminator) { 50 if (Try()) { 51 Drop(); 52 terminator.Crash("Lock::CheckLocked() failed"); 53 } 54 } 55 56 private: 57 #if USE_PTHREADS 58 pthread_mutex_t mutex_{}; 59 #else 60 std::mutex mutex_; 61 #endif 62 }; 63 64 class CriticalSection { 65 public: CriticalSection(Lock & lock)66 explicit CriticalSection(Lock &lock) : lock_{lock} { lock_.Take(); } ~CriticalSection()67 ~CriticalSection() { lock_.Drop(); } 68 69 private: 70 Lock &lock_; 71 }; 72 } // namespace Fortran::runtime 73 74 #endif // FORTRAN_RUNTIME_LOCK_H_ 75