Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit uMapParallel;
- interface
- uses
- System.SysUtils, System.Generics.Collections, System.Threading, System.SyncObjs, System.Classes,
- System.Generics.Defaults;
- type
- TMapParallel<T> = class
- private
- type
- TMapRef = reference to function(const X: T; const I: Integer): T;
- TIndexedRecord = record
- FIndex: Integer;
- FValue: T;
- constructor Create(AIndex: Integer; AValue: T);
- end;
- protected
- class procedure AddToThreadList(AItem: TIndexedRecord;
- AThreadList: TThreadList<TIndexedRecord>);
- public
- class function Map(const Source: TArray<T>; const Lambda: TMapRef): TArray<T>;
- end;
- implementation
- { TMapParallel<T>.TIndexedRecord }
- constructor TMapParallel<T>.TIndexedRecord.Create(AIndex: Integer; AValue: T);
- begin
- FIndex := AIndex;
- FValue := AValue;
- end;
- { TMapParallel<T> }
- class procedure TMapParallel<T>.AddToThreadList(AItem: TIndexedRecord; AThreadList: TThreadList<TIndexedRecord>);
- begin
- AThreadList.LockList;
- try
- AThreadList.Add(AItem);
- finally
- AThreadList.UnlockList;
- end;
- end;
- class function TMapParallel<T>.Map(const Source: TArray<T>; const Lambda: TMapRef): TArray<T>;
- var
- ThreadList: TThreadList<TIndexedRecord>;
- FinalList: TList<TIndexedRecord>;
- Comparison: TComparison<TIndexedRecord>;
- TmpIndexedRecord: TIndexedRecord;
- begin
- Result := [];
- // Thread-safe unordered storage
- ThreadList := TThreadList<TIndexedRecord>.Create;
- try
- ThreadList.Duplicates := dupAccept;
- // do the job
- TParallel.For(low(Source), high(Source),
- procedure(AIndex: Integer; ALoopState: TParallel.TLoopState)
- begin
- // add item to the ThreadList
- AddToThreadList(TIndexedRecord.Create(AIndex, Lambda(Source[AIndex], AIndex)), ThreadList);
- end);
- // not-thread-safe ordered storage
- FinalList := ThreadList.LockList;
- try
- // specify the comparer
- Comparison := function(const Left: TIndexedRecord; const Right: TIndexedRecord): Integer
- begin
- Result := TComparer<Integer>.Default.Compare(Left.FIndex, Right.FIndex);
- end;
- // sort list by the comparer
- FinalList.Sort(TComparer<TIndexedRecord>.Construct(Comparison));
- // put list items to the result array
- for TmpIndexedRecord in FinalList do
- Result := Result + [TmpIndexedRecord.FValue];
- finally
- ThreadList.UnlockList;
- end;
- finally
- FreeAndNil(ThreadList);
- end;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment