* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_PLATFORM_MUTEX_H
#define ECMASCRIPT_PLATFORM_MUTEX_H
#include <pthread.h>
#include <atomic>
#include "ecmascript/common.h"
#include "libpandabase/macros.h"
#if defined(PANDA_USE_FUTEX)
#include "ecmascript/platform/unix/futex.h"
#endif
#ifdef DEBUG
#define FATAL_IF_ERROR(f, rc) \
do { \
if (rc != 0) { \
LOG_ECMA(FATAL)<< f << " failed: " << rc; \
} \
} while (false)
#else
#define FATAL_IF_ERROR(f, rc) static_cast<void>(0)
#endif
namespace panda::ecmascript {
class PUBLIC_API Mutex {
public:
explicit Mutex(bool is_init = true);
~Mutex();
void Lock();
bool TryLock();
void Unlock();
protected:
void Init(pthread_mutexattr_t *attrs);
private:
pthread_mutex_t mutex_;
friend class ConditionVariable;
};
class RecursiveMutex : public Mutex {
public:
RecursiveMutex();
~RecursiveMutex() = default;
NO_COPY_SEMANTIC(RecursiveMutex);
NO_MOVE_SEMANTIC(RecursiveMutex);
};
class PUBLIC_API RWLock {
public:
RWLock();
~RWLock();
void ReadLock();
void WriteLock();
bool TryReadLock();
bool TryWriteLock();
void Unlock();
private:
pthread_rwlock_t rwlock_;
NO_COPY_SEMANTIC(RWLock);
NO_MOVE_SEMANTIC(RWLock);
};
class PUBLIC_API ConditionVariable {
public:
ConditionVariable();
~ConditionVariable();
void Signal();
void SignalAll();
void Wait(Mutex *mutex);
bool TimedWait(Mutex *mutex, uint64_t ms, uint64_t ns = 0, bool is_absolute = false);
private:
pthread_cond_t cond_;
};
class LockHolder {
public:
explicit LockHolder(Mutex &mtx) : lock_(mtx)
{
lock_.Lock();
}
~LockHolder()
{
lock_.Unlock();
}
private:
Mutex &lock_;
NO_COPY_SEMANTIC(LockHolder);
NO_MOVE_SEMANTIC(LockHolder);
};
class ReadLockHolder {
public:
explicit ReadLockHolder(RWLock &lock) : lock_(lock)
{
lock_.ReadLock();
}
~ReadLockHolder()
{
lock_.Unlock();
}
private:
RWLock &lock_;
NO_COPY_SEMANTIC(ReadLockHolder);
NO_MOVE_SEMANTIC(ReadLockHolder);
};
class WriteLockHolder {
public:
explicit WriteLockHolder(RWLock &lock) : lock_(lock)
{
lock_.WriteLock();
}
~WriteLockHolder()
{
lock_.Unlock();
}
private:
RWLock &lock_;
NO_COPY_SEMANTIC(WriteLockHolder);
NO_MOVE_SEMANTIC(WriteLockHolder);
};
}
#endif