- Delphi 10.1 Berlin Professional upgrade
- Mobile Add-On Pack
- "Bonus Packet" with VCL and FireMonkey Styles, Konopka VCL Controls and Marco Cantù's Object Pascal Handbook
Let's see what happens...
Parallel.For method. The seemingly innocuous code lead to an "obscure situation" exactly as described in this blog post by Stephen Toub:...iterations are handed out in indivisible chunks, and only one thread is involved in the processing of a particular chunk. This has implications for interdependencies between iterations. If iterationThe problem in this case was exactly as described above: there were blocking wait dependencies between the tasks in a producer/consumer pattern. The solution (once the problem was clear) was relatively simple: don't rely on the default partitioning ofiblocks waiting for iterationi + 1to be completed, and iterationsiandi + 1are both allocated to the same chunk, the loop will likely deadlock. The thread processing those iterations will block processing iterationi, but as that thread is also responsible for processing iterationi + 1, iterationi + 1will never get processed and iterationiwill never unblock.
Parallel.For; provide your own to avoid the potential deadlock.Parallel.For implementation in .NET and trade-offs between simplicity, overheads, and load balancing:
program Test;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Rtti;
type
TTestAttribute = class(TCustomAttribute)
private
FName: string;
public
constructor Create(const AName: string);
property Name: string read FName;
end;
[TTestAttribute('AtInterface')]
ITestInterface = interface(IInvokable)
['{92A8107E-B40E-4786-A02E-251EA0DB3937}']
[TTestAttribute('AtMethod')]
function GetValue: string;
[TTestAttribute('AtMethod')]
procedure SetValue(const AValue: string);
[TTestAttribute('AtProperty')]
property Value: string read GetValue write SetValue;
end;
constructor TTestAttribute.Create(const AName: string);
begin
inherited Create;
FName := AName;
end;
procedure ShowAttributes(const Attributes: TArray<TCustomAttribute>);
var
Attr: TCustomAttribute;
begin
for Attr in Attributes do
if Attr is TTestAttribute then
Writeln(Format('%s(''%s'')', [Attr.ClassName, TTestAttribute(Attr).Name]))
else
Writeln(Attr.ClassName);
end;
procedure Main;
var
Ctx: TRttiContext;
AType: TRttiInterfaceType;
Attributes: TArray<TCustomAttribute>;
Method: TRttiMethod;
Prop: TRttiProperty;
begin
Ctx := TRttiContext.Create;
AType := Ctx.GetType(TypeInfo(ITestInterface)) as TRttiInterfaceType;
Writeln(Format('Attributes on the interface ''%s'':', [AType.Name]));
ShowAttributes(AType.GetAttributes);
Writeln;
for Method in AType.GetMethods do
begin
Writeln(Format('Attributes on method ''%s'':', [Method.Name]));
ShowAttributes(Method.GetAttributes);
end;
Writeln;
for Prop in AType.GetProperties do
begin
Writeln(Format('Attributes on property ''%s'':', [Prop.Name]));
ShowAttributes(Prop.GetAttributes);
end;
end;
begin
try
Main;
Readln;
except
on E: Exception do
begin
ExitCode := 1;
Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
end;
end;
end.Attributes on the interface:
TTestAttribute('AtInterface')
Attributes on method 'GetValue':
TTestAttribute('AtMethod')
Attributes on method 'SetValue':
TTestAttribute('AtMethod')AType.GetProperties returns an empty array; there is no RTTI for interface properties.