I want to implement a timer queuing system using the C++ STL priority_queue container adapter.
My problem is that I want to occasionally cancel a timer, however there are no interfaces that enable me to easily delete an item in the priority_queue that is not the top item.
Any suggestions?.
Thank you for your help.
I had the exact same scenario once and did the following:
std::priority_queue
contained only the time to sort by and an index to a std::vector<Handler>
(in my case Handler
was boost::function
, but could as well be pointer to interface or function) boost::function
call clear()
, if using pointers, set it to zero) 1 To make finding a free index fast, I used a separate std::stack
of indices. When adding a timer and that stack is empty, add at the end of vector; otherwise pop the top index and use it.
2 Here's the point when you push the index to the free indices stack
The whole thing is somewhat tricky and error-prone, especially if your timer callbacks need to add or cancel timers. Here's a link to my canceling timer class described above, this code is public domain
I'm afraid STL priority_queue
doesn't offer such functionality. You can write your own heap class (which is not that hard). You could even use the std::xxx_heap
functions by dirty tricks like this:
delete_heap(iterator to_delete, iterator heap_begin, iterator heap_end)
{
to_delete->key = something that would compare less to everything; // make sure it gets to the top in the next step
std::push_heap(heap_begin, to_delete+1);
std::pop_heap(heap_begin, heap_end);
}
which will get you O(log n)
delete.
Despite what some other answers say, it is possible to access the underlying container of any standard container adapter, including priority_queue
, since the container is exposed as a protected member called c
. You can either inherit from priority_queue
and extend the interface, or use dirty tricks such as this to temporarily gain access to a normal priority_queue
.
My problem is that I want to occasionally cancel a timer, however there are no interfaces that enable me to easily delete an item in the priority_queue that is not the top item.
If canceling a timer happens often, then you need to use some different structure. std::map isn't that bad too, though cost of delete_min would go up.
If canceling a timer happens rarely, then marking the element as deleted (and ignoring it during ::pop) might do the trick.
STL priority_queue容器是专门设计的,因此只能访问顶级项目,因此如果您需要能够删除非顶级项目,则必须找到要使用的其他类。
I had the same requirement. If you have the freedom to change the container, the one that can solve this problem is std::set (no duplicates allowed) or std::multiset .
Both are ordered and can erase an element logarithmic in container size (see the documentation for details). For help in deleting in multi set you might want to see this .
See the difference std::set vs std::priority_queue before deciding.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.