blob: 0e8dcfd4966f837c26496ec0b0d9a7af394567d0 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.
*/
#ifndef ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H
#define ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H
#include <utils/Log.h>
#include <functional>
#include <iostream>
#include <vector>
namespace android {
/*
* AdjustableMaxPriorityQueue is a custom max priority queue that helps managing jobs for
* MediaTranscodingService.
*
* AdjustableMaxPriorityQueue is a wrapper template around the STL's *_heap() functions.
* - Internally, it uses a std::vector<T> to store elements in a heap order.
* - Support adjusting item's priority while maintaining the heap property.
* - Support removing any item in the heap while maintaining the heap property. Note that the
* removal complexity will be O(n) in worst case.
* - AdjustableMaxPriorityQueue needs T::operator<() at instantiation time
*/
template <class T, class Comparator = std::less<T>>
class AdjustableMaxPriorityQueue {
public:
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
AdjustableMaxPriorityQueue();
/* Whether the queue is empty. */
bool empty() const;
/* Number of items in the queue. */
int size() const;
/* Return the top element in the queue. The queue still owns the element. */
const T& top() const;
/* Discards the element with highest value based on the given comparator. */
void pop();
/* Erases all the elements in the queue. */
void clear();
/*
* Returns the element with the highest value based on the given comparator. Queue transfer the
* ownership of the item to the caller. Client MUST call empty() to check whether there is
* element at the top before calling this.
*/
T consume_top();
/* Adds an element to the heap. The queue will make a deep copy of the element. */
bool push(const T& item) { return pushInternal(item); }
/* Adds an element to the heap. The queue will take ownership of the element. */
bool push(T&& item) { return pushInternal(std::move(item)); }
/* Adds a new element to the AdjustableMaxPriorityQueue. This new element is constructed in
* place passing args as the arguments for its constructor. */
template <class... Args>
bool emplace(Args&&... args);
/* Remove an element from a AdjustableMaxPriorityQueue. */
void erase(iterator pos);
/*
* Rebuild a heap based on the given comparator. This MUST be called after changing the value
* of items.
*/
void rebuild();
/*
* Iterators used for accessing and changing the priority.
* If you change the value of items through these access iterators BE SURE to call rebuild() to
* ensure the integrity of the heap is maintained.
* NOTE: The iterator pos will change after calling rebuild().
*/
const iterator begin();
const iterator end();
/*
* Iterators used for accessing the priority.
*/
const const_iterator begin() const;
const const_iterator end() const;
/* Return the backbone storage of this PriorityQueue. Mainly used for debugging. */
const std::vector<T>& getStorage() const { return mHeap; };
private:
std::vector<T> mHeap;
/* Implementation shared by both public push() methods. */
template <class Arg>
bool pushInternal(Arg&& item);
};
template <class T, class Comparator>
AdjustableMaxPriorityQueue<T, Comparator>::AdjustableMaxPriorityQueue() {}
template <class T, class Comparator>
bool AdjustableMaxPriorityQueue<T, Comparator>::empty() const {
return mHeap.empty();
}
template <class T, class Comparator>
int AdjustableMaxPriorityQueue<T, Comparator>::size() const {
return mHeap.size();
}
template <class T, class Comparator>
const T& AdjustableMaxPriorityQueue<T, Comparator>::top() const {
DCHECK(!mHeap.empty());
return mHeap.front();
}
// Compares elements and potentially swaps (or moves) them until rearranged as a longer heap.
// Complexity of this: Up to logarithmic in the distance between first and last.
template <class T, class Comparator>
template <class Arg>
bool AdjustableMaxPriorityQueue<T, Comparator>::pushInternal(Arg&& item) {
mHeap.push_back(std::forward<Arg>(item));
std::push_heap(mHeap.begin(), mHeap.end(), Comparator());
return true;
}
template <class T, class Comparator>
template <class... Args>
bool AdjustableMaxPriorityQueue<T, Comparator>::emplace(Args&&... args) {
mHeap.emplace_back(std::forward<Args>(args)...);
std::push_heap(mHeap.begin(), mHeap.end(), Comparator());
return true;
}
// Compares elements and potentially swaps (or moves) them until rearranged as a shorter heap.
// Complexity of this: Up to twice logarithmic in the distance between first and last.
template <class T, class Comparator>
void AdjustableMaxPriorityQueue<T, Comparator>::pop() {
DCHECK(!mHeap.empty());
std::pop_heap(mHeap.begin(), mHeap.end(), Comparator());
mHeap.pop_back();
}
// Compares elements and potentially swaps (or moves) them until rearranged as a shorter heap.
// Complexity of this: Up to twice logarithmic in the distance between first and last.
template <class T, class Comparator>
T AdjustableMaxPriorityQueue<T, Comparator>::consume_top() {
DCHECK(!mHeap.empty());
std::pop_heap(mHeap.begin(), mHeap.end(), Comparator());
T to_return = std::move(mHeap.back());
mHeap.pop_back();
return to_return;
}
template <class T, class Comparator>
const typename AdjustableMaxPriorityQueue<T, Comparator>::iterator
AdjustableMaxPriorityQueue<T, Comparator>::begin() {
return mHeap.begin();
}
template <class T, class Comparator>
const typename AdjustableMaxPriorityQueue<T, Comparator>::iterator
AdjustableMaxPriorityQueue<T, Comparator>::end() {
return mHeap.end();
}
template <class T, class Comparator>
const typename AdjustableMaxPriorityQueue<T, Comparator>::const_iterator
AdjustableMaxPriorityQueue<T, Comparator>::begin() const {
return mHeap.begin();
}
template <class T, class Comparator>
const typename AdjustableMaxPriorityQueue<T, Comparator>::const_iterator
AdjustableMaxPriorityQueue<T, Comparator>::end() const {
return mHeap.end();
}
template <class T, class Comparator>
void AdjustableMaxPriorityQueue<T, Comparator>::clear() {
mHeap.erase(mHeap.begin(), mHeap.end());
}
// Complexity of this: At most 3*std::distance(first, last) comparisons.
template <class T, class Comparator>
void AdjustableMaxPriorityQueue<T, Comparator>::rebuild() {
std::make_heap(mHeap.begin(), mHeap.end(), Comparator());
}
// Remove a random element from a AdjustableMaxPriorityQueue.
template <class T, class Comparator>
void AdjustableMaxPriorityQueue<T, Comparator>::erase(iterator pos) {
DCHECK(!mHeap.empty());
mHeap.erase(pos);
rebuild();
}
} // namespace android
#endif // ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H