2ab1d8e9d8cdf8841f27aeff8d4259147f3a74c5
[charm.git] / src / conv-core / 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         void enumerate(msg_t **first, msg_t **last) const;
46         ///
47         friend std::ostream& operator<< (std::ostream &out, const msgQ &q)
48         {
49             out <<"\nmsgQ[" << q.qSize << "]:";
50             out<<"\n";
51             return out;
52         }
53
54     private:
55         ///
56         size_t qSize;
57         ///
58         #if CMK_HAS_STD_UNORDERED_MAP
59         std::unordered_map<prio_t, std::deque<const msg_t*> > msgmap;
60         typedef typename std::unordered_map<prio_t, std::deque<const msg_t*> >::iterator msgmapitr_t;
61         typedef typename std::unordered_map<prio_t, std::deque<const msg_t*> >::const_iterator msgmapconstitr_t;
62         #else
63         std::map<prio_t, std::deque<const msg_t*> > msgmap;
64         typedef typename std::map<prio_t, std::deque<const msg_t*> >::iterator msgmapitr_t;
65         typedef typename std::map<prio_t, std::deque<const msg_t*> >::const_iterator msgmapconstitr_t;
66         #endif
67         ///
68         std::priority_queue<prio_t, std::vector<prio_t>, std::greater<prio_t> > prios;
69 };
70
71
72
73 template <typename P>
74 void msgQ<P>::enq(const msg_t *msg
75                  ,const prio_t &prio
76                  ,const bool isFifo
77                  )
78 {
79     // Create or access deq holding msgs of this priority
80     std::deque<const msg_t*> &q = msgmap[prio];
81     // If this deq is empty, insert corresponding priority into prioQ
82     if (q.empty())
83         prios.push(prio);
84     // Enq msg either at front or back of deq
85     if (isFifo)
86         q.push_back(msg);
87     else
88         q.push_front(msg);
89     // Increment the total number of msgs in this container
90     qSize++;
91 }
92
93
94
95 template <typename P>
96 const msg_t* msgQ<P>::deq()
97 {
98     if (prios.empty())
99         return NULL;
100
101     // Get the top priority in the priority queue
102     const prio_t &prio = prios.top();
103
104     std::deque<const msg_t*> &q = msgmap[prio];
105     // Assert that there is at least one msg corresponding to this priority, in the msgmap
106     if (q.empty()) throw;
107     const msg_t *msg = q.front();
108     q.pop_front();
109     // If all msgs of the highest priority have been consumed, pop that priority from the priority Q
110     if (q.empty())
111         prios.pop();
112     // Decrement the total number of msgs in this container
113     qSize--;
114     return msg;
115 }
116
117
118
119 template <typename P>
120 const msg_t* msgQ<P>::front() const
121 {
122     if (prios.empty())
123         return NULL;
124     prio_t &prio = prios.top();
125     return msgmap[prio].front();
126 }
127
128
129
130 template <typename P>
131 void msgQ<P>::enumerate(msg_t **first, msg_t **last) const
132 {
133     if (first >= last)
134         return;
135
136     msg_t **ptr = first;
137     msgmapconstitr_t mapitr = msgmap.begin();
138     while (ptr != last && mapitr != msgmap.end())
139     {
140         std::deque<const msg_t*>::const_iterator itr = mapitr->second.begin();
141         while (ptr != last && itr != mapitr->second.end())
142             *ptr++ = (msg_t*) *itr++;
143         mapitr++;
144     }
145 }
146
147 #endif // MSG_Q_H
148