// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
|
//
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
// you may not use this file except in compliance with the License.
|
// You may obtain a copy of the License at
|
//
|
// http://www.apache.org/licenses/LICENSE-2.0
|
//
|
// Unless required by applicable law or agreed to in writing, software
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// See the License for the specific language governing permissions and
|
// limitations under the License.
|
|
#include "Resource.hpp"
|
|
#include "Memory.hpp"
|
#include "Debug.hpp"
|
|
namespace sw
|
{
|
Resource::Resource(size_t bytes) : size(bytes)
|
{
|
blocked = 0;
|
|
accessor = PUBLIC;
|
count = 0;
|
orphaned = false;
|
|
buffer = allocate(bytes);
|
}
|
|
Resource::~Resource()
|
{
|
deallocate(buffer);
|
}
|
|
void *Resource::lock(Accessor claimer)
|
{
|
criticalSection.lock();
|
|
while(count > 0 && accessor != claimer)
|
{
|
blocked++;
|
criticalSection.unlock();
|
|
unblock.wait();
|
|
criticalSection.lock();
|
blocked--;
|
}
|
|
accessor = claimer;
|
count++;
|
|
criticalSection.unlock();
|
|
return buffer;
|
}
|
|
void *Resource::lock(Accessor relinquisher, Accessor claimer)
|
{
|
criticalSection.lock();
|
|
// Release
|
while(count > 0 && accessor == relinquisher)
|
{
|
count--;
|
|
if(count == 0)
|
{
|
if(blocked)
|
{
|
unblock.signal();
|
}
|
else if(orphaned)
|
{
|
criticalSection.unlock();
|
|
delete this;
|
|
return 0;
|
}
|
}
|
}
|
|
// Acquire
|
while(count > 0 && accessor != claimer)
|
{
|
blocked++;
|
criticalSection.unlock();
|
|
unblock.wait();
|
|
criticalSection.lock();
|
blocked--;
|
}
|
|
accessor = claimer;
|
count++;
|
|
criticalSection.unlock();
|
|
return buffer;
|
}
|
|
void Resource::unlock()
|
{
|
criticalSection.lock();
|
ASSERT(count > 0);
|
|
count--;
|
|
if(count == 0)
|
{
|
if(blocked)
|
{
|
unblock.signal();
|
}
|
else if(orphaned)
|
{
|
criticalSection.unlock();
|
|
delete this;
|
|
return;
|
}
|
}
|
|
criticalSection.unlock();
|
}
|
|
void Resource::unlock(Accessor relinquisher)
|
{
|
criticalSection.lock();
|
ASSERT(count > 0);
|
|
while(count > 0 && accessor == relinquisher)
|
{
|
count--;
|
|
if(count == 0)
|
{
|
if(blocked)
|
{
|
unblock.signal();
|
}
|
else if(orphaned)
|
{
|
criticalSection.unlock();
|
|
delete this;
|
|
return;
|
}
|
}
|
}
|
|
criticalSection.unlock();
|
}
|
|
void Resource::destruct()
|
{
|
criticalSection.lock();
|
|
if(count == 0 && !blocked)
|
{
|
criticalSection.unlock();
|
|
delete this;
|
|
return;
|
}
|
|
orphaned = true;
|
|
criticalSection.unlock();
|
}
|
|
const void *Resource::data() const
|
{
|
return buffer;
|
}
|
}
|