mirror of
https://github.com/uroni/urbackup_backend.git
synced 2025-10-26 11:36:50 +00:00
166 lines
3.7 KiB
C++
166 lines
3.7 KiB
C++
#include "resource.h"
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <atomic>
|
|
#include <thread>
|
|
#include <set>
|
|
|
|
struct ERESOURCE_INT {
|
|
ERESOURCE_INT()
|
|
: owner(std::thread::id()),
|
|
excl_count(0) {}
|
|
|
|
std::mutex mutex;
|
|
std::condition_variable cond;
|
|
std::thread::id owner;
|
|
std::set<std::thread::id> shared_threads;
|
|
int excl_count;
|
|
};
|
|
|
|
BOOLEAN ExAcquireResourceSharedLite(PERESOURCE Resource, BOOLEAN Wait)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Resource->res->mutex);
|
|
|
|
if (Resource->res->owner!= std::thread::id() &&
|
|
Resource->res->owner == std::this_thread::get_id())
|
|
{
|
|
++Resource->res->excl_count;
|
|
return TRUE;
|
|
}
|
|
|
|
if (Resource->res->owner == std::thread::id())
|
|
{
|
|
Resource->res->shared_threads.insert(std::this_thread::get_id());
|
|
return TRUE;
|
|
}
|
|
|
|
if (!Wait)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
while (Resource->res->owner != std::thread::id())
|
|
{
|
|
Resource->res->cond.wait(lock);
|
|
}
|
|
|
|
Resource->res->shared_threads.insert(std::this_thread::get_id());
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN ExAcquireResourceExclusiveLite(PERESOURCE Resource, BOOLEAN Wait)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Resource->res->mutex);
|
|
|
|
if (Resource->res->owner!=std::thread::id() &&
|
|
Resource->res->owner == std::this_thread::get_id())
|
|
{
|
|
++Resource->res->excl_count;
|
|
return TRUE;
|
|
}
|
|
|
|
if (Resource->res->shared_threads.empty() &&
|
|
Resource->res->owner == std::thread::id())
|
|
{
|
|
Resource->res->owner = std::this_thread::get_id();
|
|
Resource->res->excl_count = 1;
|
|
return TRUE;
|
|
}
|
|
|
|
if (!Wait)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
while (!Resource->res->shared_threads.empty() ||
|
|
Resource->res->owner != std::thread::id())
|
|
{
|
|
Resource->res->cond.wait(lock);
|
|
}
|
|
|
|
Resource->res->owner = std::this_thread::get_id();
|
|
Resource->res->excl_count = 1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN ExReleaseResourceLite(PERESOURCE Resource)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Resource->res->mutex);
|
|
|
|
if (Resource->res->owner !=std::thread::id() &&
|
|
Resource->res->owner == std::this_thread::get_id())
|
|
{
|
|
if (Resource->res->excl_count > 1)
|
|
{
|
|
--Resource->res->excl_count;
|
|
}
|
|
else
|
|
{
|
|
Resource->res->owner = std::thread::id();
|
|
Resource->res->excl_count = 0;
|
|
Resource->res->cond.notify_all();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Resource->res->shared_threads.erase(std::this_thread::get_id());
|
|
if (Resource->res->shared_threads.empty())
|
|
{
|
|
Resource->res->cond.notify_all();
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void ExConvertExclusiveToSharedLite(PERESOURCE Res)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Res->res->mutex);
|
|
|
|
Res->res->owner = std::thread::id();
|
|
Res->res->excl_count = 0;
|
|
Res->res->shared_threads.insert(std::this_thread::get_id());
|
|
}
|
|
|
|
BOOLEAN ExDeleteResourceLite(PERESOURCE Resource)
|
|
{
|
|
delete Resource->res;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN ExInitializeResourceLite(PERESOURCE Resource)
|
|
{
|
|
Resource->res = new ERESOURCE_INT;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN ExIsResourceAcquiredExclusiveLite(PERESOURCE Resource)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Resource->res->mutex);
|
|
return Resource->res->owner != std::thread::id() &&
|
|
Resource->res->excl_count > 0 &&
|
|
Resource->res->owner == std::this_thread::get_id();
|
|
}
|
|
|
|
void ExReleaseResource(PERESOURCE Resource)
|
|
{
|
|
ExReleaseResourceLite(Resource);
|
|
}
|
|
|
|
BOOLEAN ExIsResourceAcquiredSharedLite(PERESOURCE Resource)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Resource->res->mutex);
|
|
|
|
if (Resource->res->owner != std::thread::id())
|
|
{
|
|
return Resource->res->owner == std::this_thread::get_id() ? TRUE : FALSE;
|
|
}
|
|
|
|
return Resource->res->shared_threads.find(std::this_thread::get_id()) != Resource->res->shared_threads.end();
|
|
}
|
|
|
|
BOOLEAN ExIsResourceAcquiredExclusive(PERESOURCE Resource)
|
|
{
|
|
return ExIsResourceAcquiredExclusiveLite(Resource);
|
|
} |