1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_PLATFORM_MUTEX_H 17 #define ECMASCRIPT_PLATFORM_MUTEX_H 18 19 #include <pthread.h> 20 #include <atomic> 21 22 #include "ecmascript/common.h" 23 #include "libpandabase/macros.h" 24 25 #if defined(PANDA_USE_FUTEX) 26 #include "ecmascript/platform/unix/futex.h" 27 #endif 28 29 #ifdef DEBUG 30 #define FATAL_IF_ERROR(f, rc) \ 31 do { \ 32 if (rc != 0) { \ 33 LOG_ECMA(FATAL)<< f << " failed: " << rc; \ 34 } \ 35 } while (false) 36 #else 37 #define FATAL_IF_ERROR(f, rc) static_cast<void>(0) 38 #endif 39 namespace panda::ecmascript { 40 41 class PUBLIC_API Mutex { 42 public: 43 explicit Mutex(bool is_init = true); 44 45 ~Mutex(); 46 47 void Lock(); 48 49 bool TryLock(); 50 51 void Unlock(); 52 53 protected: 54 void Init(pthread_mutexattr_t *attrs); 55 56 private: 57 pthread_mutex_t mutex_; 58 friend class ConditionVariable; 59 }; 60 61 class RecursiveMutex : public Mutex { 62 public: 63 RecursiveMutex(); 64 65 ~RecursiveMutex() = default; 66 67 NO_COPY_SEMANTIC(RecursiveMutex); 68 NO_MOVE_SEMANTIC(RecursiveMutex); 69 }; 70 71 class PUBLIC_API RWLock { 72 public: 73 RWLock(); 74 75 ~RWLock(); 76 77 void ReadLock(); 78 79 void WriteLock(); 80 81 bool TryReadLock(); 82 83 bool TryWriteLock(); 84 85 void Unlock(); 86 87 private: 88 pthread_rwlock_t rwlock_; 89 90 NO_COPY_SEMANTIC(RWLock); 91 NO_MOVE_SEMANTIC(RWLock); 92 }; 93 94 class PUBLIC_API ConditionVariable { 95 public: 96 ConditionVariable(); 97 98 ~ConditionVariable(); 99 100 void Signal(); 101 102 void SignalAll(); 103 104 void Wait(Mutex *mutex); 105 106 bool TimedWait(Mutex *mutex, uint64_t ms, uint64_t ns = 0, bool is_absolute = false); 107 108 private: 109 pthread_cond_t cond_; 110 }; 111 112 class LockHolder { 113 public: LockHolder(Mutex & mtx)114 explicit LockHolder(Mutex &mtx) : lock_(mtx) 115 { 116 lock_.Lock(); 117 } 118 ~LockHolder()119 ~LockHolder() 120 { 121 lock_.Unlock(); 122 } 123 124 private: 125 Mutex &lock_; 126 127 NO_COPY_SEMANTIC(LockHolder); 128 NO_MOVE_SEMANTIC(LockHolder); 129 }; 130 131 class ReadLockHolder { 132 public: ReadLockHolder(RWLock & lock)133 explicit ReadLockHolder(RWLock &lock) : lock_(lock) 134 { 135 lock_.ReadLock(); 136 } 137 ~ReadLockHolder()138 ~ReadLockHolder() 139 { 140 lock_.Unlock(); 141 } 142 143 private: 144 RWLock &lock_; 145 146 NO_COPY_SEMANTIC(ReadLockHolder); 147 NO_MOVE_SEMANTIC(ReadLockHolder); 148 }; 149 150 class WriteLockHolder { 151 public: WriteLockHolder(RWLock & lock)152 explicit WriteLockHolder(RWLock &lock) : lock_(lock) 153 { 154 lock_.WriteLock(); 155 } 156 ~WriteLockHolder()157 ~WriteLockHolder() 158 { 159 lock_.Unlock(); 160 } 161 162 private: 163 RWLock &lock_; 164 165 NO_COPY_SEMANTIC(WriteLockHolder); 166 NO_MOVE_SEMANTIC(WriteLockHolder); 167 }; 168 } // namespace panda::ecmascript 169 #endif // ECMASCRIPT_PLATFORM_MUTEX_H 170