Forum > FPC development

Pascal feature proposal: begin(syncObj)

(1/4) > >>

Cooler:
When you develop a thread-safe code you probably use critical sections (or other sync objects) very often.
So there are TONS of constructions like:
 

--- Code: ---  EnterCriticalSection(cSect);
  try
   ...
  finally
   LeaveCriticalSection(cSect);
  end;
--- End code ---
 
Besides this makes code bulky, it enforces programmer to carefully track where the protection is really needed and where it is redundant.
Wrong decision here causes performance degradation (best case) or sync issues like deadlocks (in worst case).

So my proposal has 2 goals:
- make code cleaner and more readable;
- free programmer from manual optimization (that can lead to severe bugs), which can be done by compiler.

I propose to extend the "begin ... end" brackets construction syntax like this:


--- Code: --- begin(cSect)
  ...
 end;
--- End code ---

which is equivalent to the code example above, where cSect may be an RTL critical section or RTL sync object with Lock()/Unlock() or Enter()/Leave() methods.
The compiler can then optimize this construction and omit synchronization if:
- the code section doesn't reference any non-local variables (unnecessary call),
- the code section is always executed from places already protected by the same sync object (redundant call).
In addition, it can also make 2 routine instances (protected and unprotected) to use each version from appropriate places.
So this syntax makes it much easier to make code thread-safe without headache about overheads and making the code bulky and unreadable.

marcov:
Have you looked at http://www.freepascal.org/faq.var#extensionselect   ?

Shorthand notations are generally frowned upon as motivation for language. (unless it is REALLY,REALLY common)

However I have tons of (250kloc) threadsafe code, and maybe have 20 of such constructs because they are generally deep in the business objects, and the construct is autoexpanded by the IDE, so typing is not even the limit.

Cooler:

--- Quote from: marcov on July 26, 2015, 10:25:56 am ---Have you looked at http://www.freepascal.org/faq.var#extensionselect   ?

--- End quote ---
No, thanks for the info.


--- Quote ---Shorthand notations are generally frowned upon as motivation for language. (unless it is REALLY,REALLY common)

--- End quote ---
It's not just shorthand, it's about doing less code maintenance work. It's like using dynamic arrays for data instead of manual heap allocation and bothering about memory release - easier to write, easier to read/understand, less chances to make a bug => makes language more attractive and competitive.
Anyway, there are many shorthand notations already supported in the language (with, for..in, automatic reference counting, string operators, implicit string conversions and so on), so it looks a bit strange. The language is evolving. BTW, Objective-C has similar @synchronized directive.


--- Quote ---and the construct is autoexpanded by the IDE, so typing is not even the limit.
--- End quote ---
Could you please explain this?

BeniBela:
That is why I always say  block scoped variables, referenced counted classes and automatic type inference are mandatory features for a language.

Then you could write


--- Code: ---begin
  var guard := synchronizedSection(cSect);
end;

--- End code ---


But for .. in is a tiny step in the right direction.

You can write


--- Code: ---var temp: boolean;
//begin
  for temp in synchronizedSection(cSect) do begin
   
  end;


--- End code ---

with something like


--- Code: ---type
  TSectionGuardEnumerator = class
  private
    FCurrent: boolean;
    section: PRTLCriticalSection;
  public
    function MoveNext: Boolean;
    property Current: boolean read FCurrent;
    function GetEnumerator: TSectionGuardEnumerator;
    destructor destroy(); override;
  end;
  function synchronizedSection(var section: TRTLCriticalSection): TSectionGuardEnumerator;
  begin
    result := TSectionGuardEnumerator.Create;
    result.section:=@section;
    result.FCurrent := true;
    EnterCriticalsection(section);
  end;

  destructor TSectionGuardEnumerator.destroy;
  begin
    LeaveCriticalsection(section^);
  end;

  function TSectionGuardEnumerator.MoveNext: Boolean;
  begin
    result := Current;
    FCurrent := false;
  end;

  function TSectionGuardEnumerator.GetEnumerator: TSectionGuardEnumerator;
  begin
    result := self;
  end;


--- End code ---

Basile B.:

--- Quote from: Cooler on July 26, 2015, 09:42:27 am ---When you develop a thread-safe code you probably use critical sections (or other sync objects) very often.
So there are TONS of constructions like:
 

--- Code: ---  EnterCriticalSection(cSect);
  try
   ...
  finally
   LeaveCriticalSection(cSect);
  end;
--- End code ---
 
Besides this makes code bulky, it enforces programmer to carefully track where the protection is really needed and where it is redundant.
Wrong decision here causes performance degradation (best case) or sync issues like deadlocks (in worst case).

So my proposal has 2 goals:
- make code cleaner and more readable;
- free programmer from manual optimization (that can lead to severe bugs), which can be done by compiler.

I propose to extend the "begin ... end" brackets construction syntax like this:


--- Code: --- begin(cSect)
  ...
 end;
--- End code ---

--- End quote ---

To make it more versatile (not only dedicated to TCriticalSection, which the compiler doesn't know BTW, it's a library type... ;) ), I'd see more this as an operator that could be overloaded for a particular type, for example:


--- Code: ---operator begin(Value: TCriticalSection);
begin
  Value.Enter;
end;

operator end(Value: TCriticalSection);
begin
  Value.Release;
end;

--- End code ---

Then the compiler could look if the operator overload exists for the variable of the type found within, let's call it, a BeginExpression

Another possible usage:


--- Code: ---operator begin(var Value: TMemoryStream);
begin
  Value := TMemoryStream.Create;
end;

operator end(var Value: TMemoryStream);
begin
  Value.Free;
end;

--- End code ---

The problem is that currently begin is not an expression. It's a terminal token.

Navigation

[0] Message Index

[#] Next page

Go to full version