* Copyright (c) 2025 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 WINDOW_WINDOW_MANAGER_UTILS_DMS_GLOBAL_MUTEX_H
#define WINDOW_WINDOW_MANAGER_UTILS_DMS_GLOBAL_MUTEX_H
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <functional>
#include <iomanip>
#include <mutex>
#include <sstream>
#include <thread>
#include "window_manager_hilog.h"
namespace OHOS::Rosen {
namespace DmUtils {
#define FREE_GLOBAL_LOCK_FOR_IPC() {DmUtils::DropLock ipcLock;}
class HoldLock {
public:
HoldLock()
{
if (++counter() == 1) {
if ((resMtx.try_lock()) || (lockStatus && resMtx.try_lock_for(TRY_LOCK_TIMEOUT))) {
lockStatus = true;
} else {
lockStatus = false;
TLOGD(WmsLogTag::DMS, "[HoldLock] try lock fail");
}
}
}
~HoldLock()
{
if (--counter() == 0 && lockStatus) {
resMtx.unlock();
}
}
static bool ForceUnlock()
{
auto threadLocked = --counter() >= 0;
if (threadLocked && lockStatus) {
resMtx.unlock();
return true;
}
return false;
}
static void ForceLock(bool hasLock)
{
++counter();
if (hasLock) {
if ((resMtx.try_lock()) || (lockStatus && resMtx.try_lock_for(TRY_LOCK_TIMEOUT))) {
lockStatus = true;
} else {
lockStatus = false;
TLOGD(WmsLogTag::DMS, "[ForceLock] try lock fail");
}
}
}
private:
static std::timed_mutex resMtx;
static thread_local bool lockStatus;
static constexpr std::chrono::milliseconds TRY_LOCK_TIMEOUT{ 5 };
static int& counter()
{
static thread_local int _count = 0;
return _count;
}
};
class DropLock {
public:
DropLock()
{
hasLock = HoldLock::ForceUnlock();
}
~DropLock()
{
HoldLock::ForceLock(hasLock);
}
private:
bool hasLock = true;
};
template <typename Func> auto wrap_callback(Func func)
{
return [func](auto&&... args) {
HoldLock callback_lock;
func(std::forward<decltype(args)>(args)...);
};
}
template <typename Rep, typename Period>
std::cv_status safe_wait_for(std::condition_variable& cv,
std::unique_lock<std::mutex>& lock,
const std::chrono::duration<Rep, Period>& rel_time)
{
DropLock unlockGuard;
auto status = cv.wait_for(lock, rel_time);
return status;
}
template <typename Rep, typename Period, typename Predicate>
bool safe_wait_for(std::condition_variable& cv,
std::unique_lock<std::mutex>& lock,
const std::chrono::duration<Rep, Period>& rel_time,
Predicate pred)
{
DropLock unlockGuard;
bool result = cv.wait_for(lock, rel_time, pred);
return result;
}
}
}
#endif