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