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 24 #if defined(PANDA_USE_FUTEX) 25 #include "ecmascript/platform/unix/futex.h" 26 #endif 27 28 #ifdef DEBUG 29 #define FATAL_IF_ERROR(f, rc) \ 30 do { \ 31 if (rc != 0) { \ 32 LOG_ECMA(FATAL)<< f << " failed: " << rc; \ 33 } \ 34 } while (false) 35 #else 36 #define FATAL_IF_ERROR(f, rc) static_cast<void>(0) 37 #endif 38 namespace panda::ecmascript { 39 40 class PUBLIC_API Mutex { 41 public: 42 explicit Mutex(bool is_init = true); 43 44 ~Mutex(); 45 46 void Lock(); 47 48 bool TryLock(); 49 50 void Unlock(); 51 52 protected: 53 void Init(pthread_mutexattr_t *attrs); 54 55 private: 56 pthread_mutex_t mutex_; 57 friend class ConditionVariable; 58 }; 59 60 class RecursiveMutex : public Mutex { 61 public: 62 RecursiveMutex(); 63 64 ~RecursiveMutex() = default; 65 66 NO_COPY_SEMANTIC(RecursiveMutex); 67 NO_MOVE_SEMANTIC(RecursiveMutex); 68 }; 69 70 class PUBLIC_API RWLock { 71 public: 72 RWLock(); 73 74 ~RWLock(); 75 76 void ReadLock(); 77 78 void WriteLock(); 79 80 bool TryReadLock(); 81 82 bool TryWriteLock(); 83 84 void Unlock(); 85 86 private: 87 pthread_rwlock_t rwlock_; 88 89 NO_COPY_SEMANTIC(RWLock); 90 NO_MOVE_SEMANTIC(RWLock); 91 }; 92 93 class PUBLIC_API ConditionVariable { 94 public: 95 ConditionVariable(); 96 97 ~ConditionVariable(); 98 99 void Signal(); 100 101 void SignalAll(); 102 103 void Wait(Mutex *mutex); 104 105 bool TimedWait(Mutex *mutex, uint64_t ms, uint64_t ns = 0, bool is_absolute = false); 106 107 private: 108 pthread_cond_t cond_; 109 }; 110 111 class LockHolder { 112 public: LockHolder(Mutex & mtx)113 explicit LockHolder(Mutex &mtx) : lock_(mtx) 114 { 115 lock_.Lock(); 116 } 117 ~LockHolder()118 ~LockHolder() 119 { 120 lock_.Unlock(); 121 } 122 123 private: 124 Mutex &lock_; 125 126 NO_COPY_SEMANTIC(LockHolder); 127 NO_MOVE_SEMANTIC(LockHolder); 128 }; 129 130 class ReadLockHolder { 131 public: ReadLockHolder(RWLock & lock)132 explicit ReadLockHolder(RWLock &lock) : lock_(lock) 133 { 134 lock_.ReadLock(); 135 } 136 ~ReadLockHolder()137 ~ReadLockHolder() 138 { 139 lock_.Unlock(); 140 } 141 142 private: 143 RWLock &lock_; 144 145 NO_COPY_SEMANTIC(ReadLockHolder); 146 NO_MOVE_SEMANTIC(ReadLockHolder); 147 }; 148 149 class WriteLockHolder { 150 public: WriteLockHolder(RWLock & lock)151 explicit WriteLockHolder(RWLock &lock) : lock_(lock) 152 { 153 lock_.WriteLock(); 154 } 155 ~WriteLockHolder()156 ~WriteLockHolder() 157 { 158 lock_.Unlock(); 159 } 160 161 private: 162 RWLock &lock_; 163 164 NO_COPY_SEMANTIC(WriteLockHolder); 165 NO_MOVE_SEMANTIC(WriteLockHolder); 166 }; 167 } // namespace panda::ecmascript 168 #endif // ECMASCRIPT_PLATFORM_MUTEX_H 169