2020-01-15 04:47:11 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
|
|
|
//
|
|
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
#include <vtkm/cont/Token.h>
|
|
|
|
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
using LockType = std::unique_lock<std::mutex>;
|
|
|
|
|
|
|
|
class vtkm::cont::Token::InternalStruct
|
|
|
|
{
|
|
|
|
std::mutex Mutex;
|
|
|
|
std::list<vtkm::cont::Token::HeldReference> HeldReferences;
|
|
|
|
|
|
|
|
VTKM_CONT void CheckLock(const LockType& lock) const
|
|
|
|
{
|
|
|
|
VTKM_ASSERT((lock.mutex() == &this->Mutex) && (lock.owns_lock()));
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
LockType GetLock() { return LockType(this->Mutex); }
|
|
|
|
std::list<vtkm::cont::Token::HeldReference>* GetHeldReferences(const LockType& lock)
|
|
|
|
{
|
|
|
|
this->CheckLock(lock);
|
|
|
|
return &this->HeldReferences;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct vtkm::cont::Token::HeldReference
|
|
|
|
{
|
|
|
|
std::unique_ptr<vtkm::cont::Token::ObjectReference> ObjectReference;
|
|
|
|
vtkm::cont::Token::ReferenceCount* ReferenceCountPointer;
|
|
|
|
std::mutex* MutexPointer;
|
|
|
|
std::condition_variable* ConditionVariablePointer;
|
|
|
|
|
|
|
|
HeldReference(std::unique_ptr<vtkm::cont::Token::ObjectReference>&& objRef,
|
|
|
|
vtkm::cont::Token::ReferenceCount* refCountP,
|
|
|
|
std::mutex* mutexP,
|
|
|
|
std::condition_variable* conditionVariableP)
|
|
|
|
: ObjectReference(std::move(objRef))
|
|
|
|
, ReferenceCountPointer(refCountP)
|
|
|
|
, MutexPointer(mutexP)
|
|
|
|
, ConditionVariablePointer(conditionVariableP)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
vtkm::cont::Token::Token()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-01-24 01:01:30 +00:00
|
|
|
vtkm::cont::Token::Token(Token&& rhs)
|
|
|
|
: Internals(std::move(rhs.Internals))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-01-15 04:47:11 +00:00
|
|
|
vtkm::cont::Token::~Token()
|
|
|
|
{
|
|
|
|
this->DetachFromAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void vtkm::cont::Token::DetachFromAll()
|
|
|
|
{
|
2020-01-27 22:57:40 +00:00
|
|
|
if (!this->Internals)
|
|
|
|
{
|
|
|
|
// If internals is NULL, then we are not attached to anything.
|
|
|
|
return;
|
|
|
|
}
|
2020-01-15 04:47:11 +00:00
|
|
|
LockType localLock = this->Internals->GetLock();
|
|
|
|
auto heldReferences = this->Internals->GetHeldReferences(localLock);
|
|
|
|
for (auto&& held : *heldReferences)
|
|
|
|
{
|
|
|
|
LockType objectLock(*held.MutexPointer);
|
|
|
|
*held.ReferenceCountPointer -= 1;
|
|
|
|
objectLock.unlock();
|
|
|
|
held.ConditionVariablePointer->notify_all();
|
|
|
|
}
|
|
|
|
heldReferences->clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void vtkm::cont::Token::Attach(std::unique_ptr<vtkm::cont::Token::ObjectReference>&& objectRef,
|
|
|
|
vtkm::cont::Token::ReferenceCount* referenceCountPointer,
|
2020-01-16 00:50:53 +00:00
|
|
|
std::unique_lock<std::mutex>& lock,
|
2020-01-15 04:47:11 +00:00
|
|
|
std::condition_variable* conditionVariablePointer)
|
|
|
|
{
|
2020-01-27 22:57:40 +00:00
|
|
|
if (!this->Internals)
|
|
|
|
{
|
|
|
|
this->Internals.reset(new InternalStruct);
|
|
|
|
}
|
2020-01-15 04:47:11 +00:00
|
|
|
LockType localLock = this->Internals->GetLock();
|
2020-01-19 22:50:48 +00:00
|
|
|
if (this->IsAttached(localLock, referenceCountPointer))
|
|
|
|
{
|
|
|
|
// Already attached.
|
|
|
|
return;
|
|
|
|
}
|
2020-01-16 00:50:53 +00:00
|
|
|
if (!lock.owns_lock())
|
|
|
|
{
|
|
|
|
lock.lock();
|
|
|
|
}
|
2020-01-15 04:47:11 +00:00
|
|
|
*referenceCountPointer += 1;
|
|
|
|
this->Internals->GetHeldReferences(localLock)->emplace_back(
|
2020-01-16 00:50:53 +00:00
|
|
|
std::move(objectRef), referenceCountPointer, lock.mutex(), conditionVariablePointer);
|
2020-01-15 04:47:11 +00:00
|
|
|
}
|
2020-01-19 22:50:48 +00:00
|
|
|
|
|
|
|
inline bool vtkm::cont::Token::IsAttached(
|
|
|
|
LockType& lock,
|
|
|
|
vtkm::cont::Token::ReferenceCount* referenceCountPointer) const
|
|
|
|
{
|
2020-01-27 22:57:40 +00:00
|
|
|
if (!this->Internals)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-01-19 22:50:48 +00:00
|
|
|
for (auto&& heldReference : *this->Internals->GetHeldReferences(lock))
|
|
|
|
{
|
|
|
|
if (referenceCountPointer == heldReference.ReferenceCountPointer)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool vtkm::cont::Token::IsAttached(vtkm::cont::Token::ReferenceCount* referenceCountPointer) const
|
|
|
|
{
|
2020-01-27 22:57:40 +00:00
|
|
|
if (!this->Internals)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-01-19 22:50:48 +00:00
|
|
|
LockType lock = this->Internals->GetLock();
|
|
|
|
return this->IsAttached(lock, referenceCountPointer);
|
|
|
|
}
|