Board index » delphi » Re: D2005 Code Folding

Re: D2005 Code Folding


2005-08-11 06:48:15 AM
delphi101
Dave Nottage [TeamB] writes:
Quote
Brion L. Webster writes:


>What happens if the ECS call fails with an exception? Won't that
>cause "bad stuff" to happen? that is what the MSDN docs seem to
>suggest.


Exactly. Allen is wrong.

He's not wrong ...
You two on TeamB are wrong. ;-)
All he needs to do to make the code more robust is set a boolean value after calling ECS.
This way he can check the value before freeing the critical section.
 
 

Re: D2005 Code Folding

Brian Moelk writes:
Quote

FTR, you can add my multi-threaded experience to the "ECS; try finally LCS;
end;" group.
Allen's code was basically correct and more future proof.
I would personally check to make sure if it entered the critical section before freeing it.
That's all he needed to do IMAO.
 

Re: D2005 Code Folding

Quote
He's not wrong ...
You two on TeamB are wrong. ;-)
It's not only TeamB.
Quote
All he needs to do to make the code more robust is set a boolean value
after calling ECS.
This way he can check the value before freeing the critical section.
In your code (in your other post), there is little difference between
putting the ECS outside the try, save the extra EnteredCriticalSection
variable declaration.
 

Re: D2005 Code Folding

Jason Southwell writes:
Quote
>I didn't miss the point, I understand exactly what he is saying. It
>is my opinion after years of real world thread programming in Delphi
>that you and he are both wrong.


Technically, you are using exception handlers incorrectly.

Craig and Ivo are correct in this and they together likely have many
more years of thread programming experience than you. And if you throw
my experience into the hat...
I'm sorry but I do not think Craig's and Ivo's way was too great
if you still want to execute code in or after the try block.
( If an exception was to occur execution would have exit the routine. )
Moreover, I believe it is a good practice of putting routines you think
are going to fail in a try finally or a try except block.
So, in this case, I think Allen was 100% correct in what he wrote.
But I do believe he needs some more code in the try finally block
to make sure he entered the critical section before freeing it.
 

Re: D2005 Code Folding

Quote
Allen's code was basically correct and more future proof.
Future proof?
Quote
I would personally check to make sure if it entered the critical section
before freeing it.
That's all he needed to do IMAO.
Then it is exactly the same as putting the ECS outside the try.
 

Re: D2005 Code Folding

Allen Drennan napsal(a):
Quote
If you ever called
EnterCriticalSection and didn't always call the corresponding
LeaveCriticalSection your program will deadlock at the next
EnterCriticalSection.
And that is the point. Of course, I agree that there always must be a
matching LCS call for each ECS call. By putting a ECS call *inside*
the try..finally block you actually protecting this ECS call itself
and take a care of situations where this ECS call could raise an
exception. But why? Instead, you have to protect the only code that
executes *after* the critical section was acquired (i.e. after a
successful call to ECS) in order to make sure this code does not throw
any exceptions so that a call to LCS in finally clause can be
guaranteed to occur in any case. Do you see the difference?
Quote
When its within a Try..Finally block this can not happen since the
Finally is always called.
LCS call in finally clause should not be called always. It should be
called everytime the preceding ECS call succeeds.
--
Ivo Bauer
Software Developer
OZM Research, s.r.o.
________________________________________________
ModLink - MODBUS Messaging Components for Delphi
www.ozm.cz/ivobauer/modlink/
________________________________________________
 

Re: D2005 Code Folding

Michael Anonymous napsal(a):
Quote
I would use something like this if it was that important:

EnteredCriticalSection := false;
try
EnterCriticalSection(FConferencesLock);
EnteredCriticalSection := true;

{ do something with FConferences }
finally
if ( EnteredCriticalSection ) then
LeaveCriticalSection(FConferencesLock);
end;
Which is the same as putting ECS call in front of try..finally block,
isn't it?
--
Ivo Bauer
Software Developer
OZM Research, s.r.o.
________________________________________________
ModLink - MODBUS Messaging Components for Delphi
www.ozm.cz/ivobauer/modlink/
________________________________________________
 

Re: D2005 Code Folding

Michael Anonymous napsal(a):
Quote
I'm sorry but I do not think Craig's and Ivo's way was too great
if you still want to execute code in or after the try block.
( If an exception was to occur execution would have exit the routine. )
And the point is?
Quote
Moreover, I believe it is a good practice of putting routines you think
are going to fail in a try finally or a try except block.
So, in this case, I think Allen was 100% correct in what he wrote.
Of course it is a good practise to protect the code you expect to fail
in try..finally block. But in this case you're *not* interested in
trapping exception that the ECS call may throw. What you need here to
accomplish is to protect the code executing *after* the critical
section was entered/acquired in order to ensure that corresponding LCS
call is not bypassed.
--
Ivo Bauer
Software Developer
OZM Research, s.r.o.
________________________________________________
ModLink - MODBUS Messaging Components for Delphi
www.ozm.cz/ivobauer/modlink/
________________________________________________
 

Re: D2005 Code Folding

Michael Anonymous napsal(a):
Quote
His practice was a great practice IMAO.
In some cases you still want to execute code IN or AFTER the finally
black NO MATTER WHAT.
And the point is?
Quote
Only an exception handling wizard would want to put the code outside of
the try finally block...
making the code slightly harder to deal with errors unless your the
wiz-kid who actually wrote the damn stuff.
Huh?
--
Ivo Bauer
Software Developer
OZM Research, s.r.o.
________________________________________________
ModLink - MODBUS Messaging Components for Delphi
www.ozm.cz/ivobauer/modlink/
________________________________________________
 

Re: D2005 Code Folding

Brian Moelk writes:
Quote
>Allen's code was basically correct and more future proof.


Future proof?
" the act of trying to anticipate future developments and taking action
to minimize possible negative consequences"
Source: en.wikipedia.org/wiki/Future_proof
Quote

>I would personally check to make sure if it entered the critical section

before freeing it.

>That's all he needed to do IMAO.


Then it is exactly the same as putting the ECS outside the try.

No, actually it is not.
Putting the call to ECS outside the try block creates a situation where
if the ECS raises an exception,
one's code in or after the try block might never be executed.
 

Re: D2005 Code Folding

Brian Moelk writes:
Quote
In your code (in your other post), there is little difference between
putting the ECS outside the try, save the extra EnteredCriticalSection
variable declaration.
That's correct.
Adding little difference can make one's code even more robust.
 

Re: D2005 Code Folding

Michael,
Quote
>Exactly. Allen is wrong.
>

He's not wrong ...
You two on TeamB are wrong. ;-)

All he needs to do to make the code more robust is set a boolean value
after calling ECS.
This way he can check the value before freeing the critical section.
All you are doing by adding boolean variables like that is attempting to
re-invent the "try ... finally" semantics that you are deliberately
subverting by putting code in the wrong place:
var
Success : Boolean;
sl : TStringList;
begin
Success := False;
try
sl := TStringList.Create; // Danger of out of memory exception.
Success := True;
DoStuff;
finally
if Success then
sl.Free;
end;
end;
...is that code robust? Yes, for the most part. Is it 'good code'? No, it is
a pointless workaround for the fact that:
var
sl : TStringList;
begin
try
sl := TStringList.Create; // Danger of out of memory exception.
DoStuff;
finally
sl.Free;
end;
end;
...is simply ASKING for an access violation. Is the problem the lack of a
boolean variable? No. The problem is that the programmer should have
written:
var
sl : TStringList;
begin
sl := TStringList.Create; // Danger of out of memory exception.
try
DoStuff;
finally
sl.Free;
end;
end;
...in the first place.
Eryk
PS: This reminds me of threads back in D1 days when 'exceptions' were a 'new
idea' to many. "Twilight Zone" !!
 

Re: D2005 Code Folding

Ivo Bauer writes:
Quote
Michael Anonymous napsal(a):

>I would use something like this if it was that important:
>
>EnteredCriticalSection := false;
>try
>EnterCriticalSection(FConferencesLock);
>EnteredCriticalSection := true;
>
>{ do something with FConferences }
>finally
>if ( EnteredCriticalSection ) then
>LeaveCriticalSection(FConferencesLock);
>end;


Which is the same as putting ECS call in front of try..finally block,
isn't it?

No, actually it isn't.
If ECS raises an exception,
the code in or after the try block may never be executed.
 

Re: D2005 Code Folding

Michael Anonymous napsal(a):
Quote
>Which is the same as putting ECS call in front of try..finally block,
>isn't it?

No, actually it isn't.
If ECS raises an exception,
the code in or after the try block may never be executed.
In case ECS call raises an exception, neither the code inside the try
clause nor the code inside the finally should be executed. If you put
ECS call inside try..finally block and this ECS call raises an
exception, the LCS inside the finally clause will get called, which is
wrong (it should be called *if* and *only*if* the preceding ECS call
succeeded).
--
Ivo Bauer
Software Developer
OZM Research, s.r.o.
________________________________________________
ModLink - MODBUS Messaging Components for Delphi
www.ozm.cz/ivobauer/modlink/
________________________________________________
 

Re: D2005 Code Folding

Eryk writes:
Quote
var
sl : TStringList;
begin
try
sl := TStringList.Create; // Danger of out of memory exception.
DoStuff;
finally
sl.Free;
end;
end;

...is simply ASKING for an access violation. Is the problem the lack of a
boolean variable? No. The problem is that the programmer should have
written:

var
sl : TStringList;
begin
sl := TStringList.Create; // Danger of out of memory exception.
try
DoStuff;
finally
sl.Free;
end;
end;

...in the first place.

Eryk
I still don't think your example is like the ECS subroutine.
In the case of the ESC subroutine,
it's worth take a few extra measure to insure that your program continues to run smoothly and
not enter into some sort of deadlock.