fix incorrect implementation of revertible_mutex
This commit is contained in:
parent
3fd5f77e09
commit
8182d93b9a
@ -274,26 +274,34 @@ namespace detail
|
|||||||
};
|
};
|
||||||
//end struct wdm_private_impl
|
//end struct wdm_private_impl
|
||||||
|
|
||||||
//class revertible_mutex
|
//class revertible_mutex
|
||||||
struct thread_refcount
|
struct thread_refcount
|
||||||
{
|
{
|
||||||
unsigned tid;
|
unsigned tid; //Thread ID
|
||||||
std::size_t ref;
|
std::vector<unsigned> callstack_refs;
|
||||||
|
|
||||||
|
thread_refcount(unsigned thread_id, unsigned refs)
|
||||||
|
: tid(thread_id)
|
||||||
|
{
|
||||||
|
callstack_refs.push_back(refs);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct window_manager::revertible_mutex::implementation
|
struct window_manager::revertible_mutex::implementation
|
||||||
{
|
{
|
||||||
std::recursive_mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
thread_refcount thread;
|
unsigned thread_id; //Thread ID
|
||||||
|
unsigned refs; //Ref count
|
||||||
|
|
||||||
std::vector<thread_refcount> records;
|
std::vector<thread_refcount> records;
|
||||||
};
|
};
|
||||||
|
|
||||||
window_manager::revertible_mutex::revertible_mutex()
|
window_manager::revertible_mutex::revertible_mutex()
|
||||||
: impl_(new implementation)
|
: impl_(new implementation)
|
||||||
{
|
{
|
||||||
impl_->thread.tid = 0;
|
impl_->thread_id = 0;
|
||||||
impl_->thread.ref = 0;
|
impl_->refs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
window_manager::revertible_mutex::~revertible_mutex()
|
window_manager::revertible_mutex::~revertible_mutex()
|
||||||
@ -305,20 +313,20 @@ namespace detail
|
|||||||
{
|
{
|
||||||
impl_->mutex.lock();
|
impl_->mutex.lock();
|
||||||
|
|
||||||
if(0 == impl_->thread.tid)
|
if (0 == impl_->thread_id)
|
||||||
impl_->thread.tid = nana::system::this_thread_id();
|
impl_->thread_id = nana::system::this_thread_id();
|
||||||
|
|
||||||
++(impl_->thread.ref);
|
++(impl_->refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool window_manager::revertible_mutex::try_lock()
|
bool window_manager::revertible_mutex::try_lock()
|
||||||
{
|
{
|
||||||
if(impl_->mutex.try_lock())
|
if (impl_->mutex.try_lock())
|
||||||
{
|
{
|
||||||
if (0 == impl_->thread.tid)
|
if (0 == impl_->thread_id)
|
||||||
impl_->thread.tid = nana::system::this_thread_id();
|
impl_->thread_id = nana::system::this_thread_id();
|
||||||
|
|
||||||
++(impl_->thread.ref);
|
++(impl_->refs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -326,24 +334,40 @@ namespace detail
|
|||||||
|
|
||||||
void window_manager::revertible_mutex::unlock()
|
void window_manager::revertible_mutex::unlock()
|
||||||
{
|
{
|
||||||
if(impl_->thread.tid == nana::system::this_thread_id())
|
if (impl_->thread_id == nana::system::this_thread_id())
|
||||||
if(0 == --(impl_->thread.ref))
|
if (0 == --(impl_->refs))
|
||||||
impl_->thread.tid = 0;
|
impl_->thread_id = 0;
|
||||||
|
|
||||||
impl_->mutex.unlock();
|
impl_->mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_manager::revertible_mutex::revert()
|
void window_manager::revertible_mutex::revert()
|
||||||
{
|
{
|
||||||
if(impl_->thread.tid == nana::system::this_thread_id())
|
if (impl_->thread_id == nana::system::this_thread_id())
|
||||||
{
|
{
|
||||||
std::size_t cnt = impl_->thread.ref;
|
auto const current_refs = impl_->refs;
|
||||||
|
|
||||||
impl_->records.push_back(impl_->thread);
|
//Check if there is a record
|
||||||
impl_->thread.tid = 0;
|
for (auto & r : impl_->records)
|
||||||
impl_->thread.ref = 0;
|
{
|
||||||
|
if (r.tid == impl_->thread_id)
|
||||||
|
{
|
||||||
|
r.callstack_refs.push_back(current_refs);
|
||||||
|
impl_->thread_id = 0; //Indicates a record is existing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < cnt; ++i)
|
if (impl_->thread_id)
|
||||||
|
{
|
||||||
|
//Creates a new record
|
||||||
|
impl_->records.emplace_back(impl_->thread_id, current_refs);
|
||||||
|
impl_->thread_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_->refs = 0;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < current_refs; ++i)
|
||||||
impl_->mutex.unlock();
|
impl_->mutex.unlock();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -353,8 +377,8 @@ namespace detail
|
|||||||
void window_manager::revertible_mutex::forward()
|
void window_manager::revertible_mutex::forward()
|
||||||
{
|
{
|
||||||
impl_->mutex.lock();
|
impl_->mutex.lock();
|
||||||
|
|
||||||
if(impl_->records.size())
|
if (impl_->records.size())
|
||||||
{
|
{
|
||||||
auto const this_tid = nana::system::this_thread_id();
|
auto const this_tid = nana::system::this_thread_id();
|
||||||
|
|
||||||
@ -363,11 +387,18 @@ namespace detail
|
|||||||
if (this_tid != i->tid)
|
if (this_tid != i->tid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (std::size_t u = 1; u < i->ref; ++u)
|
auto const refs = i->callstack_refs.back();
|
||||||
|
|
||||||
|
for (std::size_t u = 1; u < refs; ++u)
|
||||||
impl_->mutex.lock();
|
impl_->mutex.lock();
|
||||||
|
|
||||||
impl_->thread = *i;
|
impl_->thread_id = this_tid;
|
||||||
impl_->records.erase(i);
|
impl_->refs = refs;
|
||||||
|
|
||||||
|
if (i->callstack_refs.size() > 1)
|
||||||
|
i->callstack_refs.pop_back();
|
||||||
|
else
|
||||||
|
impl_->records.erase(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +407,7 @@ namespace detail
|
|||||||
|
|
||||||
impl_->mutex.unlock();
|
impl_->mutex.unlock();
|
||||||
}
|
}
|
||||||
//end class revertible_mutex
|
//end class revertible_mutex
|
||||||
|
|
||||||
//Utilities in this unit.
|
//Utilities in this unit.
|
||||||
namespace utl
|
namespace utl
|
||||||
|
Loading…
x
Reference in New Issue
Block a user