Re: [Boost-users] [multi_index] thread safety

Hi Joaquin,
I have to use actually two or more threads on procedure pool. I start seeing same
Problem when I have three/four threads working on same procedure pool. I tried to introduce mutex (ACE_Guard) but still having problems in execution in one/two minute of execution.
Seems I am guarding every method that is used by container. Anything wrong with the
Following code?
Thanks
Priyank
#ifndef PROCEDURE_POOL_H
#define PROCEDURE_POOL_H
/**
* Identifier pool of procedure. This procedure will be un-sorted
* hashed index provided by procedures unique id retuned by procedure.
* It internally uses boost hashed index for indexing the procedures
* in procedure pool.
*
* @author Priyank Patel
* @since Mar 30, 2006
*/
#include
hello Joaquin
Hello George,
You have to lockguard every access to the container; note this also includes, for instance, container traversal with iterators, i.e. iterator displacement. Strictly speaking, iterator dereference should also be lockguarded, although I can say unofficially that unguarded dereference is OK.
can you explain a litle more? as I konw from STL, multiple readers is ok.
Correct.
reading and inserting a new object does't invalidate iterators(for pointer-based conteiners offcourse,list, map etc...)
Correct. This also holds for multi_index_containers.
a concurrent read and insert in multi_index are not (safely)possible? I mean there might be an iterator invalidation?
Concurrent reading and writing is not safe, but the issue has nothing to do with iterator invalidation. ...I think I've got a hunch about what you've got in mind. When I say that you've got to lockguard iterator displacement, what I mean is: consider a concurrent write operation and an iterator increment; this concurrency is not thread safe and undefined behavior results: a possible outcome is iterator invalidation, but you could also get an app crash, a corrupted data structure, an infinite loop or whatever. Tecnhically speaking, an invalid iterator is a perfectly legal state for an iterator to be in, which has nothing to do with undefined behavior resulting from violating thread safety guarantees. I'm not sure I made myself clear :) Insist on me if I didn't.
offcourse there is a chance for a 'dirty-read' but this for the domain of the aplication if it is a problem and not for multi_index.
I don't get what you mean here, would you care to elaborate? Joaquín M López Muñoz Telefónica, Investigación y Desarrollo _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Hi,
comments below
On 5/12/06, Patel Priyank-PPATEL1
Hi Joaquin,
I have to use actually two or more threads on procedure pool. I start seeing same Problem when I have three/four threads working on same procedure pool. I tried to introduce mutex (ACE_Guard) but still having problems in execution in one/two minute of execution. Seems I am guarding every method that is used by container. Anything wrong with the Following code?
int Procedure_Pool::add_by_id(Procedure * _procedure) { LD_TRACE("Procedure_Pool::add_by_id"); ACE_ASSERT(_procedure != 0); ACE_DEBUG((LM_DEBUG, "ADDING %d\n", _procedure->id()));
if (find_by_id(_procedure->id()) == 0) { ACE_Guard
guard(mutex_); { // procedure not found procedure_by_id_.insert(_procedure); } // debug info ACE_DEBUG((LM_DEBUG, "Added procedure : %d \n", _procedure->id())); // return success return 0; } else { // error ACE_ERROR((LD_ERROR "%N:%l Error in adding procedure : %d \n", _procedure->id())); // return failure return -1; } }
int Procedure_Pool::remove_by_id(Procedure * _procedure) { LD_TRACE("Procedure_Pool::remove_by_id"); ACE_ASSERT(_procedure != 0); ACE_DEBUG((LM_DEBUG, "REMOVING: %d \n", _procedure->id())); if (find_by_id(_procedure->id()) != 0) { ACE_Guard
guard(mutex_); { // procedure found procedure_by_id_.erase(_procedure->id()); } ACE_DEBUG((LM_DEBUG, "Removed procedure : %d \n", _procedure->id())); return 0; } else { ACE_ERROR((LD_ERROR "%N:%l Error in removing procedure : %d \n", _procedure->id())); return -1; } }
Procedure * Procedure_Pool::find_by_id(int _id) { LD_TRACE("Procedure_Pool::find_by_id"); ACE_Guard
guard(mutex_); { Procedure_By_Id::iterator it = procedure_by_id_.find(_id); if (it != procedure_by_id_.end()) { ACE_DEBUG((LM_DEBUG, "%N:%l Found procedure for id: %d \n", _id)); return *it; } } ACE_DEBUG((LM_DEBUG, "%N:%l Not able to found procedure for id: %d \n", _id)); // return null return 0; }
Yes. There is a small theoretical problem with your code. A possible race condition. you tried to find_by_id, using mutex, than release that mutex and reacquire it for erase. That's a possible race condition. The "find" until the "erase" must be atomic. At least IMHO. Kobi.
participants (2)
-
Kobi Cohen-Arazi
-
Patel Priyank-PPATEL1