Yes, a standard binary heap will give you your requirements except the delete any in O(log n).
You can implement a skip list priority queue that has O(1) get max, O(log n) insertion, O(1) delete max, O(log n) delete any.
Pairing heap has O(1) get max, O(1) insertion, amortized O(log n) delete max. You can implement O(log n) (again, amortized) remove any with an additional data structure.
In my experience, pairing heap is much easier to implement than skip list.
For eviction notification, I would recommend computing an eviction time, and using that as the key in the priority queue. Then, I use a timer to notify me when it's time to call remove.
- At program startup, initialize a
nextRemovalTime
value to hold the next time an item should be removed. Set the initial value far into the future. Set a timer that will notify you at that time.
- To add an item to the queue, compute the expiration time by adding the TTL to the current time. Then insert the item into the queue.
- Compare the
nextRemovalTime
with the removal time for the item at the head of the queue.
- If the item at the head of the queue is earlier than
nextRemovalTime
, then cancel the existing timer, set nextRemovalTime
equal to the time the first node should be removed, and re-initialize the timer.
The idea here is that when the timer ticks, a background thread is created, and will remove the top item. And any other items whose time has expired. It then computes the new removal time and re-initializes the timer.
The drawback to that approach is that the priority queue data structure must be able to handle concurrent access. Typically that's a lock, unless you have a lock-free concurrent priority queue. It shouldn't be a problem, really, unless the queue is hit very frequently.
Another way to do it, if you're not terribly concerned about the queue growing too large, is to check for expired items whenever a new item is added or an existing item is removed. That is, insert becomes:
while (queue.peek().expirationTime < currentTime)
{
queue.removeMax();
}
queue.insert(newItem);