mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-22 22:16:37 +08:00
introduce async LockGuard
This commit is contained in:
parent
2caf7b99b7
commit
892b2b9633
@ -26,6 +26,9 @@
|
||||
|
||||
namespace oatpp { namespace async {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lock
|
||||
|
||||
Lock::Lock()
|
||||
: m_counter(0)
|
||||
{
|
||||
@ -71,4 +74,96 @@ bool Lock::try_lock() {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LockGuard
|
||||
|
||||
LockGuard::LockGuard()
|
||||
: m_ownsLock(false)
|
||||
, m_lock(nullptr)
|
||||
{}
|
||||
|
||||
LockGuard::LockGuard(Lock* lock)
|
||||
: m_ownsLock(false)
|
||||
, m_lock(lock)
|
||||
{}
|
||||
|
||||
LockGuard::~LockGuard() {
|
||||
if(m_ownsLock) {
|
||||
m_lock->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void LockGuard::setLockObject(Lock* lock) {
|
||||
if(m_lock == nullptr) {
|
||||
m_lock = lock;
|
||||
} else if(m_lock != lock) {
|
||||
throw std::runtime_error("[oatpp::async::LockGuard::setLockObject()]: Error. Invalid state. LockGuard is NOT reusable.");
|
||||
}
|
||||
}
|
||||
|
||||
CoroutineStarter LockGuard::lockAsync() {
|
||||
|
||||
class LockCoroutine : public Coroutine<LockCoroutine> {
|
||||
private:
|
||||
LockGuard* m_guard;
|
||||
public:
|
||||
|
||||
LockCoroutine(LockGuard* guard)
|
||||
: m_guard(guard)
|
||||
{}
|
||||
|
||||
Action act() override {
|
||||
return m_guard->lockAsyncInline(finish());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return LockCoroutine::start(this);
|
||||
|
||||
}
|
||||
|
||||
CoroutineStarter LockGuard::lockAsync(Lock* lock) {
|
||||
setLockObject(lock);
|
||||
return lockAsync();
|
||||
}
|
||||
|
||||
|
||||
Action LockGuard::lockAsyncInline(oatpp::async::Action&& nextAction) {
|
||||
|
||||
if(!m_ownsLock) {
|
||||
|
||||
m_ownsLock = m_lock->try_lock();
|
||||
|
||||
if(m_ownsLock) {
|
||||
return std::forward<Action>(nextAction);
|
||||
} else {
|
||||
return m_lock->waitAsync();
|
||||
}
|
||||
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::async::LockGuard::lockAsyncInline()]: Error. Invalid state. Double lock attempt.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LockGuard::unlock() {
|
||||
|
||||
if(m_lock) {
|
||||
|
||||
if(m_ownsLock) {
|
||||
|
||||
m_lock->unlock();
|
||||
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::async::LockGuard::unlock()]: Error. Invalid state. LockGuard is NOT owning the lock.");
|
||||
}
|
||||
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::async::LockGuard::unlock()]: Error. Invalid state. Lock object is nullptr.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}
|
||||
|
@ -72,6 +72,74 @@ public:
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Asynchronous lock guard. <br>
|
||||
* Should be used as a lock guard in coroutines.
|
||||
*/
|
||||
class LockGuard {
|
||||
public:
|
||||
/**
|
||||
* Convenince typedef for &id:oatpp::async::CoroutineStarter;.
|
||||
*/
|
||||
typedef oatpp::async::CoroutineStarter CoroutineStarter;
|
||||
private:
|
||||
bool m_ownsLock;
|
||||
Lock* m_lock;
|
||||
public:
|
||||
LockGuard(const LockGuard&) = delete;
|
||||
LockGuard& operator = (const LockGuard&) = delete;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
LockGuard();
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
LockGuard(Lock* lock);
|
||||
|
||||
/**
|
||||
* Non-virtual destructor. <br>
|
||||
* Will unlock the Lock if owns lock.
|
||||
*/
|
||||
~LockGuard();
|
||||
|
||||
/**
|
||||
* Set lock object.
|
||||
* @param lock - lock object.
|
||||
*/
|
||||
void setLockObject(Lock* lock);
|
||||
|
||||
/**
|
||||
* Lock the lock.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
CoroutineStarter lockAsync();
|
||||
|
||||
/**
|
||||
* Lock and guard the lock. <br>
|
||||
* Same as `setLockObject(lock) + lockAsync();`.
|
||||
* @param lock - lock to lock and guard.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
CoroutineStarter lockAsync(Lock* lock);
|
||||
|
||||
/**
|
||||
* Lock the lock. (Async-inline usage. Should be called from a separate method of coroutine).
|
||||
* @param nextAction - action to take after lock is locked.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
Action lockAsyncInline(oatpp::async::Action&& nextAction);
|
||||
|
||||
/**
|
||||
* Unlock guarded lock.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // oatpp_async_Mutex_hpp
|
||||
|
Loading…
Reference in New Issue
Block a user