Topic: have_lock()


Author: Tony <gottlobfrege@gmail.com>
Date: Mon, 21 Sep 2009 13:20:50 CST
Raw View
<I posted this via Google groups, but alas, Google seems to be having
difficulties passing things along to moderators (any moderated group)
this week>

Last I checked, in the next standard, there will be something of a
lockable concept wherein lockable objects implement:

 lock()
 unlock()
 try_lock()

I was wondering if it made sense to also require

 have_lock()

ie return true iff the current thread holds the lock.  Do NOT attempt to
acquire the lock, just return the status.  Note that this does NOT
return whether *any* thread has the lock, just whether the *current*
thread is the owner.

Why?

Somewhat for 'completeness', but also because there are times when you
want to do things only when you do NOT have a lock.  In particular, you
often want to avoid holding 2 locks (to avoid deadlocks).  Thus, if you
knew that you already head lockA, you might defer or 'queue up' a call
to something that would acquire lockB as part of its execution.  If you
knew you didn't hold lockA, you might instead make the call directly.
I hope that makes sense.

Sorry if that is already part of the coming standard and I just missed
it.  My google-fu has been weak lately.

Tony

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Mon, 21 Sep 2009 18:27:05 CST
Raw View
Tony <gottlobfrege@gmail.com> writes:

> <I posted this via Google groups, but alas, Google seems to be having
> difficulties passing things along to moderators (any moderated group)
> this week>
>
> Last I checked, in the next standard, there will be something of a
> lockable concept wherein lockable objects implement:
>
>  lock()
>  unlock()
>  try_lock()
>
> I was wondering if it made sense to also require
>
>  have_lock()
>
> ie return true iff the current thread holds the lock.  Do NOT attempt to
> acquire the lock, just return the status.  Note that this does NOT
> return whether *any* thread has the lock, just whether the *current*
> thread is the owner.

std::unique_lock has an owns_lock() function that reports whether that
instance owns a lock. It doesn't tell you anything about whether or not
the thread owns a lock on the mutex via another instance though.

In general, it is not a good idea for the mutex to provide this
information. For one thing, it can hurt performance, as the mutex needs
to store information about who owns the lock as well as actually
acquiring the lock. Secondly, and more importantly, if you don't know
whether or not you have a lock in a particular region of code then you
have a program logic error.

> Somewhat for 'completeness', but also because there are times when you
> want to do things only when you do NOT have a lock.  In particular, you
> often want to avoid holding 2 locks (to avoid deadlocks).  Thus, if you
> knew that you already head lockA, you might defer or 'queue up' a call
> to something that would acquire lockB as part of its execution.  If you
> knew you didn't hold lockA, you might instead make the call directly.
> I hope that makes sense.

In this case, why not just pass a flag indicating which mutex is locked
(if any)? This is a very context-specific behaviour, and is better
written cleanly with that context in mind rather than being provided as
a general facility.

Anthony
--
Author of C++ Concurrency in Action | http://www.manning.com/williams
just::thread C++0x thread library   | http://www.stdthread.co.uk
Just Software Solutions Ltd         | http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Tony <gottlobfrege@gmail.com>
Date: Wed, 23 Sep 2009 13:33:06 CST
Raw View
Anthony Williams wrote:
> Tony <gottlobfrege@gmail.com> writes:
>
>>
>> I was wondering if it made sense to also require
>>
>>  have_lock()
>>
> In general, it is not a good idea for the mutex to provide this
> information. For one thing, it can hurt performance, as the mutex needs
> to store information about who owns the lock as well as actually
> acquiring the lock. Secondly, and more importantly, if you don't know
> whether or not you have a lock in a particular region of code then you
> have a program logic error.
>

I was worried about the implementation implications.  Although I suspect
for most cases there is something like an atomic<int> being CAS'd, which
could probably be CAS'd to the thread ID, or something like that
(although I could also imagine that the atomic<int> was full of special
bit-fields and there wouldn't be room left for an ID).

I understand what you are saying about logic errors, but I don't think
it is always true.  I can imagine 2 or 3 cases:
1 - real life.  Code isn't always pretty, and sometimes you need to go
through some hoops.
2 - generic code.  You don't want to impose more constraints than necessary.
3 - debugging

In these cases you can probably track ownership outside the lock, but,
for case 3 in particular, it is not as fool-proof as having it built
into the lock itself.

>> Somewhat for 'completeness', but also because there are times when you
>> want to do things only when you do NOT have a lock.  In particular, you
>> often want to avoid holding 2 locks (to avoid deadlocks).  Thus, if you
>> knew that you already head lockA, you might defer or 'queue up' a call
>> to something that would acquire lockB as part of its execution.  If you
>> knew you didn't hold lockA, you might instead make the call directly.
>> I hope that makes sense.
>
> In this case, why not just pass a flag indicating which mutex is locked
> (if any)? This is a very context-specific behaviour, and is better
> written cleanly with that context in mind rather than being provided as
> a general facility.
>

I think cases 1,2,3 above argue against this.  Although, again, I agree
with you in general.  May come down to how much the standard should
encourage (impose?!) 'good' coding practices.
I just wonder how many (if any) implementations would have difficulty
with the implementation. (Or not 'difficulty' but extra cost.)  I
suspect it may be that the underlying OS could implement it easily, but
if it is not exposed, then the C++ impl will have problems.



> Anthony

Thanks,
Tony

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Thu, 24 Sep 2009 13:37:32 CST
Raw View
Tony <gottlobfrege@gmail.com> writes:

> Anthony Williams wrote:
>> Tony <gottlobfrege@gmail.com> writes:
>>
>>>
>>> I was wondering if it made sense to also require
>>>
>>>  have_lock()
>>>
>> In general, it is not a good idea for the mutex to provide this
>> information. For one thing, it can hurt performance, as the mutex needs
>> to store information about who owns the lock as well as actually
>> acquiring the lock. Secondly, and more importantly, if you don't know
>> whether or not you have a lock in a particular region of code then you
>> have a program logic error.
>>
>
> I was worried about the implementation implications.  Although I suspect
> for most cases there is something like an atomic<int> being CAS'd, which
> could probably be CAS'd to the thread ID, or something like that
> (although I could also imagine that the atomic<int> was full of special
> bit-fields and there wouldn't be room left for an ID).

Yes, you could do it by CASing the thread ID, but I don't think many
implementations will: it is generally slower than alternative
options. For one thing, it needs a CAS loop whereas alternatives can use
simple exchange operations or bit-field operations which don't require a
loop.

> I understand what you are saying about logic errors, but I don't think
> it is always true.  I can imagine 2 or 3 cases:
> 1 - real life.  Code isn't always pretty, and sometimes you need to go
> through some hoops.
> 2 - generic code.  You don't want to impose more constraints than necessary.
> 3 - debugging
>
> In these cases you can probably track ownership outside the lock, but,
> for case 3 in particular, it is not as fool-proof as having it built
> into the lock itself.

Debugging implementations of std::mutex may well track ownership to
detect deadlock or other problems --- my just::thread library certainly
does.

However, this comes with a performance cost, and providing such a
facility for general use is against the general principle of not paying
for what you don't use.

>>> Somewhat for 'completeness', but also because there are times when you
>>> want to do things only when you do NOT have a lock.  In particular, you
>>> often want to avoid holding 2 locks (to avoid deadlocks).  Thus, if you
>>> knew that you already head lockA, you might defer or 'queue up' a call
>>> to something that would acquire lockB as part of its execution.  If you
>>> knew you didn't hold lockA, you might instead make the call directly.
>>> I hope that makes sense.
>>
>> In this case, why not just pass a flag indicating which mutex is locked
>> (if any)? This is a very context-specific behaviour, and is better
>> written cleanly with that context in mind rather than being provided as
>> a general facility.
>>
>
> I think cases 1,2,3 above argue against this.  Although, again, I agree
> with you in general.  May come down to how much the standard should
> encourage (impose?!) 'good' coding practices.
> I just wonder how many (if any) implementations would have difficulty
> with the implementation. (Or not 'difficulty' but extra cost.)  I
> suspect it may be that the underlying OS could implement it easily, but
> if it is not exposed, then the C++ impl will have problems.

Neither Windows nor POSIX APIs provide this information to users, though
it is usually available for Windows CRITICAL_SECTIONs using undocumented
access. Custom-built mutexes will typically not have this information
available.

Anthony
--
Author of C++ Concurrency in Action | http://www.manning.com/williams
just::thread C++0x thread library   | http://www.stdthread.co.uk
Just Software Solutions Ltd         | http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]