msgQ test: Use unordered_map (supported by C++11 std) if available
[charm.git] / tests / charm++ / queue / msgq.h
1 #ifndef MSG_Q_H
2 #define MSG_Q_H
3
4 #include <deque>
5 #include <queue>
6 #include <ostream>
7
8 #if CMK_HAS_STD_UNORDERED_MAP
9 #include <unordered_map>
10 #else
11 #include <map>
12 #endif
13
14 typedef void msg_t;
15
16 template <typename P>
17 inline P defaultprio(P *dummy_tag) { return 0; }
18
19
20 template <typename P = int>
21 class msgQ
22 {
23     public:
24         typedef P prio_t;
25
26         ///
27         msgQ(): qSize(0) {}
28         ///
29         void enq(const msg_t *msg
30                 ,const prio_t &prio = defaultprio<prio_t>(0)
31                 ,const bool isFifo = true
32                 );
33         ///
34         const msg_t* deq();
35         ///
36         const msg_t* front() const;
37         ///
38         inline size_t size() const { return qSize; }
39         ///
40         inline bool empty() const { return (0 == qSize); }
41         ///
42         inline prio_t top_priority() const { return prios.top(); }
43
44         ///
45         friend std::ostream& operator<< (std::ostream &out, const msgQ &q)
46         {
47             out <<"\nmsgQ[" << q.qSize << "]:";
48             out<<"\n";
49             return out;
50         }
51
52     private:
53         size_t qSize;
54         #if CMK_HAS_STD_UNORDERED_MAP
55         std::unordered_map<prio_t, std::deque<const msg_t*> > msgmap;
56         #else
57         std::map<prio_t, std::deque<const msg_t*> > msgmap;
58         #endif
59         std::priority_queue<prio_t, std::vector<prio_t>, std::greater<prio_t> > prios;
60 };
61
62
63
64 template <typename P>
65 void msgQ<P>::enq(const msg_t *msg
66                  ,const prio_t &prio
67                  ,const bool isFifo
68                  )
69 {
70     // Create or access deq holding msgs of this priority
71     std::deque<const msg_t*> &q = msgmap[prio];
72     // If this deq is empty, insert corresponding priority into prioQ
73     if (q.empty())
74         prios.push(prio);
75     // Enq msg either at front or back of deq
76     if (isFifo)
77         q.push_back(msg);
78     else
79         q.push_front(msg);
80     // Increment the total number of msgs in this container
81     qSize++;
82 }
83
84
85
86 template <typename P>
87 const msg_t* msgQ<P>::deq()
88 {
89     if (prios.empty())
90         return NULL;
91
92     // Get the top priority in the priority queue
93     const prio_t &prio = prios.top();
94
95     std::deque<const msg_t*> &q = msgmap[prio];
96     // Assert that there is at least one msg corresponding to this priority, in the msgmap
97     if (q.empty()) throw;
98     const msg_t *msg = q.front();
99     q.pop_front();
100     // If all msgs of the highest priority have been consumed, pop that priority from the priority Q
101     if (q.empty())
102         prios.pop();
103     // Decrement the total number of msgs in this container
104     qSize--;
105     return msg;
106 }
107
108
109
110 template <typename P>
111 const msg_t* msgQ<P>::front() const
112 {
113     if (prios.empty())
114         return NULL;
115     prio_t &prio = prios.top();
116     return msgmap[prio].front();
117 }
118
119 #endif // MSG_Q_H
120