Thank you Alex and Ulrich!

****************************************************************
Suppose that vector has 5 elements and i = 3.
Following statement expects to update 4th element.

vector[i] = 2 * vector[i] + 1;

What actually may happen is:

vector[i] = // 4th element's reference is fetched.
// Then current thread is preemted and
// vector is emptied in other thread.
2 * vector[i] + 1; // Oops! vector is empty already
****************************************************************

If the code is like:

EnterCriticalSection();
vector[i] = 2 * vector[i] + 1;
LeaveCriticalSection();

Will the execution of the above be atomic?

Even though another thread may call "vector.empty()", will this problem be
solved by just doing this:

EnterCriticalSection();
vector.empty();
LeaveCriticalSection();


Is that good enough to say that doing the following will make using STL
classes thread-safe:

Whenever there is a writing operation from a thread (at least), all accesses
to a STL class as a whole, not just partial/single element(s), need to be
synchronized.

Re: Use STL classes thread-safely by Igor

Igor
Wed Feb 08 14:19:06 CST 2006

nly <nlyee2001@yahoo.com> wrote:
> If the code is like:
>
> EnterCriticalSection();
> vector[i] = 2 * vector[i] + 1;
> LeaveCriticalSection();
>
> Will the execution of the above be atomic?

To be exact: any code that only examines and/or manipulates this vector
instance under the same critical section will see this operation
performed completely or not at all.

> Even though another thread may call "vector.empty()", will this
> problem be solved by just doing this:
>
> EnterCriticalSection();
> vector.empty();
> LeaveCriticalSection();

In this example, if vector.empty() happens first, vector[i] is invalid
for any value of i. Somewhere there must be a check for it - this check
must occur under the critical section together with the modifying
operation itself.

> Is that good enough to say that doing the following will make using
> STL classes thread-safe:
>
> Whenever there is a writing operation from a thread (at least), all
> accesses to a STL class as a whole, not just partial/single
> element(s), need to be synchronized.

Reading operations must be under critical section also, or at least
under many-readers-single-writer lock. Otherwise the reader may observe
inconsistent data due to write operation still in progress. E.g. if you
do v.push_back(1), that may cause vector to reallocate internal memory
buffer and copy all existing elements over to the new buffer. If a
reader tries to get an element while this is going on, it may get back
garbage.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925



RE: Use STL classes thread-safely by Axter

Axter
Wed Feb 08 15:24:27 CST 2006

"nly" wrote:

> Thank you Alex and Ulrich!
>
> ****************************************************************
> Suppose that vector has 5 elements and i = 3.
> Following statement expects to update 4th element.
>
> vector[i] = 2 * vector[i] + 1;
>
> What actually may happen is:
>
> vector[i] = // 4th element's reference is fetched.
> // Then current thread is preemted and
> // vector is emptied in other thread.
> 2 * vector[i] + 1; // Oops! vector is empty already
> ****************************************************************
>
> If the code is like:
>
> EnterCriticalSection();
> vector[i] = 2 * vector[i] + 1;
> LeaveCriticalSection();
>
> Will the execution of the above be atomic?
>
> Even though another thread may call "vector.empty()", will this problem be
> solved by just doing this:
>
> EnterCriticalSection();
> vector.empty();
> LeaveCriticalSection();
>
>
> Is that good enough to say that doing the following will make using STL
> classes thread-safe:
>
> Whenever there is a writing operation from a thread (at least), all accesses
> to a STL class as a whole, not just partial/single element(s), need to be
> synchronized.
>

Consider using a synchronized smart pointer like the following:
http://code.axter.com/sync_ptr.h
http://code.axter.com/sync_ctrl.h


The above smart pointer can make it easier to synchronized your object
automatically either through single line call, or in multiple line calls.
In single line synchronization, it happens completely automatically.
In multiple line synchronization, you need to use a helper class.
sync_ptr<vector<foo> >::RefLock
MyLockedvFoo = MyThreadSafevFoo.get_locked_obj();
//You then use MyLockedvFoo as a pointer to a vector<foo> object
When MyLockedvFoo goes out of scope, it unlocks the object automatically.
You can force scope with in a set of lines by using {}

-----------------------------------------------
Top Ten Expert in Experts-Exchange C++ and MFC topic area.
http://www.experts-exchange.com/Cplusplus
------------------------------------------------


Re: Use STL classes thread-safely by Alex

Alex
Thu Feb 09 03:11:25 CST 2006

nly wrote:
> If the code is like:
>
> EnterCriticalSection();
> vector[i] = 2 * vector[i] + 1;
> LeaveCriticalSection();
>
> Will the execution of the above be atomic?
>
> Even though another thread may call "vector.empty()",
> will this problem be solved by just doing this:
>
> EnterCriticalSection();
> vector.empty();
> LeaveCriticalSection();

In addition to Igor's advice I'd recommend to use classes
for critical section too. If you use ATL/MFC already, then
look for CComCritSecLock/CSingleLock, respectively.



Re: Use STL classes thread-safely by Ulrich

Ulrich
Thu Feb 09 10:15:11 CST 2006

nly wrote:
> EnterCriticalSection();
> vector[i] = 2 * vector[i] + 1;
> LeaveCriticalSection();
>
> Will the execution of the above be atomic?

I wouldn't call it atomic, but every other thread trying to enter the same
critical section in between will block until all other threads left the
critical section.

> Even though another thread may call "vector.empty()", will this problem be
> solved by just doing this:
>
> EnterCriticalSection();
> vector.empty();
> LeaveCriticalSection();

Danger! vector::empty() returns a boolean telling you if the vector is
empty, in order to empty a vector use clear().

> Is that good enough to say that doing the following will make using STL
> classes thread-safe:
>
> Whenever there is a writing operation from a thread (at least), all
> accesses to a STL class as a whole, not just partial/single element(s),
> need to be synchronized.

No, you need to guard read operations, too, imagine you're in the middle of
reading and someone starts writing. If you only fill a vector once and then
read it from multiple threads you can do so without locking though.

Uli