|
BDE 4.14.0 Production release
|
Provide container adapter class template priority_queue .
Canonical header: bsl_queue.h
This component defines a class template, bsl::priority_queue, holding a container (of a template parameter type, CONTAINER, containing elements of another template parameter type, VALUE), and adapting it to provide highest-priority-first priority queue data structure. The component takes a third template parameter type, COMPARATOR, for customized priorities comparison between two elements.
An instantiation of priority_queue is an allocator-aware, value-semantic type whose salient attributes are its size (number of held elements) and the sorted sequence of values (of held elements). If priority_queue is instantiated with a value type, that is not itself value-semantic, then it will not retain all of its value-semantic qualities. A priority_queue cannot be tested for equality, but its value type must be able to be tested for comparing less by its comparator type.
The priority_queue implemented here adheres to the C++11 standard when compiled with a C++11 compiler, and makes the best approximation when compiled with a C++03 compiler. In particular, for C++03 we emulate move semantics, but limit forwarding (in emplace) to const lvalues, and make no effort to emulate noexcept or initializer-lists.
The type supplied as an ALLOCATOR template parameter in some of priority_queue constructors determines how the held container (of the (template parameter) type CONTAINER) will allocate memory. A priority_queue supports allocators meeting the requirements of the C++11 standard [17.6.3.5] as long as the held container does. In addition it supports scoped-allocators derived from the bslma::Allocator memory allocation protocol. Clients intending to use bslma-style allocators should use bsl::allocator as the ALLOCATOR template parameter, providing a C++11 standard-compatible adapter for a bslma::Allocator object.
When the CONTAINER template parameter is omitted the VALUE template parameter specifies the value_type of bsl::vector, the default container type. The VALUE template has no other role.
For C++17 and later, the behavior is undefined unless:
Prior to C++17, CONTAINER::value_type determines the contained value type and VALUE is simply ignored. The resulting code may work with instances of VALUE (e.g., VALUE is convertible to CONTAINER::value_type) or not (compiler errors).
The C++11 standard [23.6.4] declares any container type supporting operations front, push_back, and pop_back can be used to instantiate the (template parameter) type CONTAINER. Below is a list of public methods of priority_queue class that are effectively implemented as calling the corresponding operations in the held container (referenced as c).
In this section we show intended use of this component.
In this example, we will use the bsl::priority_queue class to implement a task scheduler that schedules a group of tasks based on their designated priorities.
Suppose we want to write a background process that runs tasks needed by foreground applications. Each task has a task id, a priority, and a function pointer that can be invoked by the background process. This background process has two threads: one thread (receiving thread) receives requests from other applications, passing required tasks to a task scheduler; the other thread (processing thread) runs the task scheduler, executing the tasks one-by-one from higher to lower priorities. To implement this functionality, we can use bsl::priority_queue in the task scheduler to buffer received, but as yet unprocessed, tasks. The task scheduler adds newly received tasks into the priority queue in the receiving thread, and extracts tasks from the priority queue for execution according to their priorities in the processing thread.
First, we define a TaskFunction type:
Then, we define a Task class, which contains a task id, a TaskFunction object and an associated task priority:
Next, we define a functor to compare the priorities of two Task objects:
Then, we define a TaskScheduler class that provides methods to hold and schedule unprocessed tasks:
Here, we define a private data member that is an instantiation of bsl::priority_queue, which uses Task for its VALUE (template parameter) type, bsl::vector<Task> for its CONTAINER (template parameter) type, and TaskComparator for its COMPARATOR (template parameter) type:
Next, we implement the TaskScheduler constructor:
Notice that we pass to the contained d_taskPriorityQueue object the bslma::Allocator supplied to the TaskScheduler at construction.
Then, we implement the addTask method, which constructs a Task object and adds it into the priority queue:
Next, we implement the processTasks method, which extracts tasks from the priority queue in order of descending priorities, and executes them:
Note that the top method always returns the Task object having the highest priority in the priority queue.
Then, we define two task functions:
Next, we create a global TaskScheduler object:
Now, we call the addTask method of taskScheduler in the receiving thread:
Finally, we call the processTasks method of taskScheduler in the processing thread: