I often have to acquire locks and release them after I'm finished with them. I use constructor/destructor to acquire & release locks. everything works fine. sometime I must acquire a lock for few instructions, then release it in the middle of a big function. I use braces to get timely destructors, but I find the "middle of nowhere" braces kind of embarrassing. something like:
void someFunc() { // do some stuff ... // now time to update share data { Lock myLock(data_mutex); //use locked data .... } // destructor called // do more stuff ...
}
I would like to have something like the using keyword in c#. Is there a way to fake it in C++ ? for now I'm using an if to do it.
void someFunc() { // do some stuff ... // now time to update share data if (Lock myLock = Lock(data_mutex)) { //use locked data .... } // Unlock done by destructor
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire& release locks. everything > works fine.
Yep, that is the perfect scenario for the RAII (resource acquisition is initialization) idiom. The new C++0x standard library provides for this 80% bread-and-butter business the so-called lock_guard class which has exactly the simple constructor/destructor API as your type.
> sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing.
Yes, in some situations we have these kinds of code flow disruptions that are hard to get rid of. For such situations the C++0x library provides the lock type unique_lock which is able to release and to re-acquire a new lock.
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ?
Not extremely much more. You may consider the Scope Guard as a more general form:
> void someFunc() > { > // do some stuff > ... > // now time to update share data > if (Lock myLock = Lock(data_mutex)) > { > //use locked data > .... > } // Unlock done by destructor
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire& release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing.
Braces are good. You introduce a lock with the specified lifetime. How does "if" make it any different?
On Nov 25, 5:48 pm, Daniel Anderson <woni...@gmail.com> wrote:
> Hi!
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire & release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing.
I guess it's a matter of taste. For me the curly braces are very natural way of denoting the block.
Putting aside the errors in the code above, the only reason "operator bool" exists in the class is to make if() construct possible, it's not required for Lock proper functionality, which violates a good design rule: make interface complete and minimal.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called > // do more stuff > ...
> }
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ?
That's one of the common mistakes people switching to another language do -- is trying to fake what they are used to in a different language. That usually causes grief for everybody who has to deal with that code. Each language commands its own style, the only way to write good code is to learn and use it.
> for now I'm using an if to do it.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > if (Lock myLock = Lock(data_mutex)) > {
That assumes that Lock is copy-constructible or move-constructible, which it's not -- because mutex is neither copy-constructible nor move- constructible. Allowing that would lead to unsafe code causing deadlocks or races.
On 25 nov, 23:48, Daniel Anderson <woni...@gmail.com> wrote:
> Hi!
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire & release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing.
Really ? Sometimes I use them to separated unrelated sections of a function body:
> void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called > // do more stuff > ...
> }
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ?
If you really want to do it. You could always use a macro but IMO it would be dangerous.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > if (Lock myLock = Lock(data_mutex)) > { > //use locked data > .... > } // Unlock done by destructor
> // do more stuff > ...
> }
> Is it good programming ? > Is there a better way ?
Why not simply align the opening parenthesis with the lock: { Lock myLock(mutex) ...
> Hi! > I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire & release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing. > something like: > struct Lock > { > Lock(Mutex& mtx) mtx_(mtx) { mtx.lock(); } > ~Lock() { mtx_.unlock(); } > operator bool() { return true;} > }; > void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called
You don't loke "middle of nowhere" braces, so you add a meaningless if statement and an otherwise pointless operator bool? Stick with the braces. <g>
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire & release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing. > something like:
Since your Lock type depends on Mutex, why not just use the straight Mutex and lock and unlock as you please?
> void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called > // do more stuff > ...
> }
Some don't even know or haven long forgotten that you can create blocks arbitrarily like this. I agree that it doesn't look nice, but it has a lot of uses and i think there's nothing wrong with using it. It's an incredibly simple and elegant way of solving this problem.
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ?
This is a C++ forum. C# is relevant to this question, but for those of us who haven't worked with it, please post a short example.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > if (Lock myLock = Lock(data_mutex)) > { > //use locked data > .... > } // Unlock done by destructor
> // do more stuff > ...
> }
You seem to be implying that this if statement will always evaluate to true (since i assume this code is equivalent to your first example), but when i see an "if" in any code, i always assume that it will sometimes not evaluate to true. On the other hand, it reminds me of this: std::weak_ptr<int> wp; void f() { if( std::shared_ptr<int> sp = wp.lock() ) ; // do something }
> Is it good programming ?
What a subjective question!
> Is there a better way ?
I think creating an arbitrary scope is one of the simplest and least error prone ways to do this. I'm sure at least one person (if not you) will disagree with me, but i like simple. I suppose you could create a class that inputs a function, locks, calls the function, then unlocks, and you could use C++0x lambdas to integrate it into your current code without too much refactoring, but that means you'll have to maintain the locking class and every function/class/etc that uses it. I guess i'm not the most articulate so i'll use someone else's words: "Perfection is achieved not when you have nothing more to add, but when you have nothing left to take away." ~ Antoine de Saint-Exupery.
In comp.lang.c++ Daniel Anderson <woni...@gmail.com> wrote:
> but I find the "middle of nowhere" braces kind of > embarrassing.
I don't think there's anything wrong with them, especially if you precede the block with a comment clarifying the reason. It's a pretty common pattern to restrict the lifetime of objects. (One concrete example where it's commonly used is the "release the memory taken by a std::vector via swapping" paradigm.)
On Nov 25, 10:48 pm, Daniel Anderson <woni...@gmail.com> wrote:
> Hi!
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire & release locks. everything > works fine.
Good. What's the problem here?
> I use braces to get timely destructors, but I find the "middle of nowhere" braces kind of embarrassing.
Why? The braces denote the lifetime of the objects declared after the opening brace. It's *exactly* the concept you want.
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ?
Yes. Braces. Or a macro so those braces don't offend your sensibilities. Try: #define \ CREATEOBJECTWITHLIMITEDSCOPEWITHOUTUSINGBRACESBECAUSEIFINDTHEMEMBARRASINGWH ATEVERTHEHELLTHATMEANS(x) {x; #define DESTROYTHELASTSETOFOBJECTSWITHLIMITEDSCOPETHATICREATEDWITHOUTACLOSINGBRACE( x) }
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire& release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing. > something like:
This is incomplete! You should never be able to copy a lock object.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called > // do more stuff > ... > }
So do I. I do not know of another way. Sometime I have considered this: //... { Lock myLock(data_mutex); // use locked data ... }
But I don't find it much better. It save a line but potentially confuses pothers.
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ?
I do not know of a way - but maybe you can find some code examples for the new C++0x threading features that provide a "better" way.
> for now I'm using an if to do it.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > if (Lock myLock = Lock(data_mutex))
And this will break down if you have a proper lock class that is non-copyable. It is also confusing, because a lock will always evaluate to true (which is the whole point, I know), so there is no need for an if.
I find the braces in the middle of nowhere quite a handy thing at times. I suppose you can expect Lock to fail so it would be wiser to follow the if() {} style here. If the design says it will never fail then I would go with the lonely braces-- unless you are expecting that you might that check sometime in the future.
-- Jyoti
On Nov 26, 3:48 am, Daniel Anderson <woni...@gmail.com> wrote:
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire & release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing. > something like:
> void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called > // do more stuff > ...
> }
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ? > for now I'm using an if to do it.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > if (Lock myLock = Lock(data_mutex)) > { > //use locked data > .... > } // Unlock done by destructor
> // do more stuff > ...
> }
> Is it good programming ? > Is there a better way ?
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire & release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing. > something like:
> void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called > // do more stuff > ...
> }
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ? > for now I'm using an if to do it.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > if (Lock myLock = Lock(data_mutex)) > { > //use locked data > .... > } // Unlock done by destructor
> // do more stuff > ...
> }
> Is it good programming ? > Is there a better way ?
Frankly, I find the "if" worse than a "standalone" block. It obscures intention of the code (there an "if, but there is no "condition" to enter the "if" block).
I don't know of a better way than what you've shown, and I don't consider hanging blocks bad. If you are so bothered, there is nothing wrong in creating a function specifically for your block. Imagine:
This arguably even reads better and you can be pretty sure that you'll normally get no runtime overhead whatsoever (optimization will see that there's only one use of SynchronizedPart and will inline it).
Also, with C++0x, perhaps some clever use of lambdas can even automate creation of "synchronized" stuff, and I would be surprised if someone didn't already do it e.g. with boost::lambda.
On Nov 25, 5:48 pm, Daniel Anderson <woni...@gmail.com> wrote:
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ? > for now I'm using an if to do it.
The whole point of C# "using" is to specify a scope for an object and its disposal. It's a way to emulate the behavior that C++ already supports naturally -- by simply writing object declarations in C++ you get the behavior of C# using. I'm not sure why you are treating it as though it's a special feature of C#.
> Is it good programming ? > Is there a better way ?
Your "if" example is not "bad" programming, just sort of silly and unnecessary (and likely more confusing to someone reading your code). The "better" way IMO is to just use braces as in your original example. What do you think is so bad about plain braces?
> On Nov 25, 11:48 pm, Daniel Anderson<woni...@gmail.com> wrote: >> [...] > I don't know of a better way than what you've shown, and I don't > consider hanging blocks bad. If you are so bothered, there is nothing > wrong in creating a function specifically for your block. Imagine:
> This arguably even reads better and you can be pretty sure that you'll > normally get no runtime overhead whatsoever (optimization will see > that there's only one use of SynchronizedPart and will inline it).
PLEASE, can we stop this whole ""no runtime overhead whatsoever (optimization will see"" stuff? The optimizer is far more limited (some might call it stupid) than such blanket statements admit.
For example, in the above snippet, unless SynchronizedPart is marked as static or enclosed in an anonymous namespace, the compiler/optimizer should assume external linkage and as such will treat this function no differently than any other function, no matter how often it's used.
Oh wait, you could also mark it as inline, except, to quote one arguably popular compilers[1] docs:
The inline keyword tells the compiler that inline expansion is preferred. However, the compiler can create a separate instance of the function (instantiate) and create standard calling linkages instead of inserting the code inline.
And [2], In some cases, the compiler will not inline a particular function for mechanical reasons. For example, the compiler will not inline:
* A function if it would result in mixing both SEH and C++ EH. * Some functions with copy constructed objects passed by value[...] * Functions returning an unwindable object by value[...] * [...] * A function with a try (C++ exception handling) statement.
So if your fn is containing a simple innocent try block, MS VC++ ain't ever able to inline it! If SynchronizedPart happens to return a non-void non-trivial object by value: no inlining!
NOTE - this reply is not intended to imply that a user should overmuch care about these inlining *details*, nor should it imply that the use of a separate function should be avoided!
Its point is rather to point out that peppering our replys with "trust your optimizer" statements is by no means always appropriate.
> On Nov 25, 5:48 pm, Daniel Anderson <woni...@gmail.com> wrote:
>> Hi!
>> I often have to acquire locks and release them after I'm finished with >> them. >> I use constructor/destructor to acquire & release locks. everything >> works fine. >> sometime I must acquire a lock for few instructions, then release it >> in the middle of a big function. I use braces to get timely >> destructors, but I find the "middle of nowhere" braces kind of >> embarrassing.
> I guess it's a matter of taste. For me the curly braces are very > natural way of denoting the block.
> Putting aside the errors in the code above, the only reason "operator > bool" exists in the class is to make if() construct possible, it's not > required for Lock proper functionality, which violates a good design > rule: make interface complete and minimal.
well, yes in the example I've shown bool always return true, but it could be use in case lock could not be acquired which would allow an else part. on this I have not decided if I should throw in the constructor or use the else part. I will probably play with it a bit before deciding
>> void someFunc() >> { >> // do some stuff >> ... >> // now time to update share data >> { >> Lock myLock(data_mutex); >> //use locked data >> .... >> } // destructor called >> // do more stuff >> ...
>> }
>> I would like to have something like the using keyword in c#. >> Is there a way to fake it in C++ ?
> That's one of the common mistakes people switching to another language > do -- is trying to fake what they are used to in a different language. > That usually causes grief for everybody who has to deal with that > code. Each language commands its own style, the only way to write good > code is to learn and use it.
I am not switching from c#, I was using an example. I find in this case the C# syntax clearer. Language do not command style, it is people who define style, language is only a tool
>> for now I'm using an if to do it.
>> void someFunc() >> { >> // do some stuff >> ... >> // now time to update share data >> if (Lock myLock = Lock(data_mutex)) >> {
> That assumes that Lock is copy-constructible or move-constructible, > which it's not -- because mutex is neither copy-constructible nor move- > constructible. Allowing that would lead to unsafe code causing > deadlocks or races.
yes, but it happen that my compiler is getting rid of the copy contructor and directly construct my object as if I was doing:
if (Lock myLock(data_mutex))
I know it is not portable, but this is not the point of this post. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
> On Nov 25, 5:48 pm, Daniel Anderson <woni...@gmail.com> wrote:
>> Hi!
>> I often have to acquire locks and release them after I'm finished with >> them. >> I use constructor/destructor to acquire & release locks. everything >> works fine. >> sometime I must acquire a lock for few instructions, then release it >> in the middle of a big function. I use braces to get timely >> destructors, but I find the "middle of nowhere" braces kind of >> embarrassing. >> something like:
>> void someFunc() >> { >> // do some stuff >> ... >> // now time to update share data >> { >> Lock myLock(data_mutex); >> //use locked data >> .... >> } // destructor called >> // do more stuff >> ...
>> }
> Some don't even know or haven long forgotten that you can create > blocks arbitrarily like this. I agree that it doesn't look nice, but > it has a lot of uses and i think there's nothing wrong with using it. > It's an incredibly simple and elegant way of solving this problem.
Simple, yes. I've doing it for a long time elegant, I use to think so, until someone remove some braces in my code that where there for RAII, since I do not think it is elegant
>> I would like to have something like the using keyword in c#. >> Is there a way to fake it in C++ ?
> This is a C++ forum. C# is relevant to this question, but for those of > us who haven't worked with it, please post a short example.
>> for now I'm using an if to do it.
>> void someFunc() >> { >> // do some stuff >> ... >> // now time to update share data >> if (Lock myLock = Lock(data_mutex)) >> { >> //use locked data >> .... >> } // Unlock done by destructor
>> // do more stuff >> ...
>> }
> You seem to be implying that this if statement will always evaluate to > true (since i assume this code is equivalent to your first example), > but when i see an "if" in any code, i always assume that it will > sometimes not evaluate to true. On the other hand, it reminds me of > this: > std::weak_ptr<int> wp; > void f() { > if( std::shared_ptr<int> sp = wp.lock() ) > ; // do something > }
>> Is it good programming ?
> What a subjective question!
according to Plato (or was it Socrates) good is not subjective :)
>> Is there a better way ?
> I think creating an arbitrary scope is one of the simplest and least > error prone ways to do this. I'm sure at least one person (if not you) > will disagree with me, but i like simple. I suppose you could create a
I do not disagree, I'm just looking for advice
> class that inputs a function, locks, calls the function, then unlocks, > and you could use C++0x lambdas to integrate it into your current code > without too much refactoring, but that means you'll have to maintain > the locking class and every function/class/etc that uses it. I guess > i'm not the most articulate so i'll use someone else's words: > "Perfection is achieved not when you have nothing more to add, but > when you have nothing left to take away." ~ Antoine de Saint-Exupery.
this is a good guy this Antoine. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
> On Nov 25, 5:48 pm, Daniel Anderson <woni...@gmail.com> wrote:
>> I would like to have something like the using keyword in c#. >> Is there a way to fake it in C++ ? >> for now I'm using an if to do it.
> The whole point of C# "using" is to specify a scope for an object and > its disposal. It's a way to emulate the behavior that C++ already > supports naturally -- by simply writing object declarations in C++ you > get the behavior of C# using. I'm not sure why you are treating it as > though it's a special feature of C#.
>> Is it good programming ? >> Is there a better way ?
> Your "if" example is not "bad" programming, just sort of silly and > unnecessary (and likely more confusing to someone reading your code). > The "better" way IMO is to just use braces as in your original > example. What do you think is so bad about plain braces?
I've worked with plenty of people at different places. where I work now, we have plenty of "not talented" programmer (maybe I'm one of them) . In the past it happen that some of my stand alone braces where removed by some programmers that did not understand the idioms. Now I cannot put comments to say why I've put braces, as my boss forbid them. For him putting comments means that the code is not clear and he does not want code that is not clear. Also he reasoned that if there is no comments, people will have to understand the code before modifying it.
So I'm trying to find a way that people will not remove my braces.
doing:
If (Lock Mylock(mutex)) {...}
could be read by others as: If I could lock this mutex, do this
while empty braces do not seem to convey more meaning than: hey I starting a new block
I could have use a for loop, as it seems more natural to declare variable ex:
For(Lock myLock(mutex); myLock.IsLock(); MyLock.Unlock()) { // do your deed
}
But the reading of the code does not convey the proper meaning (I think)
Anyway, I understand people comments. I just came here for some advices, and to see if someone thought about another way of doing the locking/unlocking
> On 27.11.2010 01:22, Goran wrote: > > On Nov 25, 11:48 pm, Daniel Anderson<woni...@gmail.com> wrote: > >> [...] > > I don't know of a better way than what you've shown, and I don't > > consider hanging blocks bad. If you are so bothered, there is nothing > > wrong in creating a function specifically for your block. Imagine:
> > This arguably even reads better and you can be pretty sure that you'll > > normally get no runtime overhead whatsoever (optimization will see > > that there's only one use of SynchronizedPart and will inline it).
> PLEASE, can we stop this whole ""no runtime overhead whatsoever (optimization > will see"" stuff? The optimizer is far more limited (some might call it stupid) > than such blanket statements admit.
> For example, in the above snippet, unless SynchronizedPart is marked as static > or enclosed in an anonymous namespace, the compiler/optimizer should assume > external linkage and as such will treat this function no differently than any > other function, no matter how often it's used.
Well, I did write "you can be pretty sure that you'll normally get no runtime overhead whatsoever" ( reading again, that "normally" is rather bad writing :-) ).
I actually disagree with external linkage part. Compilers both can and will inline the function even when it has external linkage. I was surprised when I first saw that, but now I know they do it, and it's a good thing :-) .
Also, here, we're dealing with synchronization primitives, which I think are more expensive than a function call (provided that there __is__ one). If nothing else, there's a function call to enter the primitive.
> ... point is rather to point out that peppering our replys with "trust your > optimizer" statements is by no means always appropriate.
I firmly believe that in this case, it is appropriate to trust it. This is of course not to say that I __know__ that there will not be any overhead, one can't ever tell without actual code.
> I often have to acquire locks and release them after I'm finished with > them. > I use constructor/destructor to acquire& release locks. everything > works fine. > sometime I must acquire a lock for few instructions, then release it > in the middle of a big function. I use braces to get timely > destructors, but I find the "middle of nowhere" braces kind of > embarrassing. > something like:
> void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called > // do more stuff > ... > }
> I would like to have something like the using keyword in c#. > Is there a way to fake it in C++ ?
The alternative to creating a scope just to unlock the mutex at a particlular point, it may be simpler to provide unlock() function on the lock, e.g.:
> void someFunc() > { > // do some stuff > ... > // now time to update share data > if (Lock myLock = Lock(data_mutex)) > { > //use locked data > .... > } // Unlock done by destructor
> // do more stuff > ... > }
> Is it good programming ?
If statement naturally means it is conditional, so that a reader of such code may be led to think that obtaining the lock may fail and the control flow may skip the block guarded by if.
On Nov 28, 9:31 am, Daniel Anderson <woni...@gmail.com> wrote:
> I've worked with plenty of people at different places. > where I work now, we have plenty of "not talented" programmer (maybe > I'm one of them) . In the past it happen that some of my stand alone > braces where removed by some programmers that did not understand the > idioms. > Now I cannot put comments to say why I've put braces, as my boss > forbid them. > For him putting comments means that the code is not clear and he does > not want code that is not clear. > Also he reasoned that if there is no comments, people will have to > understand the code before modifying it.
> So I'm trying to find a way that people will not remove my braces.
I think you are trying to solve the wrong "problem" here. The issue isn't clarity, it's a lack of competence of other programmers in the language you are using. It would be one thing if you were doing something relatively complicated such as template metaprogramming that others may have trouble with, but you are simply using RAII for scoping a lock, which is not exactly an uncommon odd idiom at all whether it be for locks or for more general resource management. If people are just randomly removing braces for no reason then they need to be informed to simply not do that and understand why. Rather than complicate code by introducing unnecessary control statements couldn't someone just send out a brief email explaining that braces are not superfluous because they are there for RAII? I realize that not everyone has the same amount of experience with C++ and I understand that it may seem subtle to people new to the language, but I can't imagine that this would be something horribly difficult to teach. If people understand what a destructor is then the point should be easy to make clear.
Anyway, that's just my opinion on the matter. Obviously it's up to your boss, but I would at least suggest this.
> On Nov 27, 1:40 am, Matt Calabrese<rivo...@gmail.com> wrote: >> On Nov 25, 5:48 pm, Daniel Anderson<woni...@gmail.com> wrote:
>>> I would like to have something like the using keyword in c#. >>> Is there a way to fake it in C++ ? >>> for now I'm using an if to do it.
>> The whole point of C# "using" is to specify a scope for an object and >> its disposal. It's a way to emulate the behavior that C++ already >> [...] >> The "better" way IMO is to just use braces as in your original >> example. What do you think is so bad about plain braces?
> I've worked with plenty of people at different places. > where I work now, we have plenty of "not talented" programmer (maybe > I'm one of them) . In the past it happen that some of my stand alone > braces where removed by some programmers that did not understand the > idioms. > Now I cannot put comments to say why I've put braces, as my boss > forbid them. > For him putting comments means that the code is not clear and he does > not want code that is not clear. > Also he reasoned that if there is no comments, people will have to > understand the code before modifying it.
> So I'm trying to find a way that people will not remove my braces.
Oh my :-)
In this case, I would reccomend a macro. Seriously. It may actually be the least trouble.
void someFunc() { // do some stuff ... // now time to update share data START_LOCKSCOPE(data_mutex) Lock myLock(data_mutex); //use locked data .... } // do more stuff ...
}
Of course, better would be to: * Educate your colleagues about this idom. (It's not *that* hard) * Convince your boss that some comments might be ok.
Daniel Anderson <woni...@gmail.com> wrote in news:6e1a660e-fcd7-48c8- 8fcf-f3f351a23...@r21g2000pri.googlegroups.com:
> I've worked with plenty of people at different places. > where I work now, we have plenty of "not talented" programmer (maybe > I'm one of them) . In the past it happen that some of my stand alone > braces where removed by some programmers that did not understand the > idioms. > Now I cannot put comments to say why I've put braces, as my boss > forbid them. > For him putting comments means that the code is not clear and he does > not want code that is not clear. > Also he reasoned that if there is no comments, people will have to > understand the code before modifying it.
> So I'm trying to find a way that people will not remove my braces.
In this case I would suggest #define BEGIN_LOCKED_SECTION(mutex) {Lock myLock(mutex); #define END_LOCKED_SECTION }
but I'm sure your boss has forbidden macros as well ;-)
> On Nov 26, 8:22 pm, "Hak...@gmail.com"<hak...@gmail.com> wrote: >> On Nov 25, 5:48 pm, Daniel Anderson<woni...@gmail.com> wrote:
>>> void someFunc() >>> { >>> // do some stuff >>> ... >>> // now time to update share data >>> { >>> Lock myLock(data_mutex); >>> //use locked data >>> .... >>> } // destructor called >>> // do more stuff >>> ...
>>> }
>> Some don't even know or haven long forgotten that you can create >> blocks arbitrarily like this. I agree that it doesn't look nice, but >> it has a lot of uses and i think there's nothing wrong with using it. >> It's an incredibly simple and elegant way of solving this problem. > Simple, yes. I've doing it for a long time > elegant, I use to think so, until someone remove some braces in my > code that where there for RAII, since I do not think it is elegant
Well elegance is often a matter ot taste, but anyone who remove braces from a piece of code without understanding the code gets much of what they deserve. OTOH anyone who uses this kind of idiom without a comment is being rather optimistic about the capabilities of maintenance programmers.
>>> I would like to have something like the using keyword in c#. >>> Is there a way to fake it in C++ ?
>> This is a C++ forum. C# is relevant to this question, but for those of >> us who haven't worked with it, please post a short example.
>>> for now I'm using an if to do it.
>>> void someFunc() >>> { >>> // do some stuff >>> ... >>> // now time to update share data >>> if (Lock myLock = Lock(data_mutex)) >>> { >>> //use locked data >>> .... >>> } // Unlock done by destructor
Well if you really want something other than comments to stop idiots breaking your code then
bool just_once(false); do { // place your code here
} while(just_once);
Though i think that is awful :)
>>> // do more stuff >>> ...
>>> }
>>> Is it good programming ?
>> What a subjective question!
> according to Plato (or was it Socrates) good is not subjective :)
The word 'good' has several meanings and in the current context I yake it to mean 'socially acceptable' (the society being programmers) as opposed to morally good which I think was what the Greek philosophers were meaning. And I guess that in classical Greek the words for the two meanings were almost certainly different but it is more than 50 years since I had to toil at classical Greek.
-- Note that robinton.demon.co.uk addresses are no longer valid.
On Nov 28, 9:31 am, Daniel Anderson <woni...@gmail.com> wrote:
> I've worked with plenty of people at different places. > where I work now, we have plenty of "not talented" programmer (maybe > I'm one of them) . In the past it happen that some of my stand alone > braces where removed by some programmers that did not understand the > idioms. > Now I cannot put comments to say why I've put braces, as my boss > forbid them. > For him putting comments means that the code is not clear and he does > not want code that is not clear. > Also he reasoned that if there is no comments, people will have to > understand the code before modifying it.
That sounds... less than ideal. Well, if it's really so bad, let me expand on the solution i mentioned, but give an example this time.
> void someFunc() > { > // do some stuff > ... > // now time to update share data > { > Lock myLock(data_mutex); > //use locked data > .... > } // destructor called > // do more stuff > ...
> }
becomes
void someFunc() { // do some stuff ... // now time to update share data lock_do( data_mutex, [](/*...*/) -> void { //use locked data .... } ); // do more stuff ...
}
I haven't tested the code because i have never used lambdas before in actual code, but the idea's what's important. If you can't comment your code, and you can't teach those around you about arbitrary braces, but you can use c++0x features, this is a compromise. Without c ++0x, i guess you could still move all that code to external functions if you wanted.
Of coarse, you always have the chance that someone comes by and doesn't understand the code, but when they see that scary lambda syntax, maybe they'll flee before modifying it. ;)
> >> Is it good programming ?
> > What a subjective question!
> according to Plato (or was it Socrates) good is not subjective :)
A little off topic, but: We all know that charity is good and murder is bad, but think of how many thousands of years of social evolution it took us humans to come to that conclusion. In contrast, none of what we now call programming existed even 100 years ago. We can't even all agree on what editor to use, brace style, naming conventions, or language. One might say a macro is objectively bad, but others might say when used right, macros are objectively good.
Perhaps if good was not subjective, we wouldn't have to share our ideas like this in order to be better at programming.
> On Nov 27, 8:13 pm, "Martin B."<0xCDCDC...@gmx.at> wrote: >> On 27.11.2010 01:22, Goran wrote: >>> On Nov 25, 11:48 pm, Daniel Anderson<woni...@gmail.com> wrote: >>>> [...] >>> I don't know of a better way than what you've shown, and I don't >>> consider hanging blocks bad. If you are so bothered, there is nothing >>> wrong in creating a function specifically for your block. Imagine:
>>> [...] >>> normally get no runtime overhead whatsoever (optimization will see >>> that there's only one use of SynchronizedPart and will inline it).
>> PLEASE, can we stop this whole ""no runtime overhead whatsoever (optimization >> will see"" stuff? [...]
>> For example, in the above snippet, unless SynchronizedPart is marked as static >> or enclosed in an anonymous namespace, the compiler/optimizer should assume >> external linkage and as such will treat this function no differently than any >> other function, no matter how often it's used. > [...]
> I actually disagree with external linkage part. Compilers both can and > will inline the function even when it has external linkage. I was > surprised when I first saw that, but now I know they do it, and it's a > good thing :-) .
Which compiler? Which options? Which platform? Which version?
I agree that a compiler+optimizer+linker *may* inline external-linkage functions if something like whole program optimization is enabled, in which case "it" knows that it does not need the external linkage.
Otherwise I do not see how it could make sense for a *compiler* to inline a function *not marked* as inline if it has to expect the fn to be used (by the linker) from another translation unit.
>> ... point is rather to point out that peppering our replys with "trust your >> optimizer" statements is by no means always appropriate.
> I firmly believe that in this case, it is appropriate to trust it. > This is of course not to say that I __know__ that there will not be > any overhead, one can't ever tell without actual code.
If the OP snippet "//use locked data" is longer than a few lines, I would trust the VC++ optimizer to *not* inline the separate function, even if its only used once. (Which probably wouldn't hurt overmuch, as the fn call overhead would likely be negligible.