
On Jul 14, 2004, at 6:27 AM, Alexander Terekhov wrote:
It is a philosophical issue, not technical.
Thanks for your comments. Speaking philosophically ... just wondering out loud, not trying to solve anything, I wonder if this doesn't boil down to an object oriented view vs a functional view. Because the few times I've felt the need for a recursive mutex is when I had an object, which contained a single mutex, which had several public member functions that just happened to call each other as an implementation detail. Something like: class A { public: void foo1(); // calls foo2 and foo3 under the covers void foo2(); void foo3(); private: mutex mut_; }; All three functions lock the mutex to synchronize access so A can maintain its invariant. But foo1() is an especially complicated operation and to help it do it's job also calls foo2() and foo3() under the covers. foo1() can't afford to just let foo2() and foo3() handle the locking because it also breaks invariants within it's own body and/or must execute foo2() and foo3() atomically. foo1 may restore invariants before calling foo2 and foo3, or foo2 and foo3 may be smart enough to deal with the state in which foo1 calls them (just depends on the application). So although there are non-recursive ways to solve this problem, simply allowing mut_ to be locked recursively is convenient. The alternative is write a private function that might look like: void do_foo(int parm); where parm indicates whether you need to do just 2, just 3, or both 2 and 3, and locks accordingly. Now foo1, foo2 and foo3 can all forward to do_foo without locking at the top level. The more interdependent foo's you have though, the more convenient the recursive approach looks. Admittedly, I've never felt the need to wait on a recursively locked mutex, but it seems like it would be reasonable for foo2() in the above example to do so, whether or not it had been called from an external client, or from foo1(). foo1() could tell foo2() that it had been called from foo1() so that foo2() would know to do an extra unlock/lock before/after the wait. But with many foo's that solution could get as complicated, or even more so, than the non-recursive do_foo() approach. <sigh> Hope I never feel the need to wait on a recursive mutex! :-) -Howard