I have a strange problem in c++ with this code:
mutex_type list_mutex;
typedef list<char*> RQueue;
RQueue rQueue;
RQueue::reverse_iterator rstart, rend, last;
1 while(true) {
2 LockMutex(list_mutex);
3 rstart = rQueue.rbegin();
4 rend = rQueue.rend();
5 while( (rstart != rend) && (rstart != last) ) {
6 print *rstart;
7 }
8 last = rQueue.rbegin();
9 UnlockMutex(list_mutex);
10 }
rQueue
is a queue in which I iterate in reverse orderrQueue
can receive messages at any timelast
in order to
avoid reworking with a receive message at line 6At line 8, I retain the position from where I printed the messages and I want to only print the messages that are newer than the last message.
My problem: When a iteration is finished and new messages are added in
the queue, the value of iterator last
is changed, becoming the same
as the value of the iterator rstart
, therefore the new arrived
messages are not printed at line 6.
I don't know why last = rQueue.rbegin()
modifies its value when receiving new elements after unlocking the queue.
Thanks.
If you set an iterator to rbegin()
, it will always keep pointing to the last element of the list. If you add another element at the back, the iterator will point still point to the last element (which now is the new one). It will not change, it just keeps pointing to the end.
I did this test:
list<const char *> my_list;
my_list.push_back("msg 1");
list<const char*>::reverse_iterator it = my_list.rbegin();
cout << "Iterator is " << *it << endl;
my_list.push_back("msg 2");
my_list.push_back("msg 3");
my_list.push_back("msg 4");
cout << "Iterator is " << *it << endl;
This program gives the output:
Iterator is msg 1
Iterator is msg 4
I have this other solution you might use which does not use a reverse iterator. Instead, the addMessage()
-function updates read_pos
to the newest message. If read_pos
does not point to the end, it is not changed either. This allows printMessage()
to print all messages which where added since last time it ran.
Notice that I have only tested this without the locking.
mutex_type list_mutex;
typedef list<const char*> RQueue;
RQueue rQueue;
RQueue::iterator read_pos;
void addMessage(const char *message) {
LockMutex(list_mutex);
rQueue.push_back(message);
if (rQueue.size() == 1) {
read_pos = rQueue.begin();
}
else if (read_pos == rQueue.end()) {
read_pos--;
}
UnlockMutex(list_mutex);
}
void printMessage() {
RQueue::iterator prev_pos;
while (true) {
LockMutex(list_mutex);
if (rQueue.size() == 0) {
UnlockMutex(list_mutex);
continue;
}
RQueue::iterator end = rQueue.end();
while (read_pos != end) {
cout << *read_pos << endl;
read_pos++;
}
UnlockMutex(list_mutex);
}
}