Proper use of scoped_lock in out-of-tree module?

I see different use cases of this in the gnuradio tree, like:

gr::thread::scoped_lock guard(d_mutex);

gr::thread::scoped_lock l(d_mutex);

gr::thread::scoped_lock lock(d_setlock);

As well as variances of whether the mutex variable is declared in a
header file…

Could someone lend some kind words on what is recommended (at least for
GR 3.7)?

Thanks,
Tim

On Tue, Jul 2, 2013 at 4:06 PM, Monahan-Mitchell, Tim <
[email protected]> wrote:

Could someone lend some kind words on what is recommended (at least for GR
3.7)?

There is really nothing special or unique going on here. A scoped lock
grabs the associated mutex during its scope lifetime. The above three
are
just using different names for the local variable instance of the the
lock.

The associated mutex is usually a (private) member viable of a class,
and
is used as a synchronization object by different class methods. As a
member variable, you have a choice to name it whatever you want. If the
mutex is the only one in the class, we usually call it d_mutex. If
there
is more than on mutex in the class, then we give it a unique name.

If you’re writing your own code as a class, making the mutex a member
variable and calling it d_mutex, and calling the local scoped lock
object
‘guard’, is probably the most descriptive, but again, it’s up to you.

The associated mutex is usually a (private) member variable of a class,
and is used as a synchronization object by different class methods. As
a member variable, you have a choice to name it whatever you want. If
the mutex is the only one in the class, we usually call it d_mutex. If
there is more than one mutex in the class, then we give it a unique
name.

If you’re writing your own code as a class, making the mutex a member
variable and calling it d_mutex, and calling the local scoped lock
object ‘guard’, is probably the most descriptive, but again, it’s up to
you.

OK, that helps, thanks.

One additional question - looking file_meta_source_impl.cc, it uses
‘d_mutex’ in all cases; in most places in the file, the object is called
‘guard(d_mutex)’. But in one place the object is called
‘lock(d_mutex)’… Is that a mistake?

I got concerned when I read some about this on the net, saying that it
is easy to forget that a local object will get destroyed when the scope
that created it closes. Hence the need for d_mutex to get defined as a
private class member (but it compiles fine if that step is forgotten).

Tim

On Wed, Jul 3, 2013 at 1:40 AM, Monahan-Mitchell, Tim
[email protected] wrote:

OK, that helps, thanks.

One additional question looking file_meta_source_impl.cc, it uses
d_mutex in all cases; in most places in the file, the object is called
guard(d_mutex). But in one place the object is called lock(d_mutex) Is
that a mistake?

Just an oversight, possibly put in a different time. It doesn’t matter
because the variable guard and lock are in different scopes and exist
at different times. It’s a local name, and each time we created a
scoped_lock, we could have named it something else (guard0, guard1,
guard2). No reason that they need to be the same and no reason for
them to be different.

I got concerned when I read some about this on the net, saying that it is
easy to forget that a local object will get destroyed when the scope that
created it closes. Hence the need for d_mutex to get defined as a private
class member (but it compiles fine if that step is forgotten).

Yes, exactly. The scoped_lock variable is local. It uses d_mutex to
lock the mutex during its own lifetime. When the variable goes out of
scope, d_mutex is unlocked and another call to scoped_lock can now
acquire it.

Tim

Tom

On 07/02/2013 10:40 PM, Monahan-Mitchell, Tim wrote:

I got concerned when I read some about this on the net, saying that it
is easy to forget that a local object will get destroyed when the scope
that created it closes. Hence the need for d_mutex to get defined as a
private class member (but it compiles fine if that step is forgotten).

Just to be clear, there are two variables here. The ‘d_mutex’ is a class
variable, usually private (but doesn’t have to be.) It serves as a
common synchronization object to allow multiple threads to coordinate
use of some resource, over the lifetime of a class instance, by being
locked and unlocked as needed by class methods.

The other variable, ‘guard’ or ‘lock’ or ‘l’, is the thing doing the
locking in individual methods that must synchronize access. As a scoped
lock, it is designed to lock the mutex given as a constructor parameter
when it is created, and unlock that mutex when it goes out of scope and
is destroyed. The common pattern, then, is to make it a local variable
in a method, so that it goes in and out of scope (and acquires and
releases the mutex) automatically, while the code within that scope can
assume it is holding the lock exclusively to any other thread.

Since this is a variable and not some language keyword, you can name it
whatever you like. ‘guard’ is common, but it doesn’t have to be the
same each time it is used.

What specifically do you mean when you say ‘compiles fine if that step
is forgotten’ ?


Discuss-gnuradio mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio

I got concerned when I read some about this on the net, saying that it
is easy to forget that a local object will get destroyed when the
scope that created it closes. Hence the need for d_mutex to get
defined as a private class member (but it compiles fine if that step is
forgotten).

Just to be clear, there are two variables here. The ‘d_mutex’ is a class
variable, usually private (but doesn’t have to be.) It serves as a common
synchronization object to allow multiple threads to coordinate use of some
resource, over the lifetime of a class instance, by being locked and unlocked as
needed by class methods.

The other variable, ‘guard’ or ‘lock’ or ‘l’, is the thing doing the locking in
individual methods that must synchronize access. As a scoped lock, it is designed
to lock the mutex given as a constructor parameter when it is created, and unlock
that mutex when it goes out of scope and is destroyed. The common pattern, then,
is to make it a local variable in a method, so that it goes in and out of scope
(and acquires and releases the mutex) automatically, while the code within that
scope can assume it is holding the lock exclusively to any other thread.

Since this is a variable and not some language keyword, you can name it whatever
you like. ‘guard’ is common, but it doesn’t have to be the same each time it is
used.

What specifically do you mean when you say ‘compiles fine if that step is
forgotten’ ?

In my GR 3.6.4.2-based OOT module, I placed a line like this where I
wanted exclusivity from other entry points (copied from looking at
examples in the gnuradio tree):

gruel::scoped_lock l(d_setlock);

… and did nothing else (no #include, no declaration of d_setlock
anywhere). I used gr_modtool to generate the skeleton files. It compiled
and ran without complaints (on VMware x86 and ARM target). As to whether
it actually did what it was supposed to do, I don’t know. I have since
seen occurrences of “#include<gruel/attributes.h>” in the template
header files, but I was dumb and happy at this point, so no worries.
(You should have deduced by now that I don’t use C++ much…)

While stepping up to GR 3.7, one of the things to change was that
include line, which made me investigate more, and I read this article:
http://jek-thoughts.blogspot.com/2010/06/pitfalls-of-scoped-lock.html .
That caused me to start this thread.

So I have higher confidence now that I’m using the scope lock tool
correctly, thanks again.