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