...
> "Peter Dimov" wrote
>> Uenal Mutlu wrote:
>> > "Peter Dimov" wrote
>> >> Uenal Mutlu wrote:
>> >>> "David Schwartz" wrote
>> >>>> Yes, it can and must know that it already has the lock. A
>> >>>> function that operates on X should be defined as being called with
>> >>>> X locked, or with X unlocked. It could even take a boolean that
>> >>>> indicates whether the caller has locked the object or not, though
>> >>>> this is rarely the right thing to do.
>> >>> You are unnecessarily complicating things and make the program
>> >>> slower by doing these testings.
>> >> No, he's in fact making the program faster.
>> > Are you sure? Let's see:
>> > void X::f()
>> > {
>> > Lock();
>> > for (int i = 0; i < 1000; i++)
>> > f();
>> Stack overflow or deadlock here, you probably wanted to call g().
> :-) Of course g() was meant.
>> > Unlock();
>> > }
>> > void X::g()
>> > {
>> > if (!IsLocked())
>> > return;
>> > //...do..something...
>> > }
>> > Are you saying the above version of g() is faster than this one: ?
>> > void X::g()
>> > {
>> > //...do..something...
>> > }
>> Of course not. Why would you want to test anything if you could just use
>> the
>> above? We're talking about recursive mutexes, remember?
> No I haven't. See below
>> void X::f()
>> {
>> Lock();
>> for (int i = 0; i < 1000; i++)
>> {
>> g();
>> }
>> Unlock();
>> }
>> void X::g()
>> {
>> Lock();
>> //...do..something...
>> Unlock();
>> }
> The above solution works only if your Lock() understands recursive
> locking.
> Otherwise a deadlock will happen.
>> compared to
>> void X::f()
>> {
>> Lock();
>> for (int i = 0; i < 1000; i++)
>> {
>> g( false );
>> }
>> Unlock();
>> }
>> void X::g( bool lock )
>> {
>> if( lock ) Lock();
>> //...do..something...
>> if( lock ) Unlock();
>> }
> I don't like the above because one usually uses a locker
> class like this one to automate the unlocking:
> Locker
> {
> Locker(mutex& Am) : m(Am)
> {
> m.Lock();
> }
> ~Locker()
> {
> m.Unlock();
> }
> private:
> mutex& m;
> };
> void X::f()
> {
> Locker(m);
> for (int i = 0; i < 1000; i++)
> g();
> }
> void X::g()
> {
> //...do..something...
> }
>> Let's overlook the fact that the correct version is of course:
>> void X::f()
>> {
>> Lock();
>> for (int i = 0; i < 1000; i++)
>> {
>> g_unlocked();
>> }
>> Unlock();
>> }
>> void X::g_unlocked()
>> {
>> //...do..something...
>> }
>> void X::g()
>> {
>> Lock();
>> g_unlocked();
>> Unlock();
>> }
> You don't need 2 versions of g() if you use recursive locking.
> The overhead of recursive locking is neglectable because
> it's just incrementing a counter in Lock() and decrementing it in
> Unlock().
S'not true. You can't just increment/decrement a counter in
work properly across multiple threads and CPUs. With recursive locks, too.
You keep arguing about silly things, proclaiming people to be wrong (e.g.
"see below..." - where!?!), and never providing evidence (only faulty code).
When someone questions you, you answer rather indignantly. Each post sounds
as though you've read the next chapter in your threading book and want to
share.
Anyways, this is interesting. More technical than alt.guitar.bass, but just
as much flamebait, if better disguised!