georgiana_e
georgiana_e

Reputation: 1869

C++ rbegin modify address of reverse_iterator

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  }

I don't know why last = rQueue.rbegin() modifies its value when receiving new elements after unlocking the queue.

Thanks.

Upvotes: 1

Views: 380

Answers (1)

Atle
Atle

Reputation: 1877

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);
  }
}

Upvotes: 1

Related Questions