// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file contains the implementation of IdAllocator.

#include "gpu/command_buffer/common/id_allocator.h"

#include <stdint.h>

#include <limits>
#include "base/logging.h"

namespace gpu {

IdAllocator::IdAllocator() {
  static_assert(kInvalidResource == 0u, "kInvalidResource must be 0");
  // Simplify the code by making sure that lower_bound(id) never
  // returns the beginning of the map, if id is valid (eg !=
  // kInvalidResource).
  used_ids_.insert(std::make_pair(0u, 0u));
}

IdAllocator::~IdAllocator() {}

ResourceId IdAllocator::AllocateID() {
  return AllocateIDRange(1u);
}

ResourceId IdAllocator::AllocateIDAtOrAbove(ResourceId desired_id) {
  if (desired_id == 0u || desired_id == 1u) {
    return AllocateIDRange(1u);
  }

  ResourceIdRangeMap::iterator current = used_ids_.lower_bound(desired_id);
  ResourceIdRangeMap::iterator next = current;
  if (current == used_ids_.end() || current->first > desired_id) {
    current--;
  } else {
    next++;
  }

  ResourceId first_id = current->first;
  ResourceId last_id = current->second;

  DCHECK(desired_id >= first_id);

  if (desired_id - 1u <= last_id) {
    // Append to current range.
    last_id++;
    if (last_id == 0) {
      // The increment overflowed.
      return AllocateIDRange(1u);
    }

    current->second = last_id;

    if (next != used_ids_.end() && next->first - 1u == last_id) {
      // Merge with next range.
      current->second = next->second;
      used_ids_.erase(next);
    }
    return last_id;
  } else if (next != used_ids_.end() && next->first - 1u == desired_id) {
    // Prepend to next range.
    ResourceId last_existing_id = next->second;
    used_ids_.erase(next);
    used_ids_.insert(std::make_pair(desired_id, last_existing_id));
    return desired_id;
  }
  used_ids_.insert(std::make_pair(desired_id, desired_id));
  return desired_id;
}

ResourceId IdAllocator::AllocateIDRange(uint32_t range) {
  DCHECK(range > 0u);

  ResourceIdRangeMap::iterator current = used_ids_.begin();
  ResourceIdRangeMap::iterator next = current;

  while (++next != used_ids_.end()) {
    if (next->first - current->second > range) {
      break;
    }
    current = next;
  }

  ResourceId first_id = current->second + 1u;
  ResourceId last_id = first_id + range - 1u;

  if (first_id == 0u || last_id < first_id) {
    return kInvalidResource;
  }

  current->second = last_id;

  if (next != used_ids_.end() && next->first - 1u == last_id) {
    // Merge with next range.
    current->second = next->second;
    used_ids_.erase(next);
  }

  return first_id;
}

bool IdAllocator::MarkAsUsed(ResourceId id) {
  DCHECK(id);
  ResourceIdRangeMap::iterator current = used_ids_.lower_bound(id);
  if (current != used_ids_.end() && current->first == id) {
    return false;
  }

  ResourceIdRangeMap::iterator next = current;
  --current;

  if (current->second >= id) {
    return false;
  }

  DCHECK(current->first < id && current->second < id);

  if (current->second + 1u == id) {
    // Append to current range.
    current->second = id;
    if (next != used_ids_.end() && next->first - 1u == id) {
      // Merge with next range.
      current->second = next->second;
      used_ids_.erase(next);
    }
    return true;
  } else if (next != used_ids_.end() && next->first - 1u == id) {
    // Prepend to next range.
    ResourceId last_existing_id = next->second;
    used_ids_.erase(next);
    used_ids_.insert(std::make_pair(id, last_existing_id));
    return true;
  }

  used_ids_.insert(std::make_pair(id, id));
  return true;
}

void IdAllocator::FreeID(ResourceId id) {
  FreeIDRange(id, 1u);
}

void IdAllocator::FreeIDRange(ResourceId first_id, uint32_t range) {
  static_assert(kInvalidResource == 0u, "kInvalidResource must be 0");

  if (range == 0u || (first_id == 0u && range == 1u)) {
    return;
  }

  if (first_id == 0u) {
    first_id++;
    range--;
  }

  ResourceId last_id = first_id + range - 1u;
  if (last_id < first_id) {
    last_id = std::numeric_limits<ResourceId>::max();
  }

  while (true) {
    ResourceIdRangeMap::iterator current = used_ids_.lower_bound(last_id);
    if (current == used_ids_.end() || current->first > last_id) {
      --current;
    }

    if (current->second < first_id) {
      return;
    }

    if (current->first >= first_id) {
      ResourceId last_existing_id = current->second;
      used_ids_.erase(current);
      if (last_id < last_existing_id) {
        used_ids_.insert(std::make_pair(last_id + 1u, last_existing_id));
      }
    } else if (current->second <= last_id) {
      current->second = first_id - 1u;
    } else {
      DCHECK(current->first < first_id && current->second > last_id);
      ResourceId last_existing_id = current->second;
      current->second = first_id - 1u;
      used_ids_.insert(std::make_pair(last_id + 1u, last_existing_id));
    }
  }
}

bool IdAllocator::InUse(ResourceId id) const {
  if (id == kInvalidResource) {
    return false;
  }

  ResourceIdRangeMap::const_iterator current = used_ids_.lower_bound(id);
  if (current != used_ids_.end()) {
    if (current->first == id) {
      return true;
    }
  }

  --current;
  return current->second >= id;
}

}  // namespace gpu
