15

I've seen most examples using std::mutex where the mutex is global. I was wondering is there any specific reason why this is done? I've had programs of my own where I don't do this, and simply pass the mutex in as a std::thread std::ref. Isn't it bad practice to have globals, what is the rational behind global std::mutexes in C++ if there is no language restricting reason to do this?

Krupip
  • 4,404
  • 2
  • 32
  • 54
  • 8
    No reason. It was probably done to cut down code in the example. – NathanOliver Jul 05 '17 at 17:39
  • Probably because the author hates the syntax of `std::reference_wrapper` ;) – Passer By Jul 05 '17 at 17:46
  • 2
    It totally depends. Are they fairly trivial programs? Do they consist of more than one file? Need more information. Usually globals are considered bad practice and should be avoided. Typically my mutexes tend to be class member variables. It is often natural to put them in the object that needs locking. – Galik Jul 05 '17 at 18:06

2 Answers2

9

It's bad practice to have globals except when it isn't. For example, std::cin is global.

Mutexes are in a sense global, regardless of how you make them available. They're shared between disparate pieces of code. So you can make them globals, or you can pass them down the call chain, through functions that don't use them, until you eventually reach someone who does. That's known as "tramp data" and it's also "bad practice". Choose your poison.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • Side note: You can at least minimize the number of tramps by putting the various pieces of data (mutexes, etc) into a single object together; then you only have to pass one argument down the call chain rather than many. – Jeremy Friesner Jul 05 '17 at 17:58
  • @JeremyFriesner -- yes, you can create incoherent types to simplify implementing a bad design. Seriously, though, this can be a legitimate technique. Thanks for mentioning it. – Pete Becker Jul 05 '17 at 18:06
  • Some people have criticisms about global in ``... It is not because it is done that way in `std` that it is the right way. – Jarod42 Jul 05 '17 at 18:06
  • I don't really agree with this at all. A: my implementations usually have used mutexes at the top scope, B: My threads typically have another data structure where I need mutually exclusive access, you can't portably move mutex code when you rely on some global mutex that may or may not actually exist. C: You can create a threaded class to house mutexes, or use an entirely separate class to combine mutex and resource access. Globals still seem like code smell in this situation. – Krupip Jul 05 '17 at 18:08
  • @Jarod42 -- "some people don't like it" is not the same as "it's 'bad practice'". – Pete Becker Jul 05 '17 at 18:10
  • 2
    Re, "Mutexes are in a sense global..." The sense you're looking for might be _extent_ (i.e., how long a variable lives), but when people say "global" without qualifying it, they usually mean global _scope_ (i.e., what parts of the code can see it). The scope of a C++ `std::mutex` depends on where it's declared---could be global, could be local, could be a private member---just like any other type of variable. Since the purpose of a mutex is to prevent threads from accessing the same data at the same time, it usually makes sense to declare it in the same scope as the data it protects. – Solomon Slow Jul 05 '17 at 21:08
  • @jameslarge -- that only works for simple cases. When you have to coordinate access to two separate sets of data, there's no obvious single place for the mutex. – Pete Becker Jul 05 '17 at 21:11
2

Most likely this was done to make the example easier to follow, allowing the use of the mutex itself to be the focus of the example rather than the exact specifics.

Typically a mutex protects a resource and in many cases it makes sense for the mutex to live alongside the resource. For example if you have a class with a member container that needs to be protected by a mutex, make the mutex also a member of the class. Then as the class instance is acted on by multiple threads the member-mutex can be used to protect the needed accesses to the internal container.

Mark B
  • 95,107
  • 10
  • 109
  • 188