Alex Rivera | Logout

what is the best way to synchronize container access between multiple threads in real-time application

Asked 2010-01-16T11:13:14.427
10

I have std::list<Info> infoList in my application that is shared between two threads. These 2 threads are accessing this list as follows:

Thread 1: uses push_back(), pop_front() or clear() on the list (Depending on the situation) Thread 2: uses an iterator to iterate through the items in the list and do some actions.

Thread 2 is iterating the list like the following:

for(std::list<Info>::iterator i = infoList.begin(); i != infoList.end(); ++i)
{
  DoAction(i);
}

The code is compiled using GCC 4.4.2.

Sometimes ++i causes a segfault and crashes the application. The error is caused in std_list.h line 143 at the following line:

_M_node = _M_node->_M_next;

I guess this is a racing condition. The list might have changed or even cleared by thread 1 while thread 2 was iterating it.

I used Mutex to synchronize access to this list and all went ok during my initial test. But the system just freezes under stress test making this solution totally unacceptable. This application is a real-time application and i need to find a solution so both threads can run as fast as possible without hurting the total applications throughput.

My question is this: Thread 1 and Thread 2 need to execute as fast as possible since this is a real-time application. what can i do to prevent this problem and still maintain the application performance? Are there any lock-free algorithms available for such a problem?

Its ok if i miss some newly added Info objects in thread 2's iteration but what can i do to prevent the iterator from becoming a dangling pointer?

Thanks

Edit
Report

1 Answer

1

To prevent your iterator from being invalidated you have to lock the whole for loop. Now I guess the first thread may have difficulties updating the list. I would try to give it a chance to do its job on each (or every Nth iteration).

In pseudo-code that would look like:

mutex_lock();
for(...){
  doAction();
  mutex_unlock();
  thread_yield();  // give first thread a chance
  mutex_lock();
  if(iterator_invalidated_flag) // set by first thread
    reset_iterator();
}
mutex_unlock();
answered 2010-01-16T11:32:36.930

Your Answer