File indexing completed on 2024-05-19 04:25:05
0001 /* 0002 * SPDX-FileCopyrightText: 2023 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KISADAPTEDLOCK_H 0008 #define KISADAPTEDLOCK_H 0009 0010 #include <mutex> 0011 0012 /** 0013 * A wrapper class that adapts std::unique_lock to any kind 0014 * of locking that might be necessary to a particular class. 0015 * 0016 * Just define an Adapter class that implements `lock()`, 0017 * `unlock()` and (optionally) `try_lock()` interface and 0018 * pass it to `KisAdaptedLock`. The resulting class will 0019 * behave as normal `std::unique_lock` and lock/unlock the 0020 * object as you intructed it. 0021 * 0022 * See examples in `KisCursorOverrideLockAdapter` and 0023 * `KisLockFrameGenerationLock` 0024 */ 0025 template <typename Adapter> 0026 class KisAdaptedLock 0027 : protected Adapter, 0028 public std::unique_lock<Adapter> 0029 { 0030 public: 0031 template<typename Object> 0032 KisAdaptedLock(Object object) 0033 : Adapter(object) 0034 , std::unique_lock<Adapter>( 0035 static_cast<Adapter&>(*this)) 0036 {} 0037 0038 template<typename Object> 0039 KisAdaptedLock(Object object, std::try_to_lock_t t) 0040 : Adapter(object) 0041 , std::unique_lock<Adapter>(static_cast<Adapter&>(*this), t) 0042 {} 0043 0044 template<typename Object> 0045 KisAdaptedLock(Object object, std::defer_lock_t t) 0046 : Adapter(object) 0047 , std::unique_lock<Adapter>(static_cast<Adapter&>(*this), t) 0048 {} 0049 0050 template<typename Object> 0051 KisAdaptedLock(Object object, std::adopt_lock_t t) 0052 : Adapter(object) 0053 , std::unique_lock<Adapter>(static_cast<Adapter&>(*this), t) 0054 {} 0055 0056 KisAdaptedLock(KisAdaptedLock &&rhs) 0057 : Adapter(static_cast<Adapter&>(rhs)) 0058 , std::unique_lock<Adapter>( 0059 static_cast<Adapter&>(*this), std::adopt_lock) 0060 { 0061 rhs.release(); 0062 } 0063 0064 KisAdaptedLock& operator=(KisAdaptedLock &&rhs) 0065 { 0066 static_cast<Adapter&>(*this) = rhs; 0067 static_cast<std::unique_lock<Adapter>&>(*this) = 0068 std::unique_lock<Adapter>(static_cast<Adapter&>(*this), 0069 std::adopt_lock); 0070 rhs.release(); 0071 return *this; 0072 } 0073 0074 using std::unique_lock<Adapter>::try_lock; 0075 using std::unique_lock<Adapter>::lock; 0076 using std::unique_lock<Adapter>::unlock; 0077 }; 0078 0079 /** 0080 * A macro to make sure that the resulting lock is 0081 * a 'class' and can be forward-declared instead of 0082 * the entire include pulling 0083 */ 0084 #define KIS_DECLARE_ADAPTED_LOCK(Name, Adapter) \ 0085 class Name : public KisAdaptedLock<Adapter> \ 0086 { \ 0087 public: \ 0088 using BaseClass = KisAdaptedLock<Adapter>; \ 0089 using BaseClass::BaseClass; \ 0090 }; 0091 0092 #endif // KISADAPTEDLOCK_H