tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HandleAllocator.cpp (4749B)


      1 //
      2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
      8 // to allocate GL handles.
      9 
     10 #include "libANGLE/HandleAllocator.h"
     11 
     12 #include <algorithm>
     13 #include <functional>
     14 #include <limits>
     15 
     16 #include "common/debug.h"
     17 
     18 namespace gl
     19 {
     20 
     21 struct HandleAllocator::HandleRangeComparator
     22 {
     23    bool operator()(const HandleRange &range, GLuint handle) const { return (range.end < handle); }
     24 };
     25 
     26 HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1), mLoggingEnabled(false)
     27 {
     28    mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max()));
     29 }
     30 
     31 HandleAllocator::HandleAllocator(GLuint maximumHandleValue)
     32    : mBaseValue(1), mNextValue(1), mLoggingEnabled(false)
     33 {
     34    mUnallocatedList.push_back(HandleRange(1, maximumHandleValue));
     35 }
     36 
     37 HandleAllocator::~HandleAllocator() {}
     38 
     39 void HandleAllocator::setBaseHandle(GLuint value)
     40 {
     41    ASSERT(mBaseValue == mNextValue);
     42    mBaseValue = value;
     43    mNextValue = value;
     44 }
     45 
     46 GLuint HandleAllocator::allocate()
     47 {
     48    ASSERT(!mUnallocatedList.empty() || !mReleasedList.empty());
     49 
     50    // Allocate from released list, logarithmic time for pop_heap.
     51    if (!mReleasedList.empty())
     52    {
     53        std::pop_heap(mReleasedList.begin(), mReleasedList.end(), std::greater<GLuint>());
     54        GLuint reusedHandle = mReleasedList.back();
     55        mReleasedList.pop_back();
     56 
     57        if (mLoggingEnabled)
     58        {
     59            WARN() << "HandleAllocator::allocate reusing " << reusedHandle << std::endl;
     60        }
     61 
     62        return reusedHandle;
     63    }
     64 
     65    // Allocate from unallocated list, constant time.
     66    auto listIt = mUnallocatedList.begin();
     67 
     68    GLuint freeListHandle = listIt->begin;
     69    ASSERT(freeListHandle > 0);
     70 
     71    if (listIt->begin == listIt->end)
     72    {
     73        mUnallocatedList.erase(listIt);
     74    }
     75    else
     76    {
     77        listIt->begin++;
     78    }
     79 
     80    if (mLoggingEnabled)
     81    {
     82        WARN() << "HandleAllocator::allocate allocating " << freeListHandle << std::endl;
     83    }
     84 
     85    return freeListHandle;
     86 }
     87 
     88 void HandleAllocator::release(GLuint handle)
     89 {
     90    if (mLoggingEnabled)
     91    {
     92        WARN() << "HandleAllocator::release releasing " << handle << std::endl;
     93    }
     94 
     95    // Try consolidating the ranges first.
     96    for (HandleRange &handleRange : mUnallocatedList)
     97    {
     98        if (handleRange.begin - 1 == handle)
     99        {
    100            handleRange.begin--;
    101            return;
    102        }
    103 
    104        if (handleRange.end == handle - 1)
    105        {
    106            handleRange.end++;
    107            return;
    108        }
    109    }
    110 
    111    // Add to released list, logarithmic time for push_heap.
    112    mReleasedList.push_back(handle);
    113    std::push_heap(mReleasedList.begin(), mReleasedList.end(), std::greater<GLuint>());
    114 }
    115 
    116 void HandleAllocator::reserve(GLuint handle)
    117 {
    118    if (mLoggingEnabled)
    119    {
    120        WARN() << "HandleAllocator::reserve reserving " << handle << std::endl;
    121    }
    122 
    123    // Clear from released list -- might be a slow operation.
    124    if (!mReleasedList.empty())
    125    {
    126        auto releasedIt = std::find(mReleasedList.begin(), mReleasedList.end(), handle);
    127        if (releasedIt != mReleasedList.end())
    128        {
    129            mReleasedList.erase(releasedIt);
    130            std::make_heap(mReleasedList.begin(), mReleasedList.end(), std::greater<GLuint>());
    131            return;
    132        }
    133    }
    134 
    135    // Not in released list, reserve in the unallocated list.
    136    auto boundIt = std::lower_bound(mUnallocatedList.begin(), mUnallocatedList.end(), handle,
    137                                    HandleRangeComparator());
    138 
    139    ASSERT(boundIt != mUnallocatedList.end());
    140 
    141    GLuint begin = boundIt->begin;
    142    GLuint end   = boundIt->end;
    143 
    144    if (handle == begin || handle == end)
    145    {
    146        if (begin == end)
    147        {
    148            mUnallocatedList.erase(boundIt);
    149        }
    150        else if (handle == begin)
    151        {
    152            boundIt->begin++;
    153        }
    154        else
    155        {
    156            ASSERT(handle == end);
    157            boundIt->end--;
    158        }
    159        return;
    160    }
    161 
    162    ASSERT(begin < handle && handle < end);
    163 
    164    // need to split the range
    165    auto placementIt = mUnallocatedList.erase(boundIt);
    166    placementIt      = mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end));
    167    mUnallocatedList.insert(placementIt, HandleRange(begin, handle - 1));
    168 }
    169 
    170 void HandleAllocator::reset()
    171 {
    172    mUnallocatedList.clear();
    173    mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max()));
    174    mReleasedList.clear();
    175    mBaseValue = 1;
    176    mNextValue = 1;
    177 }
    178 
    179 void HandleAllocator::enableLogging(bool enabled)
    180 {
    181    mLoggingEnabled = enabled;
    182 }
    183 
    184 }  // namespace gl