blob: 9550b6cd8adea0334035185929c757d866d6a8a3 [file]
//
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
// to allocate GL handles.
#include "libANGLE/HandleAllocator.h"
#include <algorithm>
#include <functional>
#include <limits>
#include "common/debug.h"
namespace gl
{
static constexpr bool kEnableHandleAllocatorLogging = false;
HandleAllocator::HandleAllocator() : HandleAllocator(std::numeric_limits<GLuint>::max()) {}
HandleAllocator::HandleAllocator(GLuint maximumHandleValue)
: mNextValue(1), mMaxValue(maximumHandleValue)
{}
HandleAllocator::~HandleAllocator() {}
void HandleAllocator::setBaseHandle(GLuint value)
{
mNextValue = std::max(mNextValue, value);
mReleasedList.remove_all_and_permute([value](GLuint x) { return x < value; });
}
GLuint HandleAllocator::allocate()
{
// Allocate from released list if possible
if (!mReleasedList.empty())
{
GLuint reusedHandle = mReleasedList.back();
mReleasedList.pop_back();
if (kEnableHandleAllocatorLogging)
{
WARN() << "HandleAllocator::allocate reusing " << reusedHandle << std::endl;
}
return reusedHandle;
}
// The next value may be reserved. Iterate until an unreserved value is found
if (!mReservedList.empty())
{
while (std::find(mReservedList.begin(), mReservedList.end(), mNextValue) !=
mReservedList.end())
{
mNextValue++;
}
}
GLuint nextHandle = mNextValue++;
if (kEnableHandleAllocatorLogging)
{
WARN() << "HandleAllocator::allocate allocating " << nextHandle << std::endl;
}
return nextHandle;
}
void HandleAllocator::release(GLuint handle)
{
if (kEnableHandleAllocatorLogging)
{
WARN() << "HandleAllocator::release releasing " << handle << std::endl;
}
mReleasedList.remove_all_and_permute([handle](GLuint x) { return x == handle; });
if (handle <= mNextValue)
{
mReleasedList.push_back(handle);
}
}
void HandleAllocator::reserve(GLuint handle)
{
if (kEnableHandleAllocatorLogging)
{
WARN() << "HandleAllocator::reserve reserving " << handle << std::endl;
}
mReservedList.push_back(handle);
mReleasedList.remove_all_and_permute([handle](GLuint x) { return x == handle; });
}
void HandleAllocator::reset()
{
mReservedList.clear();
mReleasedList.clear();
mNextValue = 1;
}
bool HandleAllocator::anyHandleAvailableForAllocation() const
{
return !mReleasedList.empty() || mNextValue < mMaxValue;
}
} // namespace gl