|
Boost Users : |
Subject: Re: [Boost-users] [Boost.Thread]
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2010-01-28 13:02:23
inlined below:
On Thu, Jan 28, 2010 at 12:23 PM, Andrew Chinkoff <achinkoff_at_[hidden]> wrote:
> Hi.
>
> There is a test program I would to be explained to me:
>
> *** BEGIN OF TEST PROGRAM ***
> #include <stdio.h>
> #include <boost/thread.hpp>
>
//> #define USE_SPINLOCKS
#define USE_ATOMICS
(you are using atomics, not spinlocks)
> //#define USE_MUTEXES
>
> boost::thread th1;
> boost::thread th2;
>
> boost::mutex mutex;
>
> int global_int = 0;
>
// put the mutex and/or atomics inside this function,
// where it is really needed - protecting you global data - instead of
in your for loop
int read_global_int()
{
> #ifdef USE_MUTEXES
> boost::mutex::scoped_lock locker(mutex);
return global_int;
#elif USE_ATOMICS
// add 0 to global_int. Seems odd, but by doing this with
atomic __sync functions
// we guarantee proper memory ordering and visibility, as well
as atomicity
return __sync_fetch_and_add(&global_int, 0);
> #else
> ERROR__WRONG_COMPILED;
> #endif
}
//> bool IsNotEven(int code)
// better name:
bool IsOdd(int code)
> {
// no longer grab mutex here. This is now a useful function for *any* integer
return !!(code & 1); // using !! to convert to bool
> }
>
> void thread_func()
> {
> for(int i = 0; i < 1000000; ++i)
> {
// mutex/atomic handling is inside read_global_int()
if(IsOdd(read_global_int()))
> global_int+=9; // what about mutex/atomic here?
> else
> global_int+=1; // and here?
> }
> }
>
> int main()
> {
> th1 = boost::thread(&thread_func);
> th2 = boost::thread(&thread_func);
> th1.join();
> th2.join();
> printf("global_int = %d\n", global_int);
>
> return 0;
> }
> *** END OF TEST PROGRAM ***
>
> Results of test program:
>
> 1) Test program compiled with USE_SPINLOCKS.
> Outputs are always:
> "global_int = 10"
> "global_int = 10"
> "global_int = 10"
>
> 2) Test program compiled with USE_MUTEXES.
> Outputs differ from each other:
> "global_int = 10000008"
> "global_int = 10000000"
> "global_int = 9763210"
>
> Could you explain me why outputs produced with USE_SPINLOCKS compilation
> differ from USE_MUTEXES ones?
> And what is the difference between (1) and (2) lines?
>
So now they should both look like (2).
In order to get a consistent result (global_int = 10000000), you need
to replace your global_int += 9 and += 1 with __sync instructions.
ie
increase_global_int(int inc)
{
// TO DO
// do this atomically or with locks:
// global_int += inc;
}
> Best,
> Andrew.
>
Tony
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net