3849 lines
132 KiB
ObjectPascal
3849 lines
132 KiB
ObjectPascal
//////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
///
|
|
/// Mycelium Scenes Library
|
|
/// -----------------------
|
|
///
|
|
/// (c)2007-2020 Michael Schimmel
|
|
/// Ehrenhainstr 40
|
|
/// 42329 Wuppertal / Germany
|
|
/// info@mycelium.net
|
|
///
|
|
/// All rights reserved.
|
|
///
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
unit Myc;
|
|
|
|
interface
|
|
|
|
uses
|
|
{$ifdef FullDebugMode}FastMM5, {$endif}
|
|
System.SysUtils, System.TypInfo, System.Generics.Collections,
|
|
System.Generics.Defaults;
|
|
|
|
{$minenumsize 4}
|
|
|
|
|
|
type
|
|
{$message hint 'Debug-Code! Const Params?'}
|
|
TMyc3Combiner<T, V> = reference to function( const Values: TArray<V> ): T;
|
|
|
|
TMyc3Interpolator<T> = reference to function( Delta: Double; const StartValue: T; out Value: T ): Boolean;
|
|
TMyc3TargetInterpolator<T> = reference to function( Delta: Double; const StartValue, TargetValue: T; out Value: T ): Boolean;
|
|
|
|
EMycInvalidParameter = class( Exception )
|
|
end;
|
|
|
|
EMycInvalidOperation = class( Exception )
|
|
end;
|
|
|
|
TConstFunc<A, T> = reference to function( const aa: A ): T;
|
|
TConstFunc<A, B, T> = reference to function( const aa: A; const bb: B ): T;
|
|
TConstFunc<A, B, C, T> = reference to function( const aa: A; const bb: B; const cc: C ): T;
|
|
TConstFunc<A, B, C, D, T> = reference to function( const aa: A; const bb: B; const cc: C ; const dd: D ): T;
|
|
TConstFunc<A, B, C, D, E, T> = reference to function( const aa: A; const bb: B; const cc: C ; const dd: D; const ee: E ): T;
|
|
TConstProc<A> = reference to procedure( const aa: A );
|
|
TConstProc<A, B> = reference to procedure( const aa: A; const bb: B );
|
|
TConstProc<A, B, C> = reference to procedure( const aa: A; const bb: B; const cc: C );
|
|
|
|
TCompareValues<T> = reference to function( const A, B: T ): Boolean;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMycEnumerator<T> = interface
|
|
function GetCurrent: T;
|
|
function MoveNext: Boolean;
|
|
procedure Reset;
|
|
property Current: T read GetCurrent;
|
|
end;
|
|
|
|
IMyc2Enumerable<T> = interface
|
|
function GetEnumerator: IMycEnumerator<T>;
|
|
end;
|
|
|
|
IMycCountable<T> = interface
|
|
{$region 'property access'}
|
|
function GetCount: Integer;
|
|
function GetItems( Idx: Integer ): T;
|
|
{$endregion}
|
|
property Count: Integer read GetCount;
|
|
property Items[Idx: Integer]: T read GetItems; default;
|
|
end;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IAtomicStack<T> = interface
|
|
function Pop: T;
|
|
function TryPop( out Item: T ): Boolean;
|
|
procedure Push( const Data: T );
|
|
end;
|
|
|
|
TAtomicStack<T> = record
|
|
class function Create: IAtomicStack<T>; static;
|
|
end;
|
|
|
|
TProtected<T: IInterface> = record
|
|
private
|
|
[volatile]
|
|
FItem: T;
|
|
|
|
public
|
|
constructor Create( const AItem: T );
|
|
function Exchange( const Value: T ): T;
|
|
class operator Implicit( const Value: T ): TProtected<T>;
|
|
end;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMyc2Sink = interface
|
|
function Notify: Boolean;
|
|
end;
|
|
|
|
IMyc2Flag = interface( IMyc2Sink )
|
|
function Reset: Boolean;
|
|
end;
|
|
|
|
{$message hint 'Replace TSignalTag by IMycDeletable? '}
|
|
TSignalTag = NativeInt;
|
|
|
|
IMyc2Signal = interface
|
|
function Advise( const Sink: IMyc2Sink ): TSignalTag;
|
|
procedure Unadvise( Tag: TSignalTag );
|
|
end;
|
|
|
|
IMyc2Notifier = interface( IMyc2Sink )
|
|
{$region 'property access'}
|
|
function GetSignal: IMyc2Signal;
|
|
{$endregion}
|
|
property Signal: IMyc2Signal read GetSignal;
|
|
end;
|
|
|
|
IMyc2State = interface( IMyc2Signal )
|
|
{$region 'property access'}
|
|
function GetIsSet: Boolean;
|
|
{$endregion}
|
|
property IsSet: Boolean read GetIsSet;
|
|
end;
|
|
|
|
IMyc2Condition = interface( IMyc2Sink )
|
|
{$region 'property access'}
|
|
function GetState: IMyc2State;
|
|
{$endregion}
|
|
property State: IMyc2State read GetState;
|
|
end;
|
|
|
|
IMyc2Event = interface( IMyc2Condition )
|
|
function Reset: Boolean;
|
|
end;
|
|
|
|
IMycObserver<T: IMyc2Sink> = interface
|
|
function GetItem: T;
|
|
property Item: T read GetItem;
|
|
end;
|
|
|
|
IMycNotifyObserver = IMycObserver<IMyc2Notifier>;
|
|
IMycEventObserver = IMycObserver<IMyc2Event>;
|
|
|
|
TMycStateQueue = record
|
|
private
|
|
FStack: IAtomicStack<IMyc2State>;
|
|
|
|
public
|
|
constructor Create(const AStack: IAtomicStack<IMyc2State>); overload;
|
|
|
|
class function Create: TMycStateQueue; overload; static;
|
|
|
|
procedure Add( const S: IMyc2State );
|
|
procedure WaitFor;
|
|
|
|
end;
|
|
|
|
Signals = record
|
|
private
|
|
class function GetNull: IMyc2Condition; static;
|
|
|
|
public
|
|
class function CreateCounter( Count: Integer ): IMyc2Condition; static;
|
|
class function CreateEvent( Init: Boolean = false ): IMyc2Event; overload; static;
|
|
class function CreateNotifier: IMyc2Notifier; overload; static;
|
|
class function CreateSink(Once: Boolean; const Proc: TProc): IMyc2Sink; overload; static; deprecated;
|
|
class function CreateSink(const Proc: TProc): IMyc2Sink; overload; static;
|
|
class function CreateFlag(Init: Boolean): IMyc2Flag; static;
|
|
|
|
class function CreateObserver<T: IMyc2Sink>( const Signals: array of IMyc2Signal; const Sink: T ): IMycObserver<T>; static;
|
|
class function CreateNotifyObserver( const Signals: array of IMyc2Signal ): IMycNotifyObserver; overload; static;
|
|
class function CreateEventObserver( const Signals: array of IMyc2Signal ): IMycEventObserver; overload; static;
|
|
|
|
class function CreateNotifyObserver( const Signals: IMycCountable<IMyc2Signal> ): IMycNotifyObserver; overload; static;
|
|
class function CreateEventObserver( const Signals: IMycCountable<IMyc2Signal> ): IMycEventObserver; overload; static;
|
|
|
|
class function Concat( const States: array of IMyc2State ): IMyc2State; static;
|
|
class function Union( const Sigs: array of IMyc2Signal ): IMyc2Signal; static;
|
|
|
|
class function IsStatic( const Signal: IMyc2Signal ): Boolean; static; inline;
|
|
class function MakeValid( const Signal: IMyc2Signal ): IMyc2Signal; overload; static; inline;
|
|
class function MakeValid( const Signals: array of IMyc2Signal ): TArray<IMyc2Signal>; overload; static;
|
|
|
|
class property Null: IMyc2Condition read GetNull;
|
|
end;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMyc3Value<T> = interface
|
|
{$region 'property access'}
|
|
function GetValue: T;
|
|
{$endregion}
|
|
property Value: T read GetValue;
|
|
end;
|
|
|
|
TImmutable<T> = record
|
|
private
|
|
FThis: IMyc3Value<T>;
|
|
function GetValue: T; inline;
|
|
function GetHasValue: Boolean; inline;
|
|
class function GetNull: TImmutable<T>; static; inline;
|
|
public
|
|
constructor Create(const AValue: T); overload;
|
|
class operator NotEqual(ALeft, ARight: TImmutable<T>): Boolean;
|
|
class operator Equal(ALeft, ARight: TImmutable<T>): Boolean;
|
|
property Value: T read GetValue;
|
|
property HasValue: Boolean read GetHasValue;
|
|
class property Null: TImmutable<T> read GetNull;
|
|
end;
|
|
|
|
// IDEA:
|
|
// Mutable objects represent exactly *one* property of a dynamic system.
|
|
// As such, they provide a change signal and an immutable value
|
|
// that is *replaced*, when they change.
|
|
// Q: How do you maintain thread safety with such an object?
|
|
// A: Reading a mutable object needs locking. There's no way around it.
|
|
// But picking up a reference to an immutable can be done with almost no
|
|
// overhead using atomic operations.
|
|
// Given the nature of mutable objects, they should only be used within
|
|
// the scope of a single thread (which does not have to be the main thread!)
|
|
// Q: Is it getting any better this way?
|
|
// A: mmmh... at least it offloads the application from doing this kinda stuff.
|
|
// And it ensures separating data from logic.
|
|
// Q: Shouldn't IMutable then be derived from IValue<T> or from ISignal?
|
|
// A: To be considered. Given that IMutable is *not* the value itself, because
|
|
// IValue is immutable by definition, it seems to make more sense to derive
|
|
// it from ISignal. OTOH, it isn't a signal either. Maybe it should really
|
|
// stand for it's own.
|
|
|
|
// Mutable objects may change over time.
|
|
IMyc3Mutable = interface
|
|
{$region 'property access'}
|
|
function GetChanged: IMyc2Signal;
|
|
{$endregion}
|
|
property Changed: IMyc2Signal read GetChanged;
|
|
end;
|
|
|
|
// The Values of typed mutable objects are typed immutables. (And thus should
|
|
// be IValue<T> instead of T, see idea above).
|
|
IMyc3Mutable<T> = interface( IMyc3Mutable )
|
|
{$region 'property access'}
|
|
function GetValue: T;
|
|
{$endregion}
|
|
property Value: T read GetValue;
|
|
end;
|
|
|
|
IMyc3ObjectLink<T: class> = interface
|
|
{$region 'property access'}
|
|
function GetMutable: IMyc3Mutable<T>;
|
|
{$endregion}
|
|
procedure Destroyed;
|
|
property Mutable: IMyc3Mutable<T> read GetMutable;
|
|
end;
|
|
|
|
IMyc3Validatable = interface
|
|
{$region 'property access'}
|
|
function GetInvalidate: IMyc2Signal;
|
|
{$endregion}
|
|
|
|
function Validate: Boolean;
|
|
property Invalidate: IMyc2Signal read GetInvalidate;
|
|
end;
|
|
|
|
IMyc3Validatable<T> = interface( IMyc3Validatable )
|
|
{$region 'property access'}
|
|
function GetValue: T;
|
|
{$endregion}
|
|
property Value: T read GetValue;
|
|
end;
|
|
|
|
TValidatable = record
|
|
class function FromSignal(const Signal: IMyc2Signal): IMyc3Validatable; static;
|
|
end;
|
|
|
|
// This is the generic base interface for futures. Futures are used to initialize
|
|
// and hold immutable data.
|
|
//
|
|
// After the initialization is finished, the future and its value are considered
|
|
// to be immutable, which means statically constant and accessing them is always
|
|
// thread-safe and non-blocking.
|
|
//
|
|
// Reading the data before initialization is finished is not allowed! Other
|
|
// threads have to wait for the initialization signal before accessing the value.
|
|
// This can be done explicitly by waiting or by pipelining other futures.
|
|
IMyc3Future<T> = interface
|
|
|
|
{$region 'property access'}
|
|
function GetInitialized: IMyc2State;
|
|
function GetValue: T;
|
|
{$endregion}
|
|
// Wait until initialization is finished. Being a blocking operation, this is only
|
|
// allowed from the main thread.
|
|
{$message hint 'Sollte nichts zurückgeben, damit es nicht in Conditionals verwendet wird!'}
|
|
function WaitFor: T;
|
|
|
|
// Initialization state. This state is set exactly once in the lifetime of the
|
|
// future. It can be used to pipeline other futures.
|
|
//
|
|
property Initialized: IMyc2State read GetInitialized;
|
|
|
|
// Reading the value is NOT ALLOWED until the initialization is finished,
|
|
// otherwise an exception is raised.
|
|
//
|
|
// Use [WaitFor] to block execution until the value is ready.
|
|
property Value: T read GetValue;
|
|
end;
|
|
|
|
IMyc3Changeable<T> = interface
|
|
{$region 'property access'}
|
|
function GetMutable: IMyc3Mutable<T>;
|
|
{$endregion}
|
|
procedure SetChanged;
|
|
property Mutable: IMyc3Mutable<T> read GetMutable;
|
|
end;
|
|
|
|
IMyc3Generic<T> = interface( IMyc3Changeable<T> )
|
|
{$region 'property access'}
|
|
function GetFunc: TFunc<T>;
|
|
procedure SetFunc(const Value: TFunc<T>);
|
|
{$endregion}
|
|
property Func: TFunc<T> read GetFunc write SetFunc;
|
|
end;
|
|
|
|
IMyc3Writeable<T> = interface( IMyc3Changeable<T> )
|
|
function SetValue(const Value: T): Boolean;
|
|
end;
|
|
|
|
IMyc3ValidateMutable<T> = interface( IMyc3Mutable<T> )
|
|
procedure Validate;
|
|
end;
|
|
|
|
IMyc3Property<T> = interface( IMyc3Mutable<T> )
|
|
procedure Delete; overload;
|
|
procedure Delete( const DefaultValue: T ); overload;
|
|
end;
|
|
|
|
IMyc3MutableProperty<T> = interface( IMyc3Mutable<T> )
|
|
|
|
{$region 'property access'}
|
|
procedure SetMutable( const Value: IMyc3Mutable<T> );
|
|
{$endregion}
|
|
property Mutable: IMyc3Mutable<T> write SetMutable;
|
|
end;
|
|
|
|
IMyc3MutablePropertyEx<T> = interface( IMyc3Mutable<T> )
|
|
procedure Invalidate;
|
|
end;
|
|
|
|
IMyc3Animator = interface
|
|
procedure Tick( const Ticks: Int64 );
|
|
end;
|
|
|
|
IMyc3Animator<T> = interface( IMyc3Animator )
|
|
function GetCurrent: IMyc3Mutable<T>;
|
|
property Current: IMyc3Mutable<T> read GetCurrent;
|
|
end;
|
|
|
|
IMycDeletable = interface
|
|
procedure Delete;
|
|
end;
|
|
|
|
IMycArray<T> = interface( IMyc2Enumerable<T> )
|
|
{$region 'property access'}
|
|
function GetCount: Integer;
|
|
function GetItems( Idx: Integer ): T;
|
|
{$endregion}
|
|
function ToArray: TArray<T>;
|
|
function Sort( const Comparer: IComparer<T> = nil; First: Integer = 0; Count: Integer = -1 ): TArray<Integer>;
|
|
function Divide( const Comparer: IComparer<T> ): TArray<IMycArray<T>>;
|
|
function Divide1( const Comparer: IComparer<T> ): TArray<TArray<Integer>>;
|
|
function Range( First: Integer; Count: Integer ): IMycArray<T>;
|
|
function Rearrange( const Indices: TArray<Integer> ): IMycArray<T>;
|
|
property Count: Integer read GetCount;
|
|
property Items[Idx: Integer]: T read GetItems; default;
|
|
end;
|
|
|
|
IMycChain<T> = interface( IMyc2Enumerable<T> )
|
|
{$region 'property access'}
|
|
function GetChanged: IMyc2Signal;
|
|
{$endregion}
|
|
function AddFirst( const Item: T ): IMycDeletable;
|
|
function AddLast( const Item: T ): IMycDeletable;
|
|
function ToArray: TArray<T>;
|
|
property Changed: IMyc2Signal read GetChanged;
|
|
end;
|
|
|
|
TChain = record
|
|
public
|
|
class function Create<T>: IMycChain<T>; static;
|
|
end;
|
|
|
|
TMycArray = class {helper for TArray}
|
|
public
|
|
class function Create<T>( const Arr: array of T ): IMycArray<T>; overload; static;
|
|
class function Create<T>( Count: Integer; const Getter: TFunc<Integer, T> ): IMycArray<T>; overload; static;
|
|
|
|
class function Create<T>(const Src: IMyc2Enumerable<T>): IMycArray<T>; overload; static;
|
|
|
|
class function Create<S, T>( const Src: IMycArray<S>; const Converter: TConstFunc<S, T> ): IMycArray<T>; overload; static;
|
|
|
|
class procedure Divide1<TKey, TValue>( const Src: IMycArray<TPair<TKey, TValue>>; out Keys: TArray<TKey>; out Values:
|
|
TArray<IMycArray<TValue>>; const Comparer: IComparer<TKey> ); overload; static;
|
|
|
|
class function Divide<TKey, TValue>( const Src: IMycArray<TPair<TKey, TValue>>; const Comparer: IComparer<TKey> ): TArray<TPair<TKey,
|
|
IMycArray<TValue>>>; overload; static;
|
|
|
|
class function Divide<T>( const Src: TArray<T>; const Comparer: IComparer<T> ): TArray<TArray<T>>; overload; static;
|
|
class function Divide<TKey, TValue>( const Src: TArray<TPair<TKey, TValue>>; const Comparer: IComparer<TKey> ): TArray<TPair<TKey,
|
|
TArray<TValue>>>; overload; static;
|
|
|
|
class function GetKeys<TKey, TValue>( const Arr: TArray<TPair<TKey, TValue>> ): TArray<TKey>; static;
|
|
|
|
class function CreateConvert<T, S>( const Enum: IMyc2Enumerable<S>; const Conv: TConstFunc<S, T> ): IMyc2Enumerable<T>;
|
|
end;
|
|
|
|
IMyc3Set<S, T> = interface( IMyc3Mutable<T> )
|
|
function Add( const Item: S ): Integer;
|
|
procedure Remove( const Item: S );
|
|
procedure Delete( Idx: Integer );
|
|
procedure Clear;
|
|
end;
|
|
|
|
IMycEnumerable<T> = interface( IMyc3Mutable<TArray<T>> )
|
|
{$region 'property access'}
|
|
function GetCount: Integer;
|
|
{$endregion}
|
|
function GetEnumerator: IMycEnumerator<T>;
|
|
property Count: Integer read GetCount;
|
|
end;
|
|
|
|
IMycSetItem<T> = interface( IMycDeletable )
|
|
{$region 'property access'}
|
|
function GetValue: T;
|
|
{$endregion}
|
|
property Value: T read GetValue;
|
|
end;
|
|
|
|
IMycSet<T> = interface( IMycEnumerable<T> )
|
|
function Add( const Value: T ): IMycSetItem<T>;
|
|
function Pop: T;
|
|
procedure Clear;
|
|
end;
|
|
|
|
IMycEnumArray<T> = interface( IMycEnumerable<T> )
|
|
{$region 'property access'}
|
|
function GetItems( Idx: Integer ): T;
|
|
{$endregion}
|
|
function Sort( const Comparer: IComparer<T> = nil; First: Integer = 0; Count: Integer = -1 ): IMycArray<T>;
|
|
property Items[Idx: Integer]: T read GetItems; default;
|
|
end;
|
|
|
|
TSet<T> = record
|
|
public
|
|
class function Create: IMycSet<T>; overload; static;
|
|
class function Create( const Arr: IMyc3Mutable<TArray<T>> ): IMycEnumArray<T>; overload; static;
|
|
class function CreateEx( const Arr: TArray<T> ): IMycEnumArray<T>; overload; static;
|
|
end;
|
|
|
|
IMycAssembly<T> = interface( IMycSet<IMyc3Mutable<TArray<T>>> )
|
|
{$region 'property access'}
|
|
function GetItems: IMyc3Mutable<TArray<T>>;
|
|
{$endregion}
|
|
function Add( const Value: T ): IMycDeletable; overload;
|
|
function Add( const Values: array of T ): IMycDeletable; overload;
|
|
property Items: IMyc3Mutable<TArray<T>> read GetItems;
|
|
end deprecated;
|
|
|
|
TAssembly<T> = record
|
|
class function Create: IMycAssembly<T>; static;
|
|
end deprecated;
|
|
|
|
IMycStack<T> = interface
|
|
{$region 'property access'}
|
|
function GetCount: Integer;
|
|
{$endregion}
|
|
procedure Push( const Value: T );
|
|
function Pop: T;
|
|
procedure Clear;
|
|
function ToArray: TArray<T>;
|
|
property Count: Integer read GetCount;
|
|
end;
|
|
|
|
Stack = record
|
|
class function Create<T>: IMycStack<T>; static;
|
|
end;
|
|
|
|
TFunc<U, V, W, X, Y, T> = reference to function( P1: U; P2: V; P3: W; P4: X; P5: Y ): T;
|
|
TFunc<U, V, W, X, Y, Z, T> = reference to function( P1: U; P2: V; P3: W; P4: X; P5: Y; P6: Z ): T;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// TValue
|
|
//
|
|
TValue<T> = class
|
|
type
|
|
TCalculator = reference to procedure( var Value: T );
|
|
|
|
class var
|
|
FDefaultMutable: IMyc3Mutable<T>;
|
|
FDefaultMutableFuture: IMyc3Mutable<IMyc3Future<T>>;
|
|
|
|
class constructor CreateClass;
|
|
class function GetDefaultFuture: IMyc3Future<T>; static;
|
|
|
|
public
|
|
class function AsImmutable( const Value: T ): IMyc3Value<T>; overload; static;
|
|
|
|
class function CreateLazy(const Func: TFunc<T>): IMyc3Value<T>; static;
|
|
|
|
// Create a constant future.
|
|
class function AsFuture( const Value: T ): IMyc3Future<T>; static;
|
|
|
|
// Create a generic future. Its fully up to the calculator to handle
|
|
// synchronization.
|
|
class function CreateFuture( const StartSignal: IMyc2Signal; const Calculator: TFunc<T> ): IMyc3Future<T>;
|
|
overload; static;
|
|
class function CreateFuture( const StartSignal: IMyc2Signal; const Calculator: TFunc < IMyc3Future < T >> )
|
|
: IMyc3Future<T>; overload; static;
|
|
|
|
class function CreateFutureArray( Count: Integer; const Calculator: TFunc<Integer, T> ): IMyc3Future<TArray<T>>; overload; static;
|
|
class function CreateFutureArray( const StartSignal: IMyc2Signal; Count: Integer; const Calculator: TFunc<Integer, T> ):
|
|
IMyc3Future<TArray<T>>; overload; static;
|
|
|
|
class function CreateFutures( Count: Integer; const Src: IMyc3Future < TArray < T >> ): TArray<IMyc3Future<T>>; overload; static;
|
|
|
|
// Create a generic immutable
|
|
class function CreateFuture( const Calculator: TFunc<T> ): IMyc3Future<T>; overload; static;
|
|
|
|
class function Convert<S>( P: IMyc3Future<S>; const Converter: TFunc<S, T> ): IMyc3Future<T>; static;
|
|
|
|
// Create an immutable from one other immutables.
|
|
class function CreateFuture<U>( P: IMyc3Future<U>; Calculator: TFunc<U, T> ): IMyc3Future<T>; overload; static;
|
|
class function CreateFuture<U>( P: IMyc3Future<U>; Calculator: TFunc < U, IMyc3Future < T >> ): IMyc3Future<T>;
|
|
overload; static;
|
|
class function CreateFuture<U, V>( P1: IMyc3Future<U>; P2: IMyc3Future<V>; Calculator: TFunc<U, V, T> ): IMyc3Future<T>;
|
|
overload; static;
|
|
class function CreateFuture<U, V>( P1: IMyc3Future<U>; P2: IMyc3Future<V>; Calculator: TFunc < U, V, IMyc3Future < T >> )
|
|
: IMyc3Future<T>; overload; static;
|
|
class function CreateFuture<U, V, W>( P1: IMyc3Future<U>; P2: IMyc3Future<V>; P3: IMyc3Future<W>;
|
|
Calculator: TFunc<U, V, W, T> ): IMyc3Future<T>; overload; static;
|
|
|
|
// Create an immutable array from an array of immutables.
|
|
class function CreateFuture( const Values: TArray < IMyc3Future < T >> ): IMyc3Future<TArray<T>>; overload; static;
|
|
class function CreateFuture<S>( const Values: TArray<IMyc3Future<S>>; const Calculator: TFunc<Integer, S, T> ): IMyc3Future<TArray<T>>;
|
|
overload; static;
|
|
|
|
// Calculate an immutable from a set of other immutables. This is a convenient
|
|
// function that passes the parameter Values as typed array to the calculator.
|
|
class function CreateFuture<S>( const Params: TArray<IMyc3Future<S>>; Calculator: TFunc<TArray<S>, T> ): IMyc3Future<T>;
|
|
overload; static;
|
|
|
|
// Create a future from the value of another future.
|
|
class function CreateFuture( Future: IMyc3Future<T>; Creator: TFunc<T, IMyc3Future<T>> ): IMyc3Future<T>;
|
|
overload; static;
|
|
|
|
// Execute on future init.
|
|
class function Execute( Future: IMyc3Future<T>; Proc: TConstFunc<T, IMyc2Signal> ): IMyc2State;
|
|
|
|
// Get value, if future is initialized.
|
|
class function TryGetValue( const Future: IMyc3Future<T>; out Value: T ): Boolean; static;
|
|
|
|
// Create a mutable from a constant value. The resulting mutable never changes.
|
|
class function AsConst( const Value: T ): IMyc3Mutable<T>; overload; static; deprecated 'use TMutable<T>()';
|
|
class function CreateMutable( const Value: T ): IMyc3Mutable<T>; overload; static; deprecated 'use TMutable<T>()';
|
|
|
|
class function CreateMutable( Calculator: TFunc<T> ): IMyc3Mutable<T>; overload; static;
|
|
experimental;
|
|
|
|
class function CreateMutable( const Changed: array of IMyc2Signal; const Calculator: TFunc<T> ): IMyc3Mutable<T>; overload; static; deprecated 'use TMutable<T>.FromSignals()';
|
|
class function CreateMutable(const Changed: array of IMyc2Signal; const Calculator: TFunc<IMyc3Mutable<T>>): IMyc3Mutable<T>; overload; static; deprecated 'use TMutable<T>.FromSignals()';
|
|
// Extend a mutable by a set of signals.
|
|
class function CreateMutable( const Changed: array of IMyc2Signal; const Mutable: IMyc3Mutable<T> ): IMyc3Mutable<T>; overload; static;
|
|
class function CreateMutable( const Event: IMycEventObserver; const Calculator: TFunc<T> ): IMyc3Mutable<T>; overload; static;
|
|
// Futures as mutables
|
|
class function AsMutable( const Value: IMyc3Mutable<IMyc3Value<T>> ): IMyc3Mutable<T>; overload; static;
|
|
class function AsMutable( const Value: IMyc3Mutable<IMyc3Mutable<T>> ): IMyc3Mutable<T>; overload; static;
|
|
|
|
class function AsMutable(const Value: IMyc3Future<T>): IMyc3Mutable<T>; overload; static;
|
|
class function AsMutable(const Value: IMyc3Mutable<IMyc3Future<T>>): IMyc3Mutable<T>; overload; static;
|
|
|
|
// Operators
|
|
class function CreateMutable<U>( P: IMyc3Mutable<U>; Calculator: TFunc<U, T> ): IMyc3Mutable<T>; overload; static;
|
|
class function CreateMutable<U, V>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; Calculator: TFunc<U, V, T> )
|
|
: IMyc3Mutable<T>; overload; static;
|
|
class function CreateMutable<U, V, W>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; P3: IMyc3Mutable<W>;
|
|
Calculator: TFunc<U, V, W, T> ): IMyc3Mutable<T>; overload; static;
|
|
class function CreateMutable<U, V, W, X>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; P3: IMyc3Mutable<W>;
|
|
P4: IMyc3Mutable<X>; Calculator: TFunc<U, V, W, X, T> ): IMyc3Mutable<T>; overload; static;
|
|
class function CreateMutable<U, V, W, X, Y>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; P3: IMyc3Mutable<W>; P4: IMyc3Mutable<X>; P5:
|
|
IMyc3Mutable<Y>; Calculator: TFunc<U, V, W, X, Y, T> ): IMyc3Mutable<T>; overload; static;
|
|
class function CreateMutable<U, V, W, X, Y, Z>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; P3: IMyc3Mutable<W>; P4: IMyc3Mutable<X>; P5:
|
|
IMyc3Mutable<Y>; P6: IMyc3Mutable<Z>; Calculator: TFunc<U, V, W, X, Y, Z, T> ): IMyc3Mutable<T>; overload; static;
|
|
|
|
// Mutable arrays
|
|
class function CreateMutable( const Arr: TArray < IMyc3Mutable < T >> ): IMyc3Mutable<TArray<T>>; overload; static; deprecated 'Mutable<T>.CreateArray';
|
|
class function CreateMutable<S>( const Arr: TArray<IMyc3Mutable<S>>; Calculator: TFunc<Integer, S, T> ):
|
|
IMyc3Mutable<TArray<T>>; overload; static;
|
|
class function CreateMutableEx<S>( Params: TArray<IMyc3Mutable<S>>; Calculator: TFunc<TArray<S>, T> ): IMyc3Mutable<T>; overload; static;
|
|
experimental;
|
|
|
|
{$message hint 'Debug-Code! Eigentlich ist das hier das wahre Lazy-Mutable'}
|
|
class function CreateGeneric(const Calculator: TFunc<T> = nil): IMyc3Generic<T>;
|
|
|
|
// Create a mutable, that supports direct changes to it's value.
|
|
class function CreateWriteable: IMyc3Writeable<T>; overload; static;
|
|
class function CreateWriteable( const InitValue: T ): IMyc3Writeable<T>; overload; static;
|
|
class function CreateWriteable( const InitValue: T; const EqualityComparison: TEqualityComparison<T> ): IMyc3Writeable<T>;
|
|
overload; static;
|
|
|
|
class function CreateValidate( const Calculator: TFunc<T> ): IMyc3ValidateMutable<T>; static;
|
|
|
|
class function CreateMutableProperty(const InitValue: IMyc3Mutable<T> = nil): IMyc3MutableProperty<T>; overload; static; experimental;
|
|
|
|
class function CreateProperty( const Creator: TFunc < IMyc3Mutable < T >> ): IMyc3MutablePropertyEx<T>; overload; static;
|
|
experimental;
|
|
|
|
class function CreatePropertyEx( const Decorated: IMyc3Mutable<T> ): IMyc3Property<T>; overload; static;
|
|
|
|
// Combining values
|
|
class function Combine<V>( Values: TArray<V>; Combiner: TMyc3Combiner<T, V> ): IMyc3Future<T>; overload; static;
|
|
class function Combine<V>(const Values: TArray<IMyc3Mutable<V>>; Combiner: TMyc3Combiner<T, V>): IMyc3Mutable<T>; overload; static;
|
|
class function Combine<V>( const Values: TArray<IMyc3Future<V>>; Combiner: TMyc3Combiner<T, V> ): IMyc3Future<T>;
|
|
overload; static;
|
|
class function CreateSet: IMycSet<T>; overload; static;
|
|
|
|
class function WaitFor( Future: IMyc3Future<T> ): T; overload; static;
|
|
class procedure WaitFor( const Futures: TArray<IMyc3Future<T>>; Exec: TProc<Integer, T> ); overload; static;
|
|
|
|
class function Capture( const Src: TArray<T> ): TArray<T>;
|
|
experimental;
|
|
|
|
class function CreateAnimator( const Target: IMyc3Mutable<T>; const Interpolator: TMyc3TargetInterpolator<T> )
|
|
: IMyc3Animator<T>; overload; static;
|
|
class function CreateAnimator( const Init: T; const ChangeSignal: IMyc2Signal; const Interpolator: TMyc3Interpolator<T> )
|
|
: IMyc3Animator<T>; overload; static;
|
|
|
|
class function MakeValid( const Value: IMyc3Future<T> ): IMyc3Future<T>; overload; static; inline;
|
|
class function MakeValid( const Value: IMyc3Mutable<T> ): IMyc3Mutable<T>; overload; static; inline;
|
|
|
|
class property DefaultFuture: IMyc3Future<T> read GetDefaultFuture;
|
|
class property DefaultMutable: IMyc3Mutable<T> read FDefaultMutable;
|
|
class property DefaultMutableFuture: IMyc3Mutable<IMyc3Future<T>> read FDefaultMutableFuture;
|
|
end;
|
|
|
|
TMutableFuture<T> = record
|
|
private
|
|
class var
|
|
FNull: IMyc3Mutable<IMyc3Future<T>>;
|
|
class function GetNull: IMyc3Mutable<IMyc3Future<T>>; static;
|
|
class constructor CreateClass;
|
|
|
|
public
|
|
class function Create<S>( const P: IMyc3Mutable<IMyc3Future<T>>; Calc: TFunc<T, S> ): IMyc3Mutable<IMyc3Future<S>>; static;
|
|
|
|
class property Null: IMyc3Mutable<IMyc3Future<T>> read GetNull;
|
|
end;
|
|
|
|
IMyc3MutableCache<T> = interface( IMyc3Mutable )
|
|
{$region 'property access'}
|
|
function GetCount: Integer;
|
|
{$endregion}
|
|
function Add( const Value: IMyc3Mutable<T> ): IMyc3Mutable<T>;
|
|
procedure Clear;
|
|
procedure Validate;
|
|
function GetEnumerator: IMycEnumerator<IMyc3Mutable<T>>;
|
|
property Count: Integer read GetCount;
|
|
end;
|
|
|
|
IMyc3MutableTable = interface
|
|
procedure Clear;
|
|
end;
|
|
|
|
IMyc3MutableTable<T> = interface( IMyc3MutableTable )
|
|
function Add( const Value: T ): IMyc3Mutable<T>;
|
|
end;
|
|
|
|
TMutableCache<T> = record
|
|
private
|
|
FThis: IMyc3MutableTable<T>;
|
|
|
|
function GetItem(const Value: T): IMyc3Mutable<T>;
|
|
|
|
public
|
|
constructor Create( const AThis: IMyc3MutableTable<T> );
|
|
procedure Clear;
|
|
property Item[const Value: T]: IMyc3Mutable<T> read GetItem; default;
|
|
end;
|
|
|
|
TMutable<T> = record
|
|
private
|
|
FThis: IMyc3Mutable<T>;
|
|
|
|
public
|
|
class function FromSignals(const Changed: array of IMyc2Signal; const Calculator: TFunc<T>): IMyc3Mutable<T>; overload; static;
|
|
class function FromSignals(const Changed: array of IMyc2Signal; const Calculator: TFunc<IMyc3Mutable<T>>): IMyc3Mutable<T>; overload; static;
|
|
|
|
class function From<S>(const Value: IMyc3Mutable<S>; const Conv: TFunc<S, IMyc3Mutable<T>>): TMutable<T>; overload; static;
|
|
|
|
class operator Explicit(const Value: T): TMutable<T>;
|
|
class operator Implicit(const Item: IMyc3Mutable<T>): TMutable<T>;
|
|
class operator Implicit(const Item: TMutable<T>): IMyc3Mutable<T>;
|
|
end;
|
|
|
|
TMutableFuture = record
|
|
|
|
// Arrays
|
|
class function FromArray<T>(const Value: TArray<IMyc3Mutable<IMyc3Future<T>>>): IMyc3Mutable<IMyc3Future<TArray<T>>>; overload; static;
|
|
end;
|
|
|
|
TFuture = record
|
|
class function From<S, T>(const Value: IMyc3Future<S>; const Conv: TFunc<S, T>): IMyc3Future<T>; overload; static;
|
|
class function From<S, T>(const Value: IMyc3Future<S>; const Conv: TFunc<S, IMyc3Future<T>>): IMyc3Future<T>; overload; static;
|
|
|
|
class function FromArray<T>(const Value: TArray<IMyc3Future<T>>): IMyc3Future<TArray<T>>; overload; static;
|
|
|
|
class function Combine<S, T>( const Value: TArray<IMyc3Future<S>>; const Calculator: TFunc<TArray<S>, T> ): IMyc3Future<T>; overload; static;
|
|
|
|
class function Merge<T>(const Parts: TArray<TArray<T>>): TArray<T>; overload; static;
|
|
class function Merge<T>(const Parts: TArray<IMyc3Future<TArray<T>>>): IMyc3Future<TArray<T>>; overload; static;
|
|
end;
|
|
|
|
Mutable = record
|
|
// convert
|
|
class function Convert<S, T>(const Value: IMyc3Mutable<S>; const Conv: TFunc<S, T>): IMyc3Mutable<T>; overload; static;
|
|
class function Convert<S, T>(const Value: IMyc3Mutable<IMyc3Future<S>>; const Conv: TFunc<S, T>): IMyc3Mutable<IMyc3Future<T>>; overload; static;
|
|
class function Convert<S, T>(const Value: IMyc3Mutable<IMyc3Future<S>>; const Conv: TFunc<S, IMyc3Future<T>>): IMyc3Mutable<IMyc3Future<T>>; overload; static;
|
|
|
|
// enclose
|
|
class function From<T>(const Value: T): IMyc3Mutable<T>; overload; static;
|
|
class function From<S, T>(const Value: IMyc3Mutable<S>; const Conv: TFunc<S, IMyc3Mutable<T>>): IMyc3Mutable<T>; overload; static;
|
|
class function From<R, S, T>(const ValueR: IMyc3Mutable<R>; const ValueS: IMyc3Mutable<S>; const Conv: TFunc<R, S, IMyc3Mutable<T>>): IMyc3Mutable<T>; overload; static;
|
|
|
|
// Arrays
|
|
class function FromArray<T>(const Value: TArray<IMyc3Mutable<T>>): IMyc3Mutable<TArray<T>>; overload; static;
|
|
class function FromArray<S, T>(const Value: IMyc3Mutable<TArray<S>>; const Conv: TFunc<S, T>): IMyc3Mutable<TArray<T>>; overload; static;
|
|
class function FromArray<S, T>(const Value: IMyc3Mutable<TArray<S>>; const Conv: TFunc<S, IMyc3Mutable<T>>): IMyc3Mutable<TArray<T>>; overload; static;
|
|
|
|
class function FilterArray<T>(const Values: IMyc3Mutable<TArray<T>>; const FilterFunc: TConstFunc<T, IMyc3Mutable<Boolean>>): IMyc3Mutable<TArray<T>>; static;
|
|
class function SortArray<T>(const Values: IMyc3Mutable<TArray<T>>; const Comparer: IComparer<T>): IMyc3Mutable<TArray<T>>; static;
|
|
class function TrimArray<T: IInterface>(const Values: IMyc3Mutable<TArray<T>>): IMyc3Mutable<TArray<T>>; static;
|
|
|
|
// bool
|
|
class function Create( Value: Boolean ): IMyc3Mutable<Boolean>; overload; static;
|
|
|
|
class function True: IMyc3Mutable<Boolean>; overload; static; deprecated 'use TMutableBool';
|
|
class function False: IMyc3Mutable<Boolean>; overload; static; deprecated 'use TMutableBool';
|
|
|
|
class function OpOR(const Arr: TArray<IMyc3Mutable<Boolean>>): IMyc3Mutable<Boolean>; static; deprecated 'use TMutableBool';
|
|
class function OpAND(const Arr: TArray<IMyc3Mutable<Boolean>>): IMyc3Mutable<Boolean>; static; deprecated 'use TMutableBool';
|
|
class function OpNOR(const Arr: TArray<IMyc3Mutable<Boolean>>): IMyc3Mutable<Boolean>; static; deprecated 'use TMutableBool';
|
|
class function OpNAND(const Arr: TArray<IMyc3Mutable<Boolean>>): IMyc3Mutable<Boolean>; static; deprecated 'use TMutableBool';
|
|
class function OpNOT(const A: IMyc3Mutable<Boolean>): IMyc3Mutable<Boolean>; static; deprecated 'use TMutableBool';
|
|
|
|
class function IfThen<T>(const Condition: IMyc3Mutable<Boolean>; const TrueValue: IMyc3Mutable<T>): IMyc3Mutable<T>; overload; static;
|
|
class function IfThen<T>(const Condition: IMyc3Mutable<Boolean>; const TrueValue: IMyc3Mutable<IMyc3Future<T>>): IMyc3Mutable<IMyc3Future<T>>; overload; static;
|
|
class function IfNotThen<T>(const Condition: IMyc3Mutable<Boolean>; const FalseValue: IMyc3Mutable<T>): IMyc3Mutable<T>; static;
|
|
class function IfThenElse<T>(const Condition: IMyc3Mutable<Boolean>; const TrueValue, FalseValue: IMyc3Mutable<T>): IMyc3Mutable<T>; static;
|
|
|
|
class function CreateOverride<T>(const Value, Ovrride: IMyc3Mutable<TImmutable<T>>): IMyc3Mutable<TImmutable<T>>; overload; static;
|
|
|
|
class function FromSignal(const Signal: IMyc2Signal): IMyc3Mutable<Boolean>; static;
|
|
class function FromState(const State: IMyc2State): IMyc3Mutable<Boolean>; static;
|
|
|
|
class function CreateValidator<T>( const Comparer: IComparer<T> = nil ): IMyc3MutableCache<T>; static;
|
|
class function CreateCache<T>( const Comparer: IComparer<T> = nil ): TMutableCache<T>; static;
|
|
|
|
class function CreateEventObserver<T>(const Mutables: TArray<IMyc3Mutable<T>>): IMycEventObserver; static;
|
|
class function CreateNotifyObserver<T>(const Mutables: TArray<IMyc3Mutable<T>>): IMycNotifyObserver; static;
|
|
|
|
class function ExtractSignals<T>(const Mutables: TArray<IMyc3Mutable<T>>): IMyc2Signal; static;
|
|
|
|
class function CreateAssembly<T>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<T>>>): IMyc3Mutable<TArray<T>>; overload; static;
|
|
class function CreateAssembly<T>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<IMyc3Future<T>>>>): IMyc3Mutable<IMyc3Future<TArray<T>>>; overload; static;
|
|
|
|
class function CreateAssembly<T>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<T>>>; const Creator: TFunc<TArray<T>, T>): IMyc3Mutable<T>; overload; static;
|
|
|
|
class function CreateAssembly<T>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<IMyc3Future<T>>>>; const Creator: TFunc<TArray<T>, T>):
|
|
IMyc3Mutable<IMyc3Future<T>>; overload; static;
|
|
|
|
class function CreateAssembly<T, S>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<T>>>; const Creator: TFunc<TArray<T>, S>): IMyc3Mutable<S>;
|
|
overload; static;
|
|
|
|
class function CreateAssembly<T, S>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<IMyc3Future<T>>>>; const Creator: TFunc<TArray<T>, S>):
|
|
IMyc3Mutable<IMyc3Future<S>>; overload; static;
|
|
|
|
class function ConvertSet<T, S>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<T>>>; const Converter: TFunc<T, S>): IMyc3Mutable<TArray<
|
|
IMyc3Mutable<S>>>; overload; static;
|
|
|
|
class function ConvertSet<T, S>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<IMyc3Future<T>>>>; const Converter: TFunc<T, S>): IMyc3Mutable<
|
|
TArray< IMyc3Mutable<IMyc3Future<S>>>>; overload; static;
|
|
|
|
class function Merge<T>(const Parts: IMyc3Mutable<TArray<TArray<T>>>): IMyc3Mutable<TArray<T>>; overload; static;
|
|
class function Merge<T>(const Parts: IMyc3Mutable<TArray<IMyc3Future<TArray<T>>>>): IMyc3Mutable<IMyc3Future<TArray<T>>>; overload; static;
|
|
|
|
class function CreateObjectLink<T: class>(Obj: T): IMyc3ObjectLink<T>; static;
|
|
|
|
class function CreateNullable<T>: IMyc3Writeable<TImmutable<T>>; static;
|
|
end;
|
|
|
|
TMutableBool = record
|
|
private
|
|
FThis: IMyc3Mutable<Boolean>;
|
|
class function GetDefaults(Value: Boolean): IMyc3Mutable<Boolean>; static; inline;
|
|
|
|
public
|
|
constructor Create(const AThis: IMyc3Mutable<Boolean>);
|
|
|
|
class operator LogicalNot(const Value: TMutableBool): TMutableBool;
|
|
class operator LogicalAnd(const A, B: TMutableBool): TMutableBool;
|
|
class operator LogicalOr(const A, B: TMutableBool): TMutableBool;
|
|
|
|
class operator Equal(const A, B: TMutableBool): TMutableBool;
|
|
class operator NotEqual(const A, B: TMutableBool): TMutableBool;
|
|
|
|
class operator Implicit(const Value: IMyc3Mutable<Boolean>): TMutableBool; inline;
|
|
class operator Implicit(const Value: TMutableBool): IMyc3Mutable<Boolean>; inline;
|
|
|
|
class property Defaults[Value: Boolean]: IMyc3Mutable<Boolean> read GetDefaults;
|
|
|
|
class function True: IMyc3Mutable<Boolean>; static; inline;
|
|
class function False: IMyc3Mutable<Boolean>; static; inline;
|
|
|
|
property This: IMyc3Mutable<Boolean> read FThis;
|
|
end;
|
|
|
|
Mutable<T> = class
|
|
private
|
|
class function GetComparer: IComparer<IMyc3Mutable<T>>; static; inline;
|
|
|
|
public
|
|
class function Default: IMyc3Mutable<T>; static; inline;
|
|
|
|
class function IfThen( const Condition: IMyc3Mutable<Boolean>; const TrueValue: IMyc3Mutable<T> ): IMyc3Mutable<T>; static; deprecated;
|
|
class function IfNotThen( const Condition: IMyc3Mutable<Boolean>; const FalseValue: IMyc3Mutable<T> ): IMyc3Mutable<T>; static; deprecated;
|
|
class function IfThenElse( const Condition: IMyc3Mutable<Boolean>; const TrueValue, FalseValue: IMyc3Mutable<T> ): IMyc3Mutable<T>; static; deprecated;
|
|
|
|
class function CreateArray( const Arr: TArray<IMyc3Mutable<T>> ): IMyc3Mutable<TArray<T>>; overload; static;
|
|
class function CreateArray<S>( const Arr: IMyc3Mutable<TArray<S>>; Calculator: TFunc<S, T> ): IMyc3Mutable<TArray<T>>; overload; static;
|
|
|
|
class property Comparer: IComparer<IMyc3Mutable<T>> read GetComparer;
|
|
end;
|
|
|
|
TMyc2ComputeProperty<T> = record
|
|
private
|
|
FDone: IMyc2State;
|
|
FValue: T;
|
|
|
|
public
|
|
constructor Create( const StartSignal: IMyc2Signal; const Creator: TFunc<T> );
|
|
function Value: T; inline;
|
|
procedure Terminate; inline;
|
|
property Done: IMyc2State read FDone;
|
|
end;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IMyc2TaskFactory
|
|
//
|
|
IMyc2TaskFactory = interface
|
|
{$region 'property access'}
|
|
function GetThreadCount: Integer;
|
|
{$endregion}
|
|
function CreateThread( const Proc: TProc ): IMyc2State;
|
|
function InMainThread: Boolean;
|
|
function InWorkerThread: Boolean;
|
|
function Run( StartCount: Integer; Proc: TProc ): IMyc2Sink;
|
|
procedure Teardown;
|
|
procedure WaitFor( State: IMyc2State );
|
|
property ThreadCount: Integer read GetThreadCount;
|
|
end;
|
|
|
|
TMyc3Tasks = class( TObject )
|
|
private
|
|
FApi: IMyc2TaskFactory;
|
|
FEnabled: Boolean;
|
|
function GetInMainThread: Boolean;
|
|
function GetThreadCount: Integer;
|
|
procedure SetEnabled( const Value: Boolean );
|
|
|
|
procedure Run( const StartSignal: IMyc2Signal; const Proc: TProc ); overload;
|
|
procedure Run( const Proc: TProc ); overload;
|
|
public
|
|
constructor Create( const AApi: IMyc2TaskFactory );
|
|
destructor Destroy; override;
|
|
function CreateThread( const Proc: TProc ): IMyc2State;
|
|
procedure ExpectSignaled( State: IMyc2State; const Msg: String = 'Expected state to be already set' );
|
|
|
|
function LoopUntil( const DoneSignal: IMyc2Signal; const Proc: TFunc<IMyc2State> ): IMyc2State;
|
|
|
|
function ParallelFor(const StartSignal: IMyc2Signal; LowVal, HighVal, Slice: Integer; const Proc: TProc<Integer, Integer>): IMyc2State; overload;
|
|
procedure ParallelFor(LowVal, HighVal, Slice: Integer; const Proc: TProc<Integer, Integer>); overload;
|
|
|
|
function Start( const StartSignal: IMyc2Signal; const Proc: TFunc<IMyc2Signal> ): IMyc2State; overload;
|
|
function Start( const StartSignal: IMyc2Signal; Proc: TProc ): IMyc2State; overload;
|
|
function Start<T1>( const StartSignal: IMyc2Signal; P1: T1; Proc: TProc<T1> ): IMyc2State; overload;
|
|
function Start<T1, T2>( const StartSignal: IMyc2Signal; P1: T1; P2: T2; Proc: TProc<T1, T2> ): IMyc2State; overload;
|
|
function Start( const Proc: TFunc<IMyc2Signal> ): IMyc2State; overload;
|
|
function Start( const Proc: TProc ): IMyc2State; overload;
|
|
|
|
function Enqueue( var Queue: IMyc2State; const Proc: TFunc<IMyc2Signal> ): IMyc2State; overload;
|
|
function Enqueue( var Queue: IMyc2State; const Proc: TProc ): IMyc2State; overload;
|
|
|
|
function Capture<T>( P: T; Proc: TProc<T> ): TProc; overload;
|
|
function Capture<T, R>( P1: T; P2: R; Proc: TProc<T, R> ): TProc; overload;
|
|
function Capture<T, R, U>( P1: T; P2: R; P3: U; Proc: TProc<T, R, U> ): TProc; overload;
|
|
|
|
function Capture<T, R>( P: T; Proc: TFunc<T, R> ): TFunc<R>; overload;
|
|
function Capture<T, U, R>( P: T; Proc: TFunc<T, U, R> ): TFunc<U, R>; overload;
|
|
function Capture<T, U, V, R>( P: T; Proc: TFunc<T, U, V, R> ): TFunc<U, V, R>; overload;
|
|
|
|
procedure WaitFor( const State: IMyc2State );
|
|
|
|
property InMainThread: Boolean read GetInMainThread;
|
|
property ThreadCount: Integer read GetThreadCount;
|
|
|
|
property Enabled: Boolean write SetEnabled;
|
|
end;
|
|
|
|
TTag = record
|
|
strict private
|
|
FManaged: IInterface;
|
|
FOrdinal: Int64;
|
|
{$ifdef DEBUG}
|
|
FTypeInfo: PTypeInfo;
|
|
{$endif}
|
|
|
|
public
|
|
class function From<T>(const Data: T): TTag; static;
|
|
function AsType<T>: T;
|
|
end;
|
|
|
|
// Parameters
|
|
|
|
TParameterValue = record
|
|
strict private
|
|
FMutable: IMyc3Mutable;
|
|
{$ifdef DEBUG}
|
|
FTypeInfo: PTypeInfo;
|
|
procedure CheckType(TI: PTypeInfo);
|
|
{$endif}
|
|
|
|
public
|
|
constructor Create( ATypeInfo: PTypeInfo; const AMutable: IMyc3Mutable ); overload;
|
|
function Get<T>: T;
|
|
class function Create<T>( const Intf: T ): TParameterValue; overload; static;
|
|
class function Create<T>( const Intf: IMyc3Mutable<T> ): TParameterValue; overload; static;
|
|
class function Compare( const A, B: TParameterValue ): Integer; static;
|
|
class function FromArray<T>( const Values: TArray<TParameterValue> ): TArray<IMyc3Mutable<T>>; overload; static;
|
|
class function FromVarRec( const VarRec: TVarRec ): TParameterValue; static;
|
|
constructor Assign( const Src: TParameterValue );
|
|
function AsType<T>: IMyc3Mutable<T>;
|
|
property Mutable: IMyc3Mutable read FMutable;
|
|
end;
|
|
|
|
TFieldID = Integer;
|
|
|
|
TParameterField = record
|
|
private
|
|
FID: TFieldID;
|
|
FValue: TParameterValue;
|
|
|
|
public
|
|
constructor Create( AID: TFieldID; const AValue: TParameterValue ); overload;
|
|
|
|
class function Create<T>( ID: TFieldID; const Intf: T ): TParameterField; overload; static;
|
|
class function Create<T>( ID: TFieldID; const Intf: IMyc3Mutable<T> ): TParameterField; overload; static;
|
|
|
|
property ID: TFieldID read FID;
|
|
property Value: TParameterValue read FValue write FValue;
|
|
end;
|
|
|
|
IMycParameterRecordDefinition = interface
|
|
{$region 'property access'}
|
|
function GetByName(const Caption: String): Integer;
|
|
function GetCount: Integer;
|
|
function GetFields( Idx: Integer ): TFieldID;
|
|
function GetIdx: Integer;
|
|
{$endregion}
|
|
function IndexOf( Field: TFieldID ): Integer;
|
|
property ByName[const Caption: String]: Integer read GetByName;
|
|
property Count: Integer read GetCount;
|
|
property Fields[Idx: Integer]: TFieldID read GetFields;
|
|
property Idx: Integer read GetIdx;
|
|
end;
|
|
|
|
IMyc3ParameterRecord = interface
|
|
{$region 'property access'}
|
|
function GetByName(const Caption: String): TParameterValue;
|
|
function GetDef: IMycParameterRecordDefinition;
|
|
function GetValues(ID: TFieldID): TParameterValue;
|
|
{$endregion}
|
|
function GetEnumerator: TEnumerator<TParameterField>;
|
|
property ByName[const Caption: String]: TParameterValue read GetByName;
|
|
property Def: IMycParameterRecordDefinition read GetDef;
|
|
property Values[ID: TFieldID]: TParameterValue read GetValues; default;
|
|
end;
|
|
|
|
TParameterRecord = record
|
|
private
|
|
FThis: IMyc3ParameterRecord;
|
|
|
|
function GetValues(ID: TFieldID): TParameterValue; inline;
|
|
function GetByName( const Caption: String ): TParameterValue; inline;
|
|
function GetDef: IMycParameterRecordDefinition; inline;
|
|
|
|
public
|
|
constructor Create( const AThis: IMyc3ParameterRecord );
|
|
|
|
function AsType<T>( ID: TFieldID ): IMyc3Mutable<T>; inline;
|
|
function Get<T>(ID: TFieldID): T; inline;
|
|
|
|
class operator Implicit(const Item: IMyc3ParameterRecord): TParameterRecord;
|
|
class operator Implicit(const Item: TParameterRecord): IMyc3ParameterRecord;
|
|
|
|
property Def: IMycParameterRecordDefinition read GetDef;
|
|
|
|
property Values[ID: TFieldID]: TParameterValue read GetValues; default;
|
|
property ByName[const Caption: String]: TParameterValue read GetByName;
|
|
end;
|
|
|
|
IMycParameterSpace = interface
|
|
{$region 'property access'}
|
|
function GetFieldCount: Integer;
|
|
function GetDefaultValues( FieldID: TFieldID ): TParameterValue;
|
|
function GetCaptions( FieldID: TFieldID ): String;
|
|
function GetComparer( FieldID: TFieldID ): IComparer<TParameterValue>;
|
|
function GetByName(const Caption: String): TFieldID;
|
|
{$endregion}
|
|
function AddField( TypInfo: PTypeInfo; const Caption: String; const DefaultValue: IMyc3Mutable; const Comparer: IComparer<TParameterValue> ): TFieldID;
|
|
function CompareValues( FieldID: TFieldID; const A, B: TParameterValue ): Integer;
|
|
function CreateRecord(const Fields: TArray<TParameterField>): IMyc3ParameterRecord;
|
|
function CreateDef(const Fields: TArray<TFieldID>): IMycParameterRecordDefinition;
|
|
property DefaultValues[FieldID: TFieldID]: TParameterValue read GetDefaultValues;
|
|
property Captions[FieldID: TFieldID]: String read GetCaptions;
|
|
property Comparer[FieldID: TFieldID]: IComparer<TParameterValue> read GetComparer;
|
|
property ByName[const Caption: String]: TFieldID read GetByName;
|
|
property FieldCount: Integer read GetFieldCount;
|
|
end;
|
|
|
|
TParameterSpace = record
|
|
private
|
|
FThis: IMycParameterSpace;
|
|
|
|
function GetFieldCount: Integer; inline;
|
|
function GetDefaultValues( FieldID: TFieldID ): TParameterValue; inline;
|
|
function GetCaptions( FieldID: TFieldID ): String; inline;
|
|
function GetComparer( FieldID: TFieldID ): IComparer<TParameterValue>; inline;
|
|
|
|
public
|
|
constructor Create( const AThis: IMycParameterSpace ); overload;
|
|
|
|
class function Create: TParameterSpace; overload; static;
|
|
|
|
{ TODO : ->Factory (mit D11 managed records) }
|
|
function AddField<T>(const Caption: String; const DefaultValue: T; const Comparer: IComparer<T> = nil): TFieldID;
|
|
|
|
function CompareValues( FieldID: TFieldID; const A, B: TParameterValue ): Integer;
|
|
function CreateRecord( const Fields: TArray<TParameterField> ): TParameterRecord;
|
|
function CreateDef(const Fields: TArray<TFieldID>): IMycParameterRecordDefinition;
|
|
|
|
class operator Implicit( const Item: TParameterSpace ): IMycParameterSpace;
|
|
class operator Implicit( const Item: IMycParameterSpace ): TParameterSpace;
|
|
|
|
property FieldCount: Integer read GetFieldCount;
|
|
property DefaultValues[FieldID: TFieldID]: TParameterValue read GetDefaultValues;
|
|
property Captions[FieldID: TFieldID]: String read GetCaptions;
|
|
property Comparer[FieldID: TFieldID]: IComparer<TParameterValue> read GetComparer;
|
|
end;
|
|
|
|
type
|
|
TStackTrace = record
|
|
const
|
|
Len = 64;
|
|
var
|
|
Msg: String;
|
|
StackTrace: array [0..Len-1] of NativeUInt;
|
|
constructor Create(ASkipFrames: Cardinal; const AMsg: String = '');
|
|
function ToText: String;
|
|
end;
|
|
|
|
var
|
|
Tasks: TMyc3Tasks;
|
|
|
|
procedure RaiseInvalidParameter( const Msg: String = '' );
|
|
procedure RaiseNullPointer;
|
|
procedure RaiseInvalidOperation( const Msg: String = '' ); overload;
|
|
procedure RaiseInvalidOperation( const Msg: String; const Args: array of const ); overload;
|
|
|
|
procedure ForEach( Count: Integer; Exec: TProc<Integer> ); overload;
|
|
procedure ForEach( Count1, Count2: Integer; Exec: TProc<Integer, Integer> ); overload;
|
|
procedure ForEach( Count1, Count2, Count3: Integer; Exec: TProc<Integer, Integer, Integer> ); overload;
|
|
procedure ForEach( LowIdx, HighIdx: Integer; Exec: TProc<Integer> ); overload;
|
|
|
|
implementation
|
|
|
|
uses
|
|
System.Classes, System.SyncObjs, System.SysConst, System.Math,
|
|
Myc.Signals, Myc.Tasks, Myc.Values, Myc.Values.Sets, Myc.Values.Validate,
|
|
Myc.Values.Properties, Myc.Values.Bool, Myc.Atomic, Myc.Future.Arrays,
|
|
Myc.Values.Parameter;
|
|
|
|
procedure RaiseInvalidParameter( const Msg: String = '' );
|
|
var
|
|
Str: String;
|
|
begin
|
|
Str := 'Invalid parameter';
|
|
if Msg <> '' then
|
|
Str := Str + ' (' + Msg + ')';
|
|
|
|
raise EMycInvalidParameter.Create( Str );
|
|
end;
|
|
|
|
procedure RaiseNullPointer;
|
|
begin
|
|
RaiseInvalidParameter( 'null pointer' );
|
|
end;
|
|
|
|
procedure RaiseInvalidOperation( const Msg: String ); overload;
|
|
begin
|
|
RaiseInvalidOperation( Msg, [] );
|
|
end;
|
|
|
|
procedure RaiseInvalidOperation( const Msg: String; const Args: array of const ); overload;
|
|
begin
|
|
if Msg = '' then
|
|
raise EMycInvalidOperation.Create( 'Invalid operation' )
|
|
else
|
|
raise EMycInvalidOperation.CreateFmt( 'Invalid operation: ' + Msg, Args )
|
|
end;
|
|
|
|
procedure ForEach( Count: Integer; Exec: TProc<Integer> );
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to Count - 1 do
|
|
Exec( i );
|
|
end;
|
|
|
|
procedure ForEach( Count1, Count2: Integer; Exec: TProc<Integer, Integer> );
|
|
var
|
|
i, j: Integer;
|
|
begin
|
|
for i := 0 to Count1 - 1 do
|
|
for j := 0 to Count2 - 1 do
|
|
Exec( i, j );
|
|
end;
|
|
|
|
procedure ForEach( Count1, Count2, Count3: Integer; Exec: TProc<Integer, Integer, Integer> );
|
|
var
|
|
i, j, k: Integer;
|
|
begin
|
|
for i := 0 to Count1 - 1 do
|
|
for j := 0 to Count2 - 1 do
|
|
for k := 0 to Count3 - 1 do
|
|
Exec( i, j, k );
|
|
end;
|
|
|
|
procedure ForEach( LowIdx, HighIdx: Integer; Exec: TProc<Integer> ); overload;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := LowIdx to HighIdx do
|
|
Exec( i );
|
|
end;
|
|
|
|
{ TMyc3Tasks }
|
|
|
|
constructor TMyc3Tasks.Create( const AApi: IMyc2TaskFactory );
|
|
begin
|
|
inherited Create;
|
|
FApi := AApi;
|
|
FEnabled := True;
|
|
end;
|
|
|
|
destructor TMyc3Tasks.Destroy;
|
|
begin
|
|
FApi.Teardown;
|
|
inherited;
|
|
end;
|
|
|
|
function TMyc3Tasks.Capture<T, R, U>( P1: T; P2: R; P3: U; Proc: TProc<T, R, U> ): TProc;
|
|
begin
|
|
Result :=
|
|
procedure
|
|
begin
|
|
Proc( P1, P2, P3 );
|
|
end;
|
|
end;
|
|
|
|
function TMyc3Tasks.Capture<T, R>( P: T; Proc: TFunc<T, R> ): TFunc<R>;
|
|
begin
|
|
Result :=
|
|
function: R
|
|
begin
|
|
Result := Proc( P );
|
|
end;
|
|
end;
|
|
|
|
function TMyc3Tasks.Capture<T, R>( P1: T; P2: R; Proc: TProc<T, R> ): TProc;
|
|
begin
|
|
Result :=
|
|
procedure
|
|
begin
|
|
Proc( P1, P2 );
|
|
end;
|
|
end;
|
|
|
|
function TMyc3Tasks.Capture<T, U, R>( P: T; Proc: TFunc<T, U, R> ): TFunc<U, R>;
|
|
begin
|
|
Result :=
|
|
function( Q: U ): R
|
|
begin
|
|
Result := Proc( P, Q );
|
|
end;
|
|
end;
|
|
|
|
function TMyc3Tasks.Capture<T, U, V, R>( P: T; Proc: TFunc<T, U, V, R> ): TFunc<U, V, R>;
|
|
begin
|
|
Result :=
|
|
function( Q: U; R: V ): R
|
|
begin
|
|
Result := Proc( P, Q, R );
|
|
end;
|
|
end;
|
|
|
|
function TMyc3Tasks.Capture<T>( P: T; Proc: TProc<T> ): TProc;
|
|
begin
|
|
Result :=
|
|
procedure
|
|
begin
|
|
Proc( P );
|
|
end;
|
|
end;
|
|
|
|
function TMyc3Tasks.CreateThread( const Proc: TProc ): IMyc2State;
|
|
begin
|
|
Result := FApi.CreateThread( Proc );
|
|
end;
|
|
|
|
{ TSet<T> }
|
|
|
|
class function TSet<T>.Create: IMycSet<T>;
|
|
begin
|
|
Result := TMycSet<T>.Create;
|
|
end;
|
|
|
|
class function TSet<T>.CreateEx( const Arr: TArray<T> ): IMycEnumArray<T>;
|
|
begin
|
|
Result := TMycEnumArray<T>.CreateStatic( Arr );
|
|
end;
|
|
|
|
class function TSet<T>.Create( const Arr: IMyc3Mutable<TArray<T>> ): IMycEnumArray<T>;
|
|
begin
|
|
Result := TMycEnumArray<T>.CreateMutable( Arr );
|
|
end;
|
|
|
|
{ TFuture }
|
|
|
|
class function TFuture.From<S, T>(const Value: IMyc3Future<S>; const Conv: TFunc<S, T>): IMyc3Future<T>;
|
|
begin
|
|
Result := TMyc3Future<T>.CreateFuture( Value.Initialized,
|
|
function: T
|
|
begin
|
|
Result := Conv( Value.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TFuture.Combine<S, T>(const Value: TArray<IMyc3Future<S>>;
|
|
const Calculator: TFunc<TArray<S>, T>): IMyc3Future<T>;
|
|
begin
|
|
Result := TValue<T>.CreateFuture<S>( Value, Calculator );
|
|
end;
|
|
|
|
class function TFuture.From<S, T>(const Value: IMyc3Future<S>; const Conv: TFunc<S, IMyc3Future<T>>): IMyc3Future<T>;
|
|
begin
|
|
Result := TMyc3Future<T>.CreateFuture( Value.Initialized,
|
|
function: IMyc3Future<T>
|
|
begin
|
|
Result := Conv( Value.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TFuture.FromArray<T>(const Value: TArray<IMyc3Future<T>>): IMyc3Future<TArray<T>>;
|
|
begin
|
|
Result := TMyc3FutureArrayEx<T>.Create( Value );
|
|
end;
|
|
|
|
class function TFuture.Merge<T>(const Parts: TArray<TArray<T>>): TArray<T>;
|
|
var
|
|
i, j, n: Integer;
|
|
begin
|
|
n := 0;
|
|
for i := 0 to High(Parts) do
|
|
inc( n, Length(Parts[i]) );
|
|
|
|
SetLength( Result, n );
|
|
n := 0;
|
|
for i := 0 to High(Parts) do
|
|
begin
|
|
for j := 0 to High(Parts[i]) do
|
|
begin
|
|
Result[n] := Parts[i,j];
|
|
inc(n);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
class function TFuture.Merge<T>(const Parts: TArray<IMyc3Future<TArray<T>>>): IMyc3Future<TArray<T>>;
|
|
begin
|
|
if Length(Parts) = 0 then
|
|
Result := TValue<TArray<T>>.DefaultFuture
|
|
else if Length(Parts) = 1 then
|
|
Result := Parts[0]
|
|
else
|
|
Result := TValue<TArray<T>>.CreateFuture<TArray<TArray<T>>>(
|
|
TValue<TArray<T>>.CreateFuture( Parts ),
|
|
function( Parts: TArray<TArray<T>> ): TArray<T>
|
|
begin
|
|
Result := Merge<T>( Parts );
|
|
end );
|
|
end;
|
|
|
|
{ TMutableFuture<T> }
|
|
|
|
class constructor TMutableFuture<T>.CreateClass;
|
|
begin
|
|
FNull := TValue<IMyc3Future<T>>.CreateMutable( TValue<T>.DefaultFuture );
|
|
end;
|
|
|
|
class function TMutableFuture<T>.Create<S>( const P: IMyc3Mutable<IMyc3Future<T>>; Calc: TFunc<T, S> ): IMyc3Mutable<IMyc3Future<S>>;
|
|
begin
|
|
Result := TValue<IMyc3Future<S>>.CreateMutable<IMyc3Future<T>>(
|
|
P,
|
|
function( P: IMyc3Future<T> ): IMyc3Future<S>
|
|
begin
|
|
Result := TValue<S>.CreateFuture<T>(
|
|
P,
|
|
function( P: T ): S
|
|
begin
|
|
Result := Calc( P );
|
|
end );
|
|
end );
|
|
end;
|
|
|
|
class function TMutableFuture<T>.GetNull: IMyc3Mutable<IMyc3Future<T>>;
|
|
begin
|
|
Result := FNull;
|
|
end;
|
|
|
|
{ TImmutable<T> }
|
|
|
|
constructor TImmutable<T>.Create(const AValue: T);
|
|
begin
|
|
FThis := TMyc3Value<T>.Create( AValue );
|
|
end;
|
|
|
|
function TImmutable<T>.GetValue: T;
|
|
begin
|
|
if FThis<>nil then
|
|
Result := FThis.Value
|
|
else
|
|
Result := Default(T);
|
|
end;
|
|
|
|
function TImmutable<T>.GetHasValue: Boolean;
|
|
begin
|
|
Result := FThis<>nil;
|
|
end;
|
|
|
|
class function TImmutable<T>.GetNull: TImmutable<T>;
|
|
begin
|
|
Result := Default(TImmutable<T>);
|
|
end;
|
|
|
|
class operator TImmutable<T>.Equal(ALeft, ARight: TImmutable<T>): Boolean;
|
|
begin
|
|
if ALeft.HasValue and ARight.HasValue then
|
|
Result := TEqualityComparer<T>.Default.Equals(ALeft.Value, ARight.Value)
|
|
else
|
|
Result := ALeft.HasValue = ARight.HasValue;
|
|
end;
|
|
|
|
class operator TImmutable<T>.NotEqual(ALeft, ARight: TImmutable<T>): Boolean;
|
|
begin
|
|
if ALeft.HasValue and ARight.HasValue then
|
|
Result := not TEqualityComparer<T>.Default.Equals(ALeft.Value, ARight.Value)
|
|
else
|
|
Result := ALeft.HasValue <> ARight.HasValue;
|
|
end;
|
|
|
|
{ TMyc3Tasks }
|
|
|
|
function TMyc3Tasks.Enqueue( var Queue: IMyc2State; const Proc: TFunc<IMyc2Signal> ): IMyc2State;
|
|
var
|
|
Exec: IMyc2Condition;
|
|
[unsafe]
|
|
Q: IMyc2State;
|
|
begin
|
|
Exec := Signals.CreateCounter( 1 );
|
|
|
|
Result := Exec.State;
|
|
|
|
Result._AddRef;
|
|
Pointer( Q ) := TInterlocked.Exchange( Pointer( Queue ), Pointer( Result ) );
|
|
try
|
|
Start( Q, Proc ).Advise( Exec );
|
|
finally
|
|
Q._Release;
|
|
end;
|
|
end;
|
|
|
|
function TMyc3Tasks.Enqueue( var Queue: IMyc2State; const Proc: TProc ): IMyc2State;
|
|
var
|
|
Exec: IMyc2Condition;
|
|
[unsafe]
|
|
Q: IMyc2State;
|
|
begin
|
|
Exec := Signals.CreateCounter( 1 );
|
|
|
|
Result := Exec.State;
|
|
|
|
Result._AddRef;
|
|
Pointer( Q ) := TInterlocked.Exchange( Pointer( Queue ), Pointer( Result ) );
|
|
try
|
|
Start( Q, Proc ).Advise( Exec );
|
|
finally
|
|
Q._Release;
|
|
end;
|
|
end;
|
|
|
|
procedure TMyc3Tasks.ExpectSignaled( State: IMyc2State; const Msg: String = 'Expected state to be already set' );
|
|
begin
|
|
System.Assert( Signals.IsStatic( State ) or State.IsSet, Msg );
|
|
end;
|
|
|
|
function TMyc3Tasks.GetInMainThread: Boolean;
|
|
begin
|
|
Result := FApi.InMainThread;
|
|
end;
|
|
|
|
function TMyc3Tasks.GetThreadCount: Integer;
|
|
begin
|
|
Result := FApi.ThreadCount;
|
|
end;
|
|
|
|
function TMyc3Tasks.LoopUntil( const DoneSignal: IMyc2Signal; const Proc: TFunc<IMyc2State> ): IMyc2State;
|
|
var
|
|
Done: IMyc2Event;
|
|
CapturedProc: TFunc<IMyc2State>;
|
|
begin
|
|
if Signals.IsStatic( DoneSignal ) then
|
|
exit( Signals.Null.State );
|
|
|
|
DoneSignal._AddRef;
|
|
try
|
|
Done := Signals.CreateEvent( false );
|
|
DoneSignal.Advise( Done );
|
|
|
|
CapturedProc := Proc;
|
|
|
|
Result := FApi.CreateThread(
|
|
procedure
|
|
begin
|
|
try
|
|
while not Done.State.IsSet do
|
|
WaitFor( CapturedProc );
|
|
finally
|
|
CapturedProc := nil;
|
|
end;
|
|
end );
|
|
finally
|
|
DoneSignal._Release;
|
|
end;
|
|
end;
|
|
|
|
function TMyc3Tasks.ParallelFor(const StartSignal: IMyc2Signal; LowVal, HighVal, Slice: Integer; const Proc: TProc<Integer, Integer>):
|
|
IMyc2State;
|
|
|
|
function CallFunc( f, l: Integer; Proc: TProc<Integer, Integer> ): IMyc2State;
|
|
begin
|
|
Result := Start(
|
|
StartSignal,
|
|
procedure
|
|
begin
|
|
Proc( f, l );
|
|
end );
|
|
end;
|
|
|
|
var
|
|
l, f, n: Integer;
|
|
Counter: IMyc2Condition;
|
|
begin
|
|
if not Assigned( Proc ) or ( LowVal > HighVal ) then
|
|
exit;
|
|
|
|
if Slice <= 0 then
|
|
Slice := max( 1, (HighVal-LowVal+1) div ThreadCount );
|
|
|
|
n := 0;
|
|
f := LowVal;
|
|
while f <= HighVal do
|
|
begin
|
|
inc( f, Slice );
|
|
inc( n );
|
|
end;
|
|
|
|
if n=0 then
|
|
exit;
|
|
|
|
Counter := Signals.CreateCounter( n );
|
|
|
|
f := LowVal;
|
|
while f <= HighVal do
|
|
begin
|
|
l := f + Slice - 1;
|
|
if l > HighVal then
|
|
l := HighVal;
|
|
|
|
CallFunc( f, l, Proc ).Advise( Counter );
|
|
|
|
f := l + 1;
|
|
end;
|
|
|
|
Result := Counter.State;
|
|
end;
|
|
|
|
procedure TMyc3Tasks.ParallelFor(LowVal, HighVal, Slice: Integer; const Proc: TProc<Integer, Integer>);
|
|
begin
|
|
if Slice <= 0 then
|
|
Slice := max( 1, (HighVal-LowVal+1) div ThreadCount );
|
|
|
|
if HighVal - LowVal >= Slice then
|
|
WaitFor( ParallelFor( nil, LowVal, HighVal, Slice, Proc ) )
|
|
else
|
|
Proc( LowVal, HighVal );
|
|
end;
|
|
|
|
procedure TMyc3Tasks.Run( const StartSignal: IMyc2Signal; const Proc: TProc );
|
|
begin
|
|
if not Signals.IsStatic( StartSignal ) then
|
|
begin
|
|
if FEnabled then
|
|
StartSignal.Advise( FApi.Run( 1, Proc ) )
|
|
else
|
|
StartSignal.Advise( Signals.CreateSink( True, Proc ) );
|
|
end
|
|
else
|
|
Run( Proc );
|
|
end;
|
|
|
|
procedure TMyc3Tasks.Run( const Proc: TProc );
|
|
begin
|
|
if FEnabled then
|
|
FApi.Run( 0, Proc )
|
|
else
|
|
Proc( );
|
|
end;
|
|
|
|
procedure TMyc3Tasks.SetEnabled( const Value: Boolean );
|
|
begin
|
|
{$ifndef DisableThreading}
|
|
FEnabled := Value;
|
|
{$endif}
|
|
end;
|
|
|
|
function TMyc3Tasks.Start( const StartSignal: IMyc2Signal; const Proc: TFunc<IMyc2Signal> ): IMyc2State;
|
|
var
|
|
Done: IMyc2Condition;
|
|
CapturedProc: TFunc<IMyc2Signal>;
|
|
begin
|
|
if not Assigned( Proc ) then
|
|
exit( Signals.Null.State );
|
|
|
|
Done := Signals.CreateCounter( 1 );
|
|
|
|
CapturedProc := Proc;
|
|
|
|
Run( StartSignal,
|
|
procedure
|
|
var
|
|
Sig: IMyc2Signal;
|
|
begin
|
|
try
|
|
Sig := CapturedProc( );
|
|
finally
|
|
CapturedProc := nil;
|
|
|
|
if not Signals.IsStatic( Sig ) then
|
|
Sig.Advise( Done )
|
|
else
|
|
Done.Notify;
|
|
end;
|
|
end );
|
|
|
|
exit( Done.State );
|
|
end;
|
|
|
|
function TMyc3Tasks.Start( const StartSignal: IMyc2Signal; Proc: TProc ): IMyc2State;
|
|
var
|
|
Done: IMyc2Condition;
|
|
begin
|
|
Assert( Assigned( Proc ) );
|
|
Done := Signals.CreateCounter( 1 );
|
|
|
|
Run( StartSignal,
|
|
procedure
|
|
begin
|
|
try
|
|
Proc;
|
|
finally
|
|
Done.Notify;
|
|
end;
|
|
end );
|
|
|
|
exit( Done.State );
|
|
end;
|
|
|
|
function TMyc3Tasks.Start( const Proc: TFunc<IMyc2Signal> ): IMyc2State;
|
|
begin
|
|
Result := Start( nil, Proc );
|
|
end;
|
|
|
|
function TMyc3Tasks.Start( const Proc: TProc ): IMyc2State;
|
|
begin
|
|
Result := Start( nil, Proc );
|
|
end;
|
|
|
|
function TMyc3Tasks.Start<T1, T2>( const StartSignal: IMyc2Signal; P1: T1; P2: T2; Proc: TProc<T1, T2> ): IMyc2State;
|
|
begin
|
|
Result := Start( StartSignal,
|
|
procedure
|
|
begin
|
|
Proc( P1, P2 );
|
|
end );
|
|
end;
|
|
|
|
function TMyc3Tasks.Start<T1>( const StartSignal: IMyc2Signal; P1: T1; Proc: TProc<T1> ): IMyc2State;
|
|
begin
|
|
Result := Start( StartSignal,
|
|
procedure
|
|
begin
|
|
Proc( P1 );
|
|
end );
|
|
end;
|
|
|
|
procedure TMyc3Tasks.WaitFor( const State: IMyc2State );
|
|
begin
|
|
FApi.WaitFor( State );
|
|
end;
|
|
|
|
{ TValue<T> }
|
|
|
|
class constructor TValue<T>.CreateClass;
|
|
begin
|
|
FDefaultMutable := TMyc3ConstantMutable<T>.Create( Default(T) );
|
|
FDefaultMutableFuture := TMyc3ConstantMutable<IMyc3Future<T>>.Create( TMyc3ConstantFuture<T>.Create( Default(T) ) );
|
|
end;
|
|
|
|
class function TValue<T>.Capture( const Src: TArray<T> ): TArray<T>;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
SetLength( Result, Length( Src ) );
|
|
for i := 0 to High( Src ) do
|
|
Result[i] := Src[i];
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture( Future: IMyc3Future<T>; Creator: TFunc < T, IMyc3Future < T >> ): IMyc3Future<T>;
|
|
begin
|
|
Result := TMyc3Future<T>.CreateFuture( Future.Initialized,
|
|
function: IMyc3Future<T>
|
|
begin
|
|
Result := Creator( Future.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture( const StartSignal: IMyc2Signal; const Calculator: TFunc < IMyc3Future < T >> )
|
|
: IMyc3Future<T>;
|
|
begin
|
|
Result := TMyc3Future<T>.CreateFuture( StartSignal,
|
|
function: IMyc3Future<T>
|
|
begin
|
|
Result := Calculator( );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.Combine<V>( const Values: TArray<IMyc3Future<V>>; Combiner: TMyc3Combiner<T, V> ): IMyc3Future<T>;
|
|
begin
|
|
if Values=nil then
|
|
exit( DefaultFuture );
|
|
|
|
Result := CreateFuture<V>( Values,
|
|
function( Arr: TArray<V> ): T
|
|
begin
|
|
Result := Combiner( Arr );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.Combine<V>( Values: TArray<V>; Combiner: TMyc3Combiner<T, V> ): IMyc3Future<T>;
|
|
begin
|
|
if Values=nil then
|
|
exit( DefaultFuture );
|
|
|
|
Result := TValue<T>.CreateFuture(
|
|
function: T
|
|
begin
|
|
Result := Combiner( Values );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.Combine<V>(const Values: TArray<IMyc3Mutable<V>>; Combiner: TMyc3Combiner<T, V>): IMyc3Mutable<T>;
|
|
var
|
|
Chg: TArray<IMyc2Signal>;
|
|
i: Integer;
|
|
begin
|
|
Result := Mutable.Convert<TArray<V>, T>(
|
|
TValue<V>.CreateMutable(Values),
|
|
function( Values: TArray<V> ): T
|
|
begin
|
|
if not Assigned( Combiner ) then
|
|
exit( Default( T ) );
|
|
Result := Combiner( Values );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateAnimator( const Target: IMyc3Mutable<T>; const Interpolator: TMyc3TargetInterpolator<T> )
|
|
: IMyc3Animator<T>;
|
|
begin
|
|
Result := CreateAnimator( Target.Value, Target.Changed,
|
|
function( Delta: Double; const StartValue: T; out Value: T ): Boolean
|
|
begin
|
|
Result := Interpolator( Delta, StartValue, Target.Value, Value );
|
|
if not Result then
|
|
Value := Target.Value;
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateAnimator( const Init: T; const ChangeSignal: IMyc2Signal;
|
|
const Interpolator: TMyc3Interpolator<T> ): IMyc3Animator<T>;
|
|
begin
|
|
Result := TMyc3Animator<T>.Create( Init, ChangeSignal, Interpolator );
|
|
end;
|
|
|
|
class function TValue<T>.AsFuture( const Value: T ): IMyc3Future<T>;
|
|
begin
|
|
Result := TMyc3ConstantFuture<T>.Create( Value );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture( const StartSignal: IMyc2Signal; const Calculator: TFunc<T> ): IMyc3Future<T>;
|
|
begin
|
|
Result := TMyc3Future<T>.CreateFuture( StartSignal, Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture( const Calculator: TFunc<T> ): IMyc3Future<T>;
|
|
begin
|
|
Result := TMyc3Future<T>.CreateFuture( Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture<S>( const Params: TArray<IMyc3Future<S>>; Calculator: TFunc<TArray<S>, T> ): IMyc3Future<T>;
|
|
var
|
|
Counter: IMyc2Condition;
|
|
i: Integer;
|
|
Arr: TArray<IMyc3Future<S>>;
|
|
begin
|
|
Counter := Signals.CreateCounter( Length( Params ) );
|
|
SetLength( Arr, Length( Params ) );
|
|
|
|
for i := 0 to High( Params ) do
|
|
begin
|
|
if Params[i]<>nil then
|
|
begin
|
|
Arr[i] := Params[i];
|
|
Arr[i].Initialized.Advise( Counter );
|
|
end
|
|
else
|
|
Counter.Notify;
|
|
end;
|
|
|
|
Result := TMyc3Future<T>.CreateFuture( Counter.State,
|
|
function: T
|
|
var
|
|
Values: TArray<S>;
|
|
i: Integer;
|
|
begin
|
|
SetLength( Values, Length( Arr ) );
|
|
for i := 0 to High( Values ) do
|
|
if Arr[i]<>nil then
|
|
Values[i] := Arr[i].Value;
|
|
|
|
Result := Calculator( Values );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture<U, V>( P1: IMyc3Future<U>; P2: IMyc3Future<V>; Calculator: TFunc<U, V, T> ): IMyc3Future<T>;
|
|
var
|
|
Counter: IMyc2Condition;
|
|
begin
|
|
Assert( Assigned( P1 ) and Assigned( P2 ) );
|
|
Counter := Signals.CreateCounter( 2 );
|
|
|
|
P1.Initialized.Advise( Counter );
|
|
P2.Initialized.Advise( Counter );
|
|
|
|
Result := CreateFuture( Counter.State,
|
|
function: T
|
|
begin
|
|
Result := Calculator( P1.Value, P2.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture<U, V>( P1: IMyc3Future<U>; P2: IMyc3Future<V>; Calculator: TFunc < U, V, IMyc3Future < T >>
|
|
): IMyc3Future<T>;
|
|
var
|
|
Counter: IMyc2Condition;
|
|
begin
|
|
Assert( Assigned( P1 ) and Assigned( P2 ) );
|
|
Counter := Signals.CreateCounter( 2 );
|
|
|
|
P1.Initialized.Advise( Counter );
|
|
P2.Initialized.Advise( Counter );
|
|
|
|
Result := CreateFuture( Counter.State,
|
|
function: IMyc3Future<T>
|
|
begin
|
|
Result := Calculator( P1.Value, P2.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture<U>( P: IMyc3Future<U>; Calculator: TFunc<U, T> ): IMyc3Future<T>;
|
|
begin
|
|
Assert( Assigned( P ) );
|
|
Result := CreateFuture( P.Initialized,
|
|
function: T
|
|
begin
|
|
Result := Calculator( P.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture<U>( P: IMyc3Future<U>; Calculator: TFunc < U, IMyc3Future < T >> ): IMyc3Future<T>;
|
|
begin
|
|
Assert( Assigned( P ) );
|
|
Result := CreateFuture( P.Initialized,
|
|
function: IMyc3Future<T>
|
|
begin
|
|
Result := Calculator( P.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.AsImmutable( const Value: T ): IMyc3Value<T>;
|
|
begin
|
|
Result := TMyc3Value<T>.Create( Value );
|
|
end;
|
|
|
|
class function TValue<T>.CreateLazy(const Func: TFunc<T>): IMyc3Value<T>;
|
|
begin
|
|
Result := TMyc3Lazy<T>.Create( Func );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture( const Values: TArray < IMyc3Future < T >> ): IMyc3Future<TArray<T>>;
|
|
begin
|
|
Result := TMyc3FutureArrayEx<T>.Create( Values );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture<S>( const Values: TArray<IMyc3Future<S>>; const Calculator: TFunc<Integer, S, T> ):
|
|
IMyc3Future<TArray<T>>;
|
|
begin
|
|
Result := TMyc3FutureArrayConvert<T, S>.Create( Values, Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFuture<U, V, W>( P1: IMyc3Future<U>; P2: IMyc3Future<V>; P3: IMyc3Future<W>;
|
|
Calculator: TFunc<U, V, W, T> ): IMyc3Future<T>;
|
|
var
|
|
Counter: IMyc2Condition;
|
|
begin
|
|
Assert( Assigned( P1 ) and Assigned( P2 ) and Assigned( P3 ) );
|
|
Counter := Signals.CreateCounter( 3 );
|
|
|
|
P1.Initialized.Advise( Counter );
|
|
P2.Initialized.Advise( Counter );
|
|
P3.Initialized.Advise( Counter );
|
|
|
|
Result := CreateFuture( Counter.State,
|
|
function: T
|
|
begin
|
|
Result := Calculator( P1.Value, P2.Value, P3.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFutures( Count: Integer; const Src: IMyc3Future < TArray < T >> ): TArray<IMyc3Future<T>>;
|
|
begin
|
|
Result := TMyc3FutureArray<T>.CreateFutures( Count, Src );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable( const Value: T ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := AsConst( Value );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable( const Changed: array of IMyc2Signal; const Calculator: TFunc<T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable( Changed, Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.AsMutable( const Value: IMyc3Mutable<IMyc3Mutable<T>> ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3EnclosedMutable<T>.Create( Value );
|
|
end;
|
|
|
|
class function TValue<T>.AsMutable( const Value: IMyc3Mutable<IMyc3Value<T>> ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TValue<T>.CreateMutable<IMyc3Value<T>>(
|
|
Value,
|
|
function( Immutable: IMyc3Value<T> ): T
|
|
begin
|
|
if Immutable<>nil then
|
|
Result := Immutable.Value
|
|
else
|
|
Result := default ( T );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.AsConst( const Value: T ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3ConstantMutable<T>.Create( Value );
|
|
end;
|
|
|
|
class function TValue<T>.AsMutable(const Value: IMyc3Future<T>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3FutureAsMutable<T>.CreateFutureAsMutable( Value )
|
|
end;
|
|
|
|
class function TValue<T>.AsMutable(const Value: IMyc3Mutable<IMyc3Future<T>>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3EnclosedMutable<T>.Create(
|
|
TMyc3Mutable<IMyc3Mutable<T>>.CreateMutable(
|
|
Value.Changed,
|
|
function: IMyc3Mutable<T>
|
|
begin
|
|
Result := AsMutable( Value.Value );
|
|
end ) );
|
|
end;
|
|
|
|
class function TValue<T>.Convert<S>( P: IMyc3Future<S>; const Converter: TFunc<S, T> ): IMyc3Future<T>;
|
|
begin
|
|
if P.Initialized.IsSet then
|
|
Result := AsFuture( Converter( P.Value ) )
|
|
else
|
|
Result := CreateFuture<S>( P, Converter );
|
|
end;
|
|
|
|
class function TValue<T>.CreateGeneric(const Calculator: TFunc<T>): IMyc3Generic<T>;
|
|
begin
|
|
Result := TMyc3Changeable<T>.CreateGeneric( Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFutureArray( const StartSignal: IMyc2Signal; Count: Integer; const Calculator: TFunc<Integer, T> ):
|
|
IMyc3Future<TArray<T>>;
|
|
var
|
|
Init: IMyc2State;
|
|
Arr: TArray<T>;
|
|
Calc: TFunc<Integer, T>;
|
|
begin
|
|
SetLength( Arr, Count );
|
|
|
|
Calc := Calculator;
|
|
Init := Tasks.ParallelFor(
|
|
StartSignal,
|
|
0, Count-1, 1,
|
|
procedure( A, B: Integer )
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := A to B do
|
|
Calc( i )
|
|
end );
|
|
|
|
Result := TMyc3Future<TArray<T>>.CreateFuture( Init, Arr );
|
|
end;
|
|
|
|
class function TValue<T>.CreateFutureArray( Count: Integer; const Calculator: TFunc<Integer, T> ): IMyc3Future<TArray<T>>;
|
|
begin
|
|
Result := CreateFutureArray( Signals.Null.State, Count, Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateValidate( const Calculator: TFunc<T> ): IMyc3ValidateMutable<T>;
|
|
begin
|
|
Result := TMyc3ValidateMutable<T>.Create( Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable( const Arr: TArray < IMyc3Mutable < T >> ): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateArray( Arr );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable( Calculator: TFunc<T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := CreateMutable( [], Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable( const Event: IMycEventObserver; const Calculator: TFunc<T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable( Event, Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable( const Changed: array of IMyc2Signal; const Mutable: IMyc3Mutable<T> ): IMyc3Mutable<T>;
|
|
var
|
|
Notifier: IMyc2Notifier;
|
|
i: Integer;
|
|
begin
|
|
Notifier := Signals.CreateNotifier;
|
|
Mutable.Changed.Advise( Notifier );
|
|
for i := 0 to High( Changed ) do
|
|
Changed[i].Advise( Notifier );
|
|
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
Notifier.Signal,
|
|
function: T
|
|
begin
|
|
Result := Mutable.Value;
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable(const Changed: array of IMyc2Signal; const Calculator: TFunc<IMyc3Mutable<T>>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3EnclosedMutable<T>.Create( TMyc3Mutable<IMyc3Mutable<T>>.CreateMutable( Changed, Calculator ) );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable<U, V, W>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; P3: IMyc3Mutable<W>;
|
|
Calculator: TFunc<U, V, W, T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( P1 ) and Assigned( P2 ) and Assigned( P3 ) );
|
|
|
|
if not Signals.IsStatic(P1.Changed) or not Signals.IsStatic(P2.Changed) or not Signals.IsStatic(P3.Changed) then
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[P1.Changed, P2.Changed, P3.Changed],
|
|
function: T
|
|
begin
|
|
Result := Calculator( P1.Value, P2.Value, P3.Value );
|
|
end );
|
|
end
|
|
else
|
|
Result := TMyc3ConstantMutable<T>.Create( Calculator( P1.Value, P2.Value, P3.Value ) );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable<U, V, W, X>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; P3: IMyc3Mutable<W>;
|
|
P4: IMyc3Mutable<X>; Calculator: TFunc<U, V, W, X, T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( P1 ) and Assigned( P2 ) and Assigned( P3 ) and Assigned( P4 ) );
|
|
|
|
if not Signals.IsStatic(P1.Changed) or not Signals.IsStatic(P2.Changed) or not Signals.IsStatic(P3.Changed) or not Signals.IsStatic(P4.Changed) then
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[P1.Changed, P2.Changed, P3.Changed, P4.Changed],
|
|
function: T
|
|
begin
|
|
Result := Calculator( P1.Value, P2.Value, P3.Value, P4.Value );
|
|
end );
|
|
end
|
|
else
|
|
Result := TMyc3ConstantMutable<T>.Create( Calculator( P1.Value, P2.Value, P3.Value, P4.Value ) );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutableEx<S>( Params: TArray<IMyc3Mutable<S>>; Calculator: TFunc<TArray<S>, T> ): IMyc3Mutable<T>;
|
|
var
|
|
i: Integer;
|
|
Sigs: TArray<IMyc2Signal>;
|
|
begin
|
|
case Length( Params ) of
|
|
0:
|
|
Result := CreateMutable(
|
|
function: T
|
|
begin
|
|
Result := Calculator( [] );
|
|
end );
|
|
1:
|
|
Result := CreateMutable<S>( Params[0],
|
|
function( P: S ): T
|
|
begin
|
|
Result := Calculator( [P] );
|
|
end );
|
|
2:
|
|
Result := CreateMutable<S, S>( Params[0], Params[1],
|
|
function( P1, P2: S ): T
|
|
begin
|
|
Result := Calculator( [P1, P2] );
|
|
end );
|
|
3:
|
|
Result := CreateMutable<S, S, S>( Params[0], Params[1], Params[2],
|
|
function( P1, P2, P3: S ): T
|
|
begin
|
|
Result := Calculator( [P1, P2, P3] );
|
|
end );
|
|
4:
|
|
Result := CreateMutable<S, S, S, S>( Params[0], Params[1], Params[2], Params[3],
|
|
function( P1, P2, P3, P4: S ): T
|
|
begin
|
|
Result := Calculator( [P1, P2, P3, P4] );
|
|
end );
|
|
else
|
|
begin
|
|
SetLength( Sigs, Length( Params ) );
|
|
|
|
for i := 0 to High( Sigs ) do
|
|
begin
|
|
Assert( Assigned( Params[i] ) );
|
|
Sigs[i] := Params[i].Changed;
|
|
end;
|
|
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
Sigs,
|
|
function: T
|
|
var
|
|
Values: TArray<S>;
|
|
Init: IMyc2Signal;
|
|
i: Integer;
|
|
begin
|
|
SetLength( Values, Length( Params ) );
|
|
for i := 0 to High( Values ) do
|
|
Values[i] := Params[i].Value;
|
|
|
|
Result := Calculator( Values );
|
|
end );
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable<S>( const Arr: TArray<IMyc3Mutable<S>>; Calculator: TFunc<Integer, S, T> ):
|
|
IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result := TMyc3MutableArray<T, S>.Create( Arr, Calculator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable<U, V, W, X, Y, Z>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; P3: IMyc3Mutable<W>; P4:
|
|
IMyc3Mutable<X>; P5: IMyc3Mutable<Y>; P6: IMyc3Mutable<Z>; Calculator: TFunc<U, V, W, X, Y, Z, T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( P1 ) and Assigned( P2 ) and Assigned( P3 ) and Assigned( P4 ) and Assigned( P5 ) and Assigned( P6 ) );
|
|
|
|
if not Signals.IsStatic(P1.Changed) or not Signals.IsStatic(P2.Changed) or not Signals.IsStatic(P3.Changed)
|
|
or not Signals.IsStatic(P4.Changed) or not Signals.IsStatic(P5.Changed) or not Signals.IsStatic(P6.Changed) then
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[P1.Changed, P2.Changed, P3.Changed, P4.Changed, P5.Changed, P6.Changed],
|
|
function: T
|
|
begin
|
|
Result := Calculator( P1.Value, P2.Value, P3.Value, P4.Value, P5.Value, P6.Value );
|
|
end );
|
|
end
|
|
else
|
|
Result := TMyc3ConstantMutable<T>.Create( Calculator( P1.Value, P2.Value, P3.Value, P4.Value, P5.Value, P6.Value ) );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable<U, V, W, X, Y>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; P3: IMyc3Mutable<W>; P4: IMyc3Mutable<X>;
|
|
P5: IMyc3Mutable<Y>; Calculator: TFunc<U, V, W, X, Y, T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( P1 ) and Assigned( P2 ) and Assigned( P3 ) and Assigned( P4 ) and Assigned( P5 ) );
|
|
|
|
if not Signals.IsStatic(P1.Changed) or not Signals.IsStatic(P2.Changed) or not Signals.IsStatic(P3.Changed)
|
|
or not Signals.IsStatic(P4.Changed) or not Signals.IsStatic(P5.Changed) then
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[P1.Changed, P2.Changed, P3.Changed, P4.Changed, P5.Changed],
|
|
function: T
|
|
begin
|
|
Result := Calculator( P1.Value, P2.Value, P3.Value, P4.Value, P5.Value );
|
|
end );
|
|
end
|
|
else
|
|
Result := TMyc3ConstantMutable<T>.Create( Calculator( P1.Value, P2.Value, P3.Value, P4.Value, P5.Value ) );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable<U, V>( P1: IMyc3Mutable<U>; P2: IMyc3Mutable<V>; Calculator: TFunc<U, V, T> )
|
|
: IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( P1 ) and Assigned( P1 ) );
|
|
|
|
if not Signals.IsStatic(P1.Changed) or not Signals.IsStatic(P2.Changed) then
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[P1.Changed, P2.Changed],
|
|
function: T
|
|
begin
|
|
Result := Calculator( P1.Value, P2.Value );
|
|
end );
|
|
end
|
|
else
|
|
Result := TMyc3ConstantMutable<T>.Create( Calculator( P1.Value, P2.Value ) );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutable<U>( P: IMyc3Mutable<U>; Calculator: TFunc<U, T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( P ) );
|
|
|
|
if not Signals.IsStatic(P.Changed) then
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
P.Changed,
|
|
function: T
|
|
begin
|
|
Result := Calculator( P.Value );
|
|
end );
|
|
end
|
|
else
|
|
Result := TMyc3ConstantMutable<T>.Create( Calculator( P.Value ) );
|
|
end;
|
|
|
|
class function TValue<T>.CreateWriteable( const InitValue: T ): IMyc3Writeable<T>;
|
|
begin
|
|
Result := TMyc3Writeable<T>.CreateWriteable( InitValue );
|
|
end;
|
|
|
|
class function TValue<T>.CreatePropertyEx( const Decorated: IMyc3Mutable<T> ): IMyc3Property<T>;
|
|
begin
|
|
Result := TMycProperty<T>.CreateProperty( Decorated );
|
|
end;
|
|
|
|
class function TValue<T>.CreateProperty( const Creator: TFunc < IMyc3Mutable < T >> ): IMyc3MutablePropertyEx<T>;
|
|
begin
|
|
Result := TMyc3MutablePropertyEx<T>.Create( Creator );
|
|
end;
|
|
|
|
class function TValue<T>.CreateMutableProperty(const InitValue: IMyc3Mutable<T>): IMyc3MutableProperty<T>;
|
|
begin
|
|
Result := TMyc3MutableProperty<T>.Create( InitValue );
|
|
end;
|
|
|
|
class function TValue<T>.CreateSet: IMycSet<T>;
|
|
begin
|
|
Result := TMycSet<T>.Create;
|
|
end;
|
|
|
|
class function TValue<T>.CreateWriteable( const InitValue: T; const EqualityComparison: TEqualityComparison<T> )
|
|
: IMyc3Writeable<T>;
|
|
begin
|
|
Result := TMyc3Writeable<T>.CreateWriteable( InitValue, EqualityComparison );
|
|
end;
|
|
|
|
class function TValue<T>.CreateWriteable: IMyc3Writeable<T>;
|
|
begin
|
|
Result := CreateWriteable( Default(T) );
|
|
end;
|
|
|
|
class function TValue<T>.Execute( Future: IMyc3Future<T>; Proc: TConstFunc<T, IMyc2Signal> ): IMyc2State;
|
|
begin
|
|
Result := Tasks.Start( Future.Initialized,
|
|
function: IMyc2Signal
|
|
begin
|
|
Result := Proc( Future.Value );
|
|
end );
|
|
end;
|
|
|
|
class function TValue<T>.GetDefaultFuture: IMyc3Future<T>;
|
|
begin
|
|
Result := TMyc3Future<T>.DefaultFuture;
|
|
end;
|
|
|
|
class function TValue<T>.MakeValid( const Value: IMyc3Future<T> ): IMyc3Future<T>;
|
|
begin
|
|
Result := Value;
|
|
if Result = nil then
|
|
Result := DefaultFuture;
|
|
end;
|
|
|
|
class function TValue<T>.MakeValid( const Value: IMyc3Mutable<T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := Value;
|
|
if Result = nil then
|
|
Result := DefaultMutable;
|
|
end;
|
|
|
|
class function TValue<T>.TryGetValue( const Future: IMyc3Future<T>; out Value: T ): Boolean;
|
|
begin
|
|
Result := Future <> nil;
|
|
if Result then
|
|
begin
|
|
Result := Future.Initialized = Signals.Null.State;
|
|
if Result then
|
|
begin
|
|
Result := Future.Initialized.IsSet;
|
|
if Result then
|
|
Value := Future.Value;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
class function TValue<T>.WaitFor( Future: IMyc3Future<T> ): T;
|
|
begin
|
|
Tasks.WaitFor( Future.Initialized );
|
|
exit( Future.Value );
|
|
end;
|
|
|
|
class procedure TValue<T>.WaitFor( const Futures: TArray<IMyc3Future<T>>; Exec: TProc<Integer, T> );
|
|
var
|
|
i: Integer;
|
|
Arr: TArray<IMyc3Future<T>>;
|
|
begin
|
|
SetLength( Arr, Length( Futures ) );
|
|
for i := 0 to High( Futures ) do
|
|
if Futures[i].Initialized.IsSet then
|
|
Exec( i, Futures[i].Value )
|
|
else
|
|
Arr[i] := Futures[i];
|
|
|
|
for i := 0 to High( Arr ) do
|
|
if Arr[i] <> nil then
|
|
Exec( i, WaitFor( Futures[i] ) );
|
|
end;
|
|
|
|
{ TMyc2ComputeProperty<T> }
|
|
|
|
constructor TMyc2ComputeProperty<T>.Create( const StartSignal: IMyc2Signal; const Creator: TFunc<T> );
|
|
var
|
|
P: ^T;
|
|
begin
|
|
FValue := default ( T );
|
|
P := @FValue;
|
|
FDone := Tasks.Start( StartSignal,
|
|
procedure
|
|
begin
|
|
P^ := Creator( );
|
|
end );
|
|
end;
|
|
|
|
procedure TMyc2ComputeProperty<T>.Terminate;
|
|
begin
|
|
if FDone <> Signals.Null.State then
|
|
begin
|
|
Tasks.WaitFor( FDone );
|
|
FDone := Signals.Null.State;
|
|
end;
|
|
end;
|
|
|
|
function TMyc2ComputeProperty<T>.Value: T;
|
|
begin
|
|
Terminate;
|
|
Result := FValue;
|
|
end;
|
|
|
|
{ Signals }
|
|
|
|
class function Signals.CreateCounter( Count: Integer ): IMyc2Condition;
|
|
begin
|
|
Result := TMyc2Signal.CreateCounter( Count )
|
|
end;
|
|
|
|
class function Signals.CreateEvent( Init: Boolean = false ): IMyc2Event;
|
|
begin
|
|
Result := TMyc2Signal.CreateEvent( Init );
|
|
end;
|
|
|
|
class function Signals.CreateNotifier: IMyc2Notifier;
|
|
begin
|
|
Result := TMyc2Signal.CreateNotifier;
|
|
end;
|
|
|
|
class function Signals.CreateSink(Once: Boolean; const Proc: TProc): IMyc2Sink;
|
|
begin
|
|
Result := TMyc2SinkProc.CreateSink( Once, Proc );
|
|
end;
|
|
|
|
class function Signals.Concat( const States: array of IMyc2State ): IMyc2State;
|
|
begin
|
|
Result := TMyc2Signal.CreateConcat( States );
|
|
end;
|
|
|
|
class function Signals.CreateObserver<T>( const Signals: array of IMyc2Signal; const Sink: T ): IMycObserver<T>;
|
|
begin
|
|
Result := TMycObserver<T>.CreateObserver( Signals, Sink );
|
|
end;
|
|
|
|
class function Signals.CreateEventObserver( const Signals: array of IMyc2Signal ): IMycEventObserver;
|
|
begin
|
|
Result := CreateObserver<IMyc2Event>( Signals, CreateEvent( True ) );
|
|
end;
|
|
|
|
class function Signals.CreateNotifyObserver( const Signals: array of IMyc2Signal ): IMycNotifyObserver;
|
|
begin
|
|
Result := CreateObserver<IMyc2Notifier>( Signals, CreateNotifier );
|
|
end;
|
|
|
|
class function Signals.CreateNotifyObserver( const Signals: IMycCountable<IMyc2Signal> ): IMycNotifyObserver;
|
|
var
|
|
Arr: TArray<IMyc2Signal>;
|
|
i: Integer;
|
|
begin
|
|
SetLength( Arr, Signals.Count );
|
|
for i := 0 to High( Arr ) do
|
|
Arr[i] := Signals[i];
|
|
|
|
Result := CreateNotifyObserver( Arr );
|
|
end;
|
|
|
|
class function Signals.CreateEventObserver( const Signals: IMycCountable<IMyc2Signal> ): IMycEventObserver;
|
|
var
|
|
Arr: TArray<IMyc2Signal>;
|
|
i: Integer;
|
|
begin
|
|
SetLength( Arr, Signals.Count );
|
|
for i := 0 to High( Arr ) do
|
|
Arr[i] := Signals[i];
|
|
|
|
Result := CreateEventObserver( Arr );
|
|
end;
|
|
|
|
class function Signals.CreateFlag(Init: Boolean): IMyc2Flag;
|
|
begin
|
|
Result := TMyc2Flag.Create( Init );
|
|
end;
|
|
|
|
class function Signals.CreateSink(const Proc: TProc): IMyc2Sink;
|
|
begin
|
|
Result := TMyc2SinkProc.CreateSink( false, Proc );
|
|
end;
|
|
|
|
class function Signals.GetNull: IMyc2Condition;
|
|
begin
|
|
exit( TMyc2Signal.Null );
|
|
end;
|
|
|
|
class function Signals.IsStatic( const Signal: IMyc2Signal ): Boolean;
|
|
begin
|
|
Result := ( Signal = nil ) or ( Signal = Null.State );
|
|
end;
|
|
|
|
class function Signals.MakeValid( const Signal: IMyc2Signal ): IMyc2Signal;
|
|
begin
|
|
if IsStatic( Signal ) then
|
|
exit( Null.State )
|
|
else
|
|
exit( Signal );
|
|
end;
|
|
|
|
class function Signals.MakeValid( const Signals: array of IMyc2Signal ): TArray<IMyc2Signal>;
|
|
begin
|
|
Result := TMyc2Signal.MakeValid( Signals );
|
|
end;
|
|
|
|
class function Signals.Union( const Sigs: array of IMyc2Signal ): IMyc2Signal;
|
|
begin
|
|
Result := TMyc2Signal.CreateUnion( Sigs );
|
|
end;
|
|
|
|
{ TState }
|
|
|
|
class function TAtomicStack<T>.Create: IAtomicStack<T>;
|
|
begin
|
|
Result := TMycAtomicStack<T>.Create;
|
|
end;
|
|
|
|
{ TProtected<T> }
|
|
|
|
constructor TProtected<T>.Create( const AItem: T );
|
|
begin
|
|
FItem := AItem;
|
|
end;
|
|
|
|
function TProtected<T>.Exchange( const Value: T ): T;
|
|
begin
|
|
if Value <> nil then
|
|
Value._AddRef;
|
|
|
|
PPointer( @Result )^ := TInterlocked.Exchange( PPointer( @FItem )^, PPointer( @Value )^ );
|
|
end;
|
|
|
|
class operator TProtected<T>.Implicit( const Value: T ): TProtected<T>;
|
|
begin
|
|
Result.Create( Value );
|
|
end;
|
|
|
|
{ Mutable }
|
|
|
|
class function Mutable.ConvertSet<T, S>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<T>>>; const Converter: TFunc<T, S>): IMyc3Mutable<
|
|
TArray< IMyc3Mutable<S>>>;
|
|
begin
|
|
Result := TValue<TArray<IMyc3Mutable<S>>>.CreateMutable<TArray<IMyc3Mutable<T>>>(
|
|
Arr,
|
|
function( Arr: TArray<IMyc3Mutable<T>> ): TArray<IMyc3Mutable<S>>
|
|
var
|
|
i: Integer;
|
|
begin
|
|
SetLength( Result, Length(Arr) );
|
|
for i := 0 to High(Result) do
|
|
begin
|
|
Assert( Arr[i] <> nil );
|
|
Result[i] := TValue<S>.CreateMutable<T>( Arr[i], Converter );
|
|
end;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.ConvertSet<T, S>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<IMyc3Future<T>>>>; const Converter: TFunc<T, S>):
|
|
IMyc3Mutable<TArray< IMyc3Mutable<IMyc3Future<S>>>>;
|
|
begin
|
|
Result := ConvertSet<IMyc3Future<T>, IMyc3Future<S>>(
|
|
Arr,
|
|
function( Item: IMyc3Future<T> ): IMyc3Future<S>
|
|
begin
|
|
Assert( Item <> nil );
|
|
Result := TValue<S>.CreateFuture<T>( Item, Converter );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.Create( Value: Boolean ): IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TMycMutableBoolean.CreateBoolean( Value );
|
|
end;
|
|
|
|
class function Mutable.CreateAssembly<T>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<T>>>): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result :=
|
|
Mutable.From<TArray<IMyc3Mutable<T>>, TArray<T>>(
|
|
Arr,
|
|
function( Arr: TArray<IMyc3Mutable<T>> ): IMyc3Mutable<TArray<T>>
|
|
begin
|
|
Result := TValue<T>.CreateMutable( Arr );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.CreateAssembly<T>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<IMyc3Future<T>>>>): IMyc3Mutable<IMyc3Future<TArray<T>>>;
|
|
begin
|
|
Result :=
|
|
Mutable.From<TArray<IMyc3Mutable<IMyc3Future<T>>>, IMyc3Future<TArray<T>>>(
|
|
Arr,
|
|
function( Arr: TArray<IMyc3Mutable<IMyc3Future<T>>> ): IMyc3Mutable<IMyc3Future<TArray<T>>>
|
|
begin
|
|
Result := TMutableFuture.FromArray<T>( Arr );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.CreateAssembly<T>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<T>>>; const Creator: TFunc<TArray<T>, T>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TValue<T>.AsMutable(
|
|
TValue<IMyc3Mutable<T>>.CreateMutable<TArray<IMyc3Mutable<T>>>(
|
|
Arr,
|
|
function( Arr: TArray<IMyc3Mutable<T>> ): IMyc3Mutable<T>
|
|
begin
|
|
Result := TValue<T>.CreateMutable<TArray<T>>( TValue<T>.CreateMutable( Arr ), Creator ) ;
|
|
end ) );
|
|
end;
|
|
|
|
class function Mutable.CreateAssembly<T, S>(
|
|
const Arr: IMyc3Mutable<TArray<IMyc3Mutable<IMyc3Future<T>>>>;
|
|
const Creator: TFunc<TArray<T>, S>): IMyc3Mutable<IMyc3Future<S>>;
|
|
begin
|
|
Result := CreateAssembly<IMyc3Future<T>, IMyc3Future<S>>( Arr,
|
|
function( Arr: TArray<IMyc3Future<T>> ): IMyc3Future<S>
|
|
begin
|
|
Result := TValue<S>.CreateFuture<TArray<T>>( TValue<T>.CreateFuture( Arr ), Creator );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.CreateAssembly<T, S>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<T>>>; const Creator: TFunc<TArray<T>, S>):
|
|
IMyc3Mutable<S>;
|
|
begin
|
|
Result := TValue<S>.AsMutable(
|
|
TValue<IMyc3Mutable<S>>.CreateMutable<TArray<IMyc3Mutable<T>>>(
|
|
Arr,
|
|
function( Arr: TArray<IMyc3Mutable<T>> ): IMyc3Mutable<S>
|
|
begin
|
|
Result := TValue<S>.CreateMutable<TArray<T>>( TValue<T>.CreateMutable( Arr ), Creator ) ;
|
|
end ) );
|
|
end;
|
|
|
|
class function Mutable.CreateAssembly<T>(const Arr: IMyc3Mutable<TArray<IMyc3Mutable<IMyc3Future<T>>>>; const Creator: TFunc<TArray<T>, T>)
|
|
: IMyc3Mutable<IMyc3Future<T>>;
|
|
begin
|
|
Result := CreateAssembly<IMyc3Future<T>>( Arr,
|
|
function( Arr: TArray<IMyc3Future<T>> ): IMyc3Future<T>
|
|
begin
|
|
Result := TValue<T>.CreateFuture<TArray<T>>( TValue<T>.CreateFuture( Arr ), Creator );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.FromSignal(const Signal: IMyc2Signal): IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TMycMutableSignal.Create( Signal );
|
|
end;
|
|
|
|
class function Mutable.CreateOverride<T>(const Value, Ovrride: IMyc3Mutable<TImmutable<T>>): IMyc3Mutable<TImmutable<T>>;
|
|
begin
|
|
Result := TValue<TImmutable<T>>.CreateMutable<TImmutable<T>, TImmutable<T>>(
|
|
Value, Ovrride,
|
|
function( Value, Ovrride: TImmutable<T> ): TImmutable<T>
|
|
begin
|
|
if not Ovrride.HasValue then
|
|
Result := Value
|
|
else
|
|
Result := Ovrride;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.CreateCache<T>( const Comparer: IComparer<T> = nil ): TMutableCache<T>;
|
|
begin
|
|
Result.Create( TMycMutableTable<T>.Create( Comparer ) );
|
|
end;
|
|
|
|
class function Mutable.CreateNotifyObserver<T>(const Mutables: TArray<IMyc3Mutable<T>>): IMycNotifyObserver;
|
|
var
|
|
Sigs: TArray<IMyc2Signal>;
|
|
i: Integer;
|
|
begin
|
|
SetLength( Sigs, Length(Mutables) );
|
|
for i := 0 to High(Sigs) do
|
|
Sigs[i] := Mutables[i].Changed;
|
|
Result := Signals.CreateNotifyObserver(Sigs);
|
|
end;
|
|
|
|
class function Mutable.CreateEventObserver<T>(const Mutables: TArray<IMyc3Mutable<T>>): IMycEventObserver;
|
|
var
|
|
Sigs: TArray<IMyc2Signal>;
|
|
i: Integer;
|
|
begin
|
|
SetLength( Sigs, Length(Mutables) );
|
|
for i := 0 to High(Sigs) do
|
|
Sigs[i] := Mutables[i].Changed;
|
|
Result := Signals.CreateEventObserver(Sigs);
|
|
end;
|
|
|
|
class function Mutable.CreateValidator<T>( const Comparer: IComparer<T> = nil ): IMyc3MutableCache<T>;
|
|
begin
|
|
Result := TMycMutableCache<T>.CreateCache( Comparer );
|
|
end;
|
|
|
|
class function Mutable.ExtractSignals<T>(const Mutables: TArray<IMyc3Mutable<T>>): IMyc2Signal;
|
|
var
|
|
i: Integer;
|
|
Arr: TArray<IMyc2Signal>;
|
|
begin
|
|
SetLength( Arr, Length(Mutables) );
|
|
for i := 0 to High(Arr) do
|
|
Arr[i] := Mutables[i].Changed;
|
|
Result := Signals.Union( Arr );
|
|
end;
|
|
|
|
class function Mutable.False: IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TMycMutableBoolean.CreateBoolean( System.False );
|
|
end;
|
|
|
|
class function Mutable.From<S, T>(const Value: IMyc3Mutable<S>; const Conv: TFunc<S, IMyc3Mutable<T>>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3EnclosedMutable<T>.Create(
|
|
TValue<IMyc3Mutable<T>>.CreateMutable<S>( Value, Conv ) );
|
|
end;
|
|
|
|
class function Mutable.Convert<S, T>(const Value: IMyc3Mutable<S>; const Conv: TFunc<S, T>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TValue<T>.CreateMutable<S>( Value, Conv );
|
|
end;
|
|
|
|
class function Mutable.Convert<S, T>(const Value: IMyc3Mutable<IMyc3Future<S>>; const Conv: TFunc<S, T>): IMyc3Mutable<IMyc3Future<T>>;
|
|
begin
|
|
Result := Convert<IMyc3Future<S>, IMyc3Future<T>>(
|
|
Value,
|
|
function( Value: IMyc3Future<S> ): IMyc3Future<T>
|
|
begin
|
|
Result := TFuture.From<S, T>( Value, Conv )
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.Convert<S, T>(const Value: IMyc3Mutable<IMyc3Future<S>>; const Conv: TFunc<S, IMyc3Future<T>>): IMyc3Mutable<IMyc3Future<T>>;
|
|
begin
|
|
Result := Convert<IMyc3Future<S>, IMyc3Future<T>>(
|
|
Value,
|
|
function( Value: IMyc3Future<S> ): IMyc3Future<T>
|
|
begin
|
|
Result := TFuture.From<S, T>( Value, Conv )
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.CreateNullable<T>: IMyc3Writeable<TImmutable<T>>;
|
|
begin
|
|
Result := TValue<TImmutable<T>>.CreateWriteable( TImmutable<T>.Null );
|
|
end;
|
|
|
|
class function Mutable.CreateObjectLink<T>(Obj: T): IMyc3ObjectLink<T>;
|
|
begin
|
|
Result := TMyc3ObjectLink<T>.Create( Obj );
|
|
end;
|
|
|
|
class function Mutable.TrimArray<T>(const Values: IMyc3Mutable<TArray<T>>): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result := TValue<TArray<T>>.CreateMutable<TArray<T>>(
|
|
Values,
|
|
function( Values: TArray<T> ): TArray<T>
|
|
var
|
|
i, n: Integer;
|
|
begin
|
|
n := 0;
|
|
for i := 0 to High(Values) do
|
|
if Assigned(Values[i]) then
|
|
inc(n);
|
|
|
|
SetLength( Result, n );
|
|
n := 0;
|
|
for i := 0 to High(Values) do
|
|
begin
|
|
Result[n] := Values[i];
|
|
inc(n);
|
|
end;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.FilterArray<T>(const Values: IMyc3Mutable<TArray<T>>; const FilterFunc: TConstFunc<T, IMyc3Mutable<Boolean>>): IMyc3Mutable<TArray<T>>;
|
|
var
|
|
Sieve: IMyc3Mutable<TArray<IMyc3Mutable<Boolean>>>;
|
|
begin
|
|
Sieve := TValue<TArray<IMyc3Mutable<Boolean>>>.CreateMutable<TArray<T>>(
|
|
Values,
|
|
function( Values: TArray<T> ): TArray<IMyc3Mutable<Boolean>>
|
|
var
|
|
i: Integer;
|
|
begin
|
|
SetLength( Result, Length( Values ) );
|
|
for i := 0 to High(Values) do
|
|
Result[i] := FilterFunc( Values[i] );
|
|
end );
|
|
|
|
Result := TValue<TArray<T>>.CreateMutable<TArray<Boolean>, TArray<T>>(
|
|
Mutable.CreateAssembly<Boolean>( Sieve ),
|
|
Values,
|
|
function( Sieve: TArray<Boolean>; GeoArr: TArray<T> ): TArray<T>
|
|
var
|
|
i, n: Integer;
|
|
begin
|
|
n := 0;
|
|
for i := 0 to High(GeoArr) do
|
|
if Sieve[i] then
|
|
inc( n );
|
|
SetLength( Result, n );
|
|
n := 0;
|
|
for i := 0 to High(GeoArr) do
|
|
if Sieve[i] then
|
|
begin
|
|
Result[n] := GeoArr[i];
|
|
inc(n);
|
|
end;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.From<R, S, T>(const ValueR: IMyc3Mutable<R>; const ValueS: IMyc3Mutable<S>; const Conv: TFunc<R, S, IMyc3Mutable<T>>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3EnclosedMutable<T>.Create(
|
|
TValue<IMyc3Mutable<T>>.CreateMutable<R, S>( ValueR, ValueS, Conv ) );
|
|
end;
|
|
|
|
class function Mutable.From<T>(const Value: T): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3ConstantMutable<T>.Create( Value );
|
|
end;
|
|
|
|
class function Mutable.FromArray<S, T>(const Value: IMyc3Mutable<TArray<S>>; const Conv: TFunc<S, T>): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result :=
|
|
Convert<TArray<S>, TArray<T>>( Value,
|
|
function( Arr: TArray<S> ): TArray<T>
|
|
var
|
|
i: Integer;
|
|
begin
|
|
SetLength( Result, Length(Arr) );
|
|
for i := 0 to High(Arr) do
|
|
Result[i] := Conv( Arr[i] );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.FromArray<S, T>(const Value: IMyc3Mutable<TArray<S>>; const Conv: TFunc<S, IMyc3Mutable<T>>): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result := CreateAssembly<T>( FromArray<S, IMyc3Mutable<T>>( Value, Conv ) );
|
|
end;
|
|
|
|
class function Mutable.FromArray<T>(const Value: TArray<IMyc3Mutable<T>>): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result := TMyc3MutableArray<T, T>.Create(
|
|
Value,
|
|
function( Idx: Integer; Val: T ): T
|
|
begin
|
|
Result := Val;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.FromState(const State: IMyc2State): IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TMycMutableState.Create( State );
|
|
end;
|
|
|
|
class function Mutable.IfNotThen<T>(const Condition: IMyc3Mutable<Boolean>; const FalseValue: IMyc3Mutable<T>): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( Condition ) and Assigned( FalseValue ) );
|
|
|
|
if Signals.IsStatic(Condition.Changed) then
|
|
begin
|
|
if Condition.Value then
|
|
exit( TValue<T>.DefaultMutable )
|
|
else
|
|
exit( FalseValue );
|
|
end;
|
|
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[Condition.Changed, FalseValue.Changed],
|
|
function: T
|
|
begin
|
|
if Condition.Value then
|
|
Result := System.Default( T )
|
|
else
|
|
Result := FalseValue.Value;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.IfThen<T>(const Condition: IMyc3Mutable<Boolean>; const TrueValue: IMyc3Mutable<T>): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( Condition ) and Assigned( TrueValue ) );
|
|
|
|
if Signals.IsStatic(Condition.Changed) then
|
|
begin
|
|
if Condition.Value then
|
|
exit( TrueValue )
|
|
else
|
|
exit( TValue<T>.DefaultMutable );
|
|
end;
|
|
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[Condition.Changed, TrueValue.Changed],
|
|
function: T
|
|
begin
|
|
if Condition.Value then
|
|
Result := TrueValue.Value
|
|
else
|
|
Result := System.Default( T );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.IfThen<T>(const Condition: IMyc3Mutable<Boolean>; const TrueValue: IMyc3Mutable<IMyc3Future<T>>): IMyc3Mutable<
|
|
IMyc3Future<T>>;
|
|
begin
|
|
Result := IfThenElse<IMyc3Future<T>>( Condition, TrueValue, TValue<T>.DefaultMutableFuture );
|
|
end;
|
|
|
|
class function Mutable.IfThenElse<T>(const Condition: IMyc3Mutable<Boolean>; const TrueValue, FalseValue: IMyc3Mutable<T>): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( Condition ) and Assigned( TrueValue ) and Assigned( FalseValue ) );
|
|
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[Condition.Changed, TrueValue.Changed, FalseValue.Changed],
|
|
function: T
|
|
begin
|
|
if Condition.Value then
|
|
Result := TrueValue.Value
|
|
else
|
|
Result := FalseValue.Value;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.Merge<T>(const Parts: IMyc3Mutable<TArray<TArray<T>>>): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result := TValue<TArray<T>>.CreateMutable<TArray<TArray<T>>>(
|
|
Parts,
|
|
function( Parts: TArray<TArray<T>> ): TArray<T>
|
|
begin
|
|
Result := TFuture.Merge<T>( Parts );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.Merge<T>(const Parts: IMyc3Mutable<TArray<IMyc3Future<TArray<T>>>>): IMyc3Mutable<IMyc3Future<TArray<T>>>;
|
|
begin
|
|
Result := TValue<IMyc3Future<TArray<T>>>.CreateMutable<TArray<IMyc3Future<TArray<T>>>>(
|
|
Parts,
|
|
function( Parts: TArray<IMyc3Future<TArray<T>>> ): IMyc3Future<TArray<T>>
|
|
begin
|
|
Result := TFuture.Merge<T>( Parts );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.OpAND(const Arr: TArray<IMyc3Mutable<Boolean>>): IMyc3Mutable<Boolean>;
|
|
begin
|
|
if Length(Arr)=2 then
|
|
Result := TValue<Boolean>.CreateMutable<Boolean, Boolean>(
|
|
Arr[0], Arr[1],
|
|
function( A, B: Boolean ): Boolean
|
|
begin
|
|
Result := A and B;
|
|
end )
|
|
else if Length(Arr)=1 then
|
|
Result := Arr[0]
|
|
else
|
|
Result := TValue<Boolean>.CreateMutable<TArray<Boolean>>(
|
|
TValue<Boolean>.CreateMutable(Arr),
|
|
function( Arr: TArray<Boolean> ): Boolean
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to High(Arr) do
|
|
if not Arr[i] then
|
|
exit( System.False );
|
|
exit( System.true );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.OpNOT(const A: IMyc3Mutable<Boolean>): IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TValue<Boolean>.CreateMutable<Boolean>(
|
|
A,
|
|
function( A: Boolean ): Boolean
|
|
begin
|
|
Result := not A;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.OpNOR(const Arr: TArray<IMyc3Mutable<Boolean>>): IMyc3Mutable<Boolean>;
|
|
begin
|
|
if Length(Arr)=2 then
|
|
Result := TValue<Boolean>.CreateMutable<Boolean, Boolean>(
|
|
Arr[0], Arr[1],
|
|
function( A, B: Boolean ): Boolean
|
|
begin
|
|
Result := not (A or B);
|
|
end )
|
|
else if Length(Arr)=1 then
|
|
Result := OpNOT( Arr[0] )
|
|
else
|
|
Result := TValue<Boolean>.CreateMutable<TArray<Boolean>>(
|
|
TValue<Boolean>.CreateMutable(Arr),
|
|
function( Arr: TArray<Boolean> ): Boolean
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to High(Arr) do
|
|
if not Arr[i] then
|
|
exit( System.true );
|
|
exit( System.False );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.OpNAND(const Arr: TArray<IMyc3Mutable<Boolean>>): IMyc3Mutable<Boolean>;
|
|
begin
|
|
if Length(Arr)=2 then
|
|
Result := TValue<Boolean>.CreateMutable<Boolean, Boolean>(
|
|
Arr[0], Arr[1],
|
|
function( A, B: Boolean ): Boolean
|
|
begin
|
|
Result := not (A and B);
|
|
end )
|
|
else if Length(Arr)=1 then
|
|
Result := OpNOT( Arr[0] )
|
|
else
|
|
Result := TValue<Boolean>.CreateMutable<TArray<Boolean>>(
|
|
TValue<Boolean>.CreateMutable(Arr),
|
|
function( Arr: TArray<Boolean> ): Boolean
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to High(Arr) do
|
|
if not Arr[i] then
|
|
exit( System.true );
|
|
exit( System.False );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.OpOR(const Arr: TArray<IMyc3Mutable<Boolean>>): IMyc3Mutable<Boolean>;
|
|
begin
|
|
if Length(Arr)=2 then
|
|
Result := TValue<Boolean>.CreateMutable<Boolean, Boolean>(
|
|
Arr[0], Arr[1],
|
|
function( A, B: Boolean ): Boolean
|
|
begin
|
|
Result := A or B;
|
|
end )
|
|
else if Length(Arr)=1 then
|
|
Result := Arr[0]
|
|
else
|
|
Result := TValue<Boolean>.CreateMutable<TArray<Boolean>>(
|
|
TValue<Boolean>.CreateMutable(Arr),
|
|
function( Arr: TArray<Boolean> ): Boolean
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to High(Arr) do
|
|
if Arr[i] then
|
|
exit( System.true );
|
|
exit( System.False );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.SortArray<T>(const Values: IMyc3Mutable<TArray<T>>; const Comparer: IComparer<T>): IMyc3Mutable<TArray<T>>;
|
|
var
|
|
Cmp: IComparer<T>;
|
|
begin
|
|
Cmp := Comparer;
|
|
if not Assigned(Cmp) then
|
|
Cmp := TComparer<T>.Default;
|
|
|
|
Result := TValue<TArray<T>>.CreateMutable<TArray<T>>(
|
|
Values,
|
|
function( Values: TArray<T> ): TArray<T>
|
|
begin
|
|
SetLength( Result, Length(Values) );
|
|
TArray.Copy<T>( Values, Result, Length(Values) );
|
|
TArray.Sort<T>( Result, Cmp );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable.True: IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TMycMutableBoolean.CreateBoolean( System.True );
|
|
end;
|
|
|
|
class function Mutable<T>.GetComparer: IComparer<IMyc3Mutable<T>>;
|
|
begin
|
|
Result := TMyc3Mutable<T>.Comparer;
|
|
end;
|
|
|
|
class function Mutable<T>.CreateArray( const Arr: TArray<IMyc3Mutable<T>> ): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateArray( Arr );
|
|
end;
|
|
|
|
class function Mutable<T>.CreateArray<S>( const Arr: IMyc3Mutable<TArray<S>>; Calculator: TFunc<S, T> ): IMyc3Mutable<TArray<T>>;
|
|
begin
|
|
Result := TMyc3Mutable<TArray<T>>.CreateMutable(
|
|
[Arr.Changed],
|
|
function: TArray<T>
|
|
var
|
|
i: Integer;
|
|
begin
|
|
SetLength( Result, Length( Arr.Value ) );
|
|
for i := 0 to High( Arr.Value ) do
|
|
Result[i] := Calculator( Arr.Value[i] );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable<T>.Default: IMyc3Mutable<T>;
|
|
begin
|
|
Result := TValue<T>.DefaultMutable;
|
|
end;
|
|
|
|
class function Mutable<T>.IfThen( const Condition: IMyc3Mutable<Boolean>; const TrueValue: IMyc3Mutable<T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( Condition ) and Assigned( TrueValue ) );
|
|
|
|
if Condition = Mutable.True then
|
|
exit( TrueValue )
|
|
else if Condition = Mutable.False then
|
|
exit( default );
|
|
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[Condition.Changed, TrueValue.Changed],
|
|
function: T
|
|
begin
|
|
if Condition.Value then
|
|
Result := TrueValue.Value
|
|
else
|
|
Result := System.Default( T );
|
|
end );
|
|
end;
|
|
|
|
class function Mutable<T>.IfNotThen( const Condition: IMyc3Mutable<Boolean>; const FalseValue: IMyc3Mutable<T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( Condition ) and Assigned( FalseValue ) );
|
|
|
|
if Condition = Mutable.True then
|
|
exit( default )
|
|
else if Condition = Mutable.False then
|
|
exit( FalseValue );
|
|
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[Condition.Changed, FalseValue.Changed],
|
|
function: T
|
|
begin
|
|
if Condition.Value then
|
|
Result := System.Default( T )
|
|
else
|
|
Result := FalseValue.Value;
|
|
end );
|
|
end;
|
|
|
|
class function Mutable<T>.IfThenElse( const Condition: IMyc3Mutable<Boolean>; const TrueValue, FalseValue: IMyc3Mutable<T> ): IMyc3Mutable<T>;
|
|
begin
|
|
Assert( Assigned( Condition ) and Assigned( TrueValue ) and Assigned( FalseValue ) );
|
|
|
|
if Condition = Mutable.True then
|
|
exit( TrueValue );
|
|
if Condition = Mutable.False then
|
|
exit( FalseValue );
|
|
if TrueValue = default then
|
|
exit( IfNotThen( Condition, FalseValue ) );
|
|
if FalseValue = default then
|
|
exit( IfThen( Condition, TrueValue ) );
|
|
|
|
Result := TMyc3Mutable<T>.CreateMutable(
|
|
[Condition.Changed, TrueValue.Changed, FalseValue.Changed],
|
|
function: T
|
|
begin
|
|
if Condition.Value then
|
|
Result := TrueValue.Value
|
|
else
|
|
Result := FalseValue.Value;
|
|
end );
|
|
end;
|
|
|
|
{ TMutableBool }
|
|
|
|
constructor TMutableBool.Create(const AThis: IMyc3Mutable<Boolean>);
|
|
begin
|
|
FThis := AThis;
|
|
end;
|
|
|
|
class function TMutableBool.GetDefaults(Value: Boolean): IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TMycMutableBoolean.CreateBoolean( Value );
|
|
end;
|
|
|
|
class function TMutableBool.True: IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TMycMutableBoolean.CreateBoolean( System.true );
|
|
end;
|
|
|
|
class function TMutableBool.False: IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := TMycMutableBoolean.CreateBoolean( System.false );
|
|
end;
|
|
|
|
class operator TMutableBool.Equal(const A, B: TMutableBool): TMutableBool;
|
|
begin
|
|
Result := TValue<Boolean>.CreateMutable<Boolean, Boolean>(
|
|
A, B,
|
|
function( A, B: Boolean ): Boolean
|
|
begin
|
|
Result := A = B;
|
|
end );
|
|
end;
|
|
|
|
class operator TMutableBool.Implicit(const Value: IMyc3Mutable<Boolean>): TMutableBool;
|
|
begin
|
|
Result.Create( Value );
|
|
end;
|
|
|
|
class operator TMutableBool.Implicit(const Value: TMutableBool): IMyc3Mutable<Boolean>;
|
|
begin
|
|
Result := Value.This;
|
|
end;
|
|
|
|
class operator TMutableBool.LogicalAnd(const A, B: TMutableBool): TMutableBool;
|
|
begin
|
|
Result := TValue<Boolean>.CreateMutable<Boolean, Boolean>(
|
|
A, B,
|
|
function( A, B: Boolean ): Boolean
|
|
begin
|
|
Result := A and B;
|
|
end );
|
|
end;
|
|
|
|
class operator TMutableBool.LogicalNot(const Value: TMutableBool): TMutableBool;
|
|
begin
|
|
Result := TValue<Boolean>.CreateMutable<Boolean>(
|
|
Value,
|
|
function( Value: Boolean ): Boolean
|
|
begin
|
|
Result := not Value;
|
|
end );
|
|
end;
|
|
|
|
class operator TMutableBool.LogicalOr(const A, B: TMutableBool): TMutableBool;
|
|
begin
|
|
Result := TValue<Boolean>.CreateMutable<Boolean, Boolean>(
|
|
A, B,
|
|
function( A, B: Boolean ): Boolean
|
|
begin
|
|
Result := A or B;
|
|
end );
|
|
end;
|
|
|
|
class operator TMutableBool.NotEqual(const A, B: TMutableBool): TMutableBool;
|
|
begin
|
|
Result := TValue<Boolean>.CreateMutable<Boolean, Boolean>(
|
|
A, B,
|
|
function( A, B: Boolean ): Boolean
|
|
begin
|
|
Result := A <> B;
|
|
end );
|
|
end;
|
|
|
|
{ TAssembly<T> }
|
|
|
|
class function TAssembly<T>.Create: IMycAssembly<T>;
|
|
begin
|
|
Result := TMycAssembly<T>.Create;
|
|
end;
|
|
|
|
{ TMycArray<T> }
|
|
|
|
class function TMycArray.Create<T>( const Arr: array of T ): IMycArray<T>;
|
|
begin
|
|
Result := TMycCustomArray<T>.CreateArray( Arr );
|
|
end;
|
|
|
|
class function TMycArray.Create<T>( Count: Integer; const Getter: TFunc<Integer, T> ): IMycArray<T>;
|
|
begin
|
|
Result := TMycGenericArray<T>.Create( Count, Getter );
|
|
end;
|
|
|
|
class function TMycArray.Create<S, T>( const Src: IMycArray<S>; const Converter: TConstFunc<S, T> ): IMycArray<T>;
|
|
begin
|
|
Result := TMycCustomArray<T>.CreateConvert<S>( Src, Converter );
|
|
end;
|
|
|
|
class function TMycArray.Create<T>(const Src: IMyc2Enumerable<T>): IMycArray<T>;
|
|
var
|
|
n: Integer;
|
|
E: IMycEnumerator<T>;
|
|
Vals: TArray<T>;
|
|
begin
|
|
E := Src.GetEnumerator;
|
|
|
|
n := 0;
|
|
while E.MoveNext do
|
|
inc( n );
|
|
|
|
SetLength( Vals, n );
|
|
|
|
E.Reset;
|
|
n := 0;
|
|
while E.MoveNext do
|
|
begin
|
|
Vals[n] := E.Current;
|
|
inc(n);
|
|
end;
|
|
|
|
Result := TMycCustomArray<T>.CreateArray( Vals );
|
|
end;
|
|
|
|
class function TMycArray.CreateConvert<T, S>( const Enum: IMyc2Enumerable<S>; const Conv: TConstFunc<S, T> ): IMyc2Enumerable<T>;
|
|
begin
|
|
Result := TMyc2ConvertEnumerable<T, S>.Create( Enum, Conv );
|
|
end;
|
|
|
|
class function TMycArray.Divide<T>( const Src: TArray<T>; const Comparer: IComparer<T> ): TArray<TArray<T>>;
|
|
var
|
|
i: Integer;
|
|
Arr: TArray<IMycArray<T>>;
|
|
begin
|
|
Arr := Create<T>( Src ).Divide( Comparer );
|
|
|
|
SetLength( Result, Length( Arr ) );
|
|
for i := 0 to High( Result ) do
|
|
Result[i] := Arr[i].ToArray;
|
|
end;
|
|
|
|
class procedure TMycArray.Divide1<TKey, TValue>( const Src: IMycArray<TPair<TKey, TValue>>; out Keys: TArray<TKey>; out Values:
|
|
TArray<IMycArray<TValue>>; const Comparer: IComparer<TKey> );
|
|
var
|
|
Arr: TArray<IMycArray<TPair<TKey, TValue>>>;
|
|
i: Integer;
|
|
begin
|
|
Arr := Src.Divide(
|
|
TComparer<TPair<TKey, TValue>>.Construct(
|
|
function( const A, B: TPair<TKey, TValue> ): Integer
|
|
begin
|
|
Result := Comparer.Compare( A.Key, B.Key );
|
|
end ) );
|
|
|
|
SetLength( Keys, Length( Arr ) );
|
|
SetLength( Values, Length( Arr ) );
|
|
for i := 0 to High( Arr ) do
|
|
begin
|
|
Keys[i] := Arr[i][0].Key;
|
|
|
|
Values[i] := TMycCustomArray<TValue>.CreateConvert<TPair<TKey, TValue>>(
|
|
Arr[i],
|
|
function( const P: TPair<TKey, TValue> ): TValue
|
|
begin
|
|
Result := P.Value;
|
|
end );
|
|
end;
|
|
end;
|
|
|
|
class function TMycArray.Divide<TKey, TValue>( const Src: TArray<TPair<TKey, TValue>>; const Comparer: IComparer<TKey> ): TArray<TPair<TKey,
|
|
TArray<TValue>>>;
|
|
var
|
|
i, j: Integer;
|
|
Arr: TArray<IMycArray<TPair<TKey, TValue>>>;
|
|
begin
|
|
Arr := Create<TPair<TKey, TValue>>( Src ).Divide(
|
|
TComparer<TPair<TKey, TValue>>.Construct(
|
|
function( const A, B: TPair<TKey, TValue> ): Integer
|
|
begin
|
|
Result := Comparer.Compare( A.Key, B.Key );
|
|
end ) );
|
|
|
|
SetLength( Result, Length( Arr ) );
|
|
for i := 0 to High( Result ) do
|
|
begin
|
|
Result[i].Key := Arr[i][0].Key;
|
|
SetLength( Result[i].Value, Arr[i].Count );
|
|
for j := 0 to High( Result[i].Value ) do
|
|
Result[i].Value[j] := Arr[i][j].Value;
|
|
end;
|
|
end;
|
|
|
|
class function TMycArray.Divide<TKey, TValue>( const Src: IMycArray<TPair<TKey, TValue>>; const Comparer: IComparer<TKey> ):
|
|
TArray<TPair<TKey, IMycArray<TValue>>>;
|
|
var
|
|
Arr: TArray<IMycArray<TPair<TKey, TValue>>>;
|
|
i: Integer;
|
|
begin
|
|
Arr := Src.Divide(
|
|
TComparer<TPair<TKey, TValue>>.Construct(
|
|
function( const A, B: TPair<TKey, TValue> ): Integer
|
|
begin
|
|
Result := Comparer.Compare( A.Key, B.Key );
|
|
end ) );
|
|
|
|
SetLength( Result, Length( Arr ) );
|
|
for i := 0 to High( Result ) do
|
|
begin
|
|
Result[i] := TPair<TKey, IMycArray<TValue>>.Create(
|
|
Arr[i][0].Key,
|
|
TMycCustomArray<TValue>.CreateConvert<TPair<TKey, TValue>>(
|
|
Arr[i],
|
|
function( const P: TPair<TKey, TValue> ): TValue
|
|
begin
|
|
Result := P.Value;
|
|
end ) );
|
|
end;
|
|
end;
|
|
|
|
class function TMycArray.GetKeys<TKey, TValue>( const Arr: TArray<TPair<TKey, TValue>> ): TArray<TKey>;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
SetLength( Result, Length( Arr ) );
|
|
for i := 0 to High( Arr ) do
|
|
Result[i] := Arr[i].Key;
|
|
end;
|
|
|
|
class function TChain.Create<T>: IMycChain<T>;
|
|
begin
|
|
Result := TMycChain<T>.Create;
|
|
end;
|
|
|
|
{ TMutableCache<T> }
|
|
|
|
constructor TMutableCache<T>.Create( const AThis: IMyc3MutableTable<T> );
|
|
begin
|
|
FThis := AThis;
|
|
end;
|
|
|
|
function TMutableCache<T>.GetItem(const Value: T): IMyc3Mutable<T>;
|
|
begin
|
|
Result := FThis.Add( Value );
|
|
end;
|
|
|
|
procedure TMutableCache<T>.Clear;
|
|
begin
|
|
FThis.Clear;
|
|
end;
|
|
|
|
class function Stack.Create<T>: IMycStack<T>;
|
|
begin
|
|
Result := TMycStack<T>.Create;
|
|
end;
|
|
|
|
{ TTag }
|
|
|
|
class function TTag.From<T>(const Data: T): TTag;
|
|
begin
|
|
{$ifdef DEBUG}
|
|
Result.FTypeInfo := TypeInfo(T);
|
|
Assert( (Result.FTypeInfo<>nil) and (Result.FTypeInfo.Name <> 'TTag'), 'Recursive tag declaration' );
|
|
{$endif}
|
|
|
|
case PTypeInfo(TypeInfo(T)).Kind of
|
|
tkInteger:
|
|
begin
|
|
case PTypeInfo(TypeInfo(T)).TypeData.OrdType of
|
|
otSByte: PShortInt(@Result.FOrdinal)^ := PShortInt(@Data)^;
|
|
otUByte: PByte(@Result.FOrdinal)^ := PByte(@Data)^;
|
|
otSWord: PSmallInt(@Result.FOrdinal)^ := PSmallInt(@Data)^;
|
|
otUWord: PWord(@Result.FOrdinal)^ := PWord(@Data)^;
|
|
otSLong: PInteger(@Result.FOrdinal)^ := PInteger(@Data)^;
|
|
otULong: PLongword(@Result.FOrdinal)^ := PLongword(@Data)^;
|
|
end;
|
|
end;
|
|
|
|
tkInt64:
|
|
begin
|
|
Result.FOrdinal := PInt64(@Data)^;
|
|
end;
|
|
|
|
tkFloat:
|
|
begin
|
|
case PTypeInfo(TypeInfo(T)).TypeData.FloatType of
|
|
ftSingle: PSingle(@Result.FOrdinal)^ := PSingle(@Data)^;
|
|
ftDouble: PDouble(@Result.FOrdinal)^ := PDouble(@Data)^;
|
|
else
|
|
begin
|
|
Result.FOrdinal := 0;
|
|
Result.FManaged := TMyc3Value<T>.Create(Data);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{$IFNDEF AUTOREFCOUNT}
|
|
tkClass,
|
|
{$ENDIF}
|
|
tkPointer:
|
|
begin
|
|
PPointer(@Result.FOrdinal)^ := PPointer(@Data)^;
|
|
end;
|
|
|
|
tkInterface:
|
|
begin
|
|
Result.FOrdinal := 0;
|
|
Result.FManaged := IInterface(PPointer(@Data)^);
|
|
end;
|
|
|
|
else
|
|
begin
|
|
Result.FOrdinal := 0;
|
|
Result.FManaged := TMyc3Value<T>.Create(Data);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TTag.AsType<T>: T;
|
|
begin
|
|
{$ifdef DEBUG}
|
|
if FTypeInfo=nil then
|
|
RaiseInvalidOperation( 'TTag not initialized, value of type %s expected', [PTypeInfo(TypeInfo(T)).Name] );
|
|
|
|
if FTypeInfo <> TypeInfo(T) then
|
|
RaiseInvalidOperation( 'TTag<%s> can''t cast to %s', [FTypeInfo.Name, PTypeInfo(TypeInfo(T)).Name] );
|
|
{$endif}
|
|
|
|
case PTypeInfo(TypeInfo(T)).Kind of
|
|
tkInteger:
|
|
begin
|
|
case PTypeInfo(TypeInfo(T)).TypeData.OrdType of
|
|
otSByte: PShortInt(@Result)^ := PShortInt(@FOrdinal)^;
|
|
otUByte: PByte(@Result)^ := PByte(@FOrdinal)^;
|
|
otSWord: PSmallInt(@Result)^ := PSmallInt(@FOrdinal)^;
|
|
otUWord: PWord(@Result)^ := PWord(@FOrdinal)^;
|
|
otSLong: PInteger(@Result)^ := PInteger(@FOrdinal)^;
|
|
otULong: PLongword(@Result)^ := PLongword(@FOrdinal)^;
|
|
end;
|
|
end;
|
|
|
|
tkInt64:
|
|
begin
|
|
PInt64(@Result)^ := FOrdinal;
|
|
end;
|
|
|
|
tkFloat:
|
|
begin
|
|
case PTypeInfo(TypeInfo(T)).TypeData.FloatType of
|
|
ftSingle: PSingle(@Result)^ := PSingle(@FOrdinal)^;
|
|
ftDouble: PDouble(@Result)^ := PDouble(@FOrdinal)^;
|
|
else
|
|
Result := IMyc3Value<T>( FManaged ).Value;
|
|
end;
|
|
end;
|
|
|
|
{$IFNDEF AUTOREFCOUNT}
|
|
tkClass,
|
|
{$ENDIF}
|
|
tkPointer:
|
|
begin
|
|
PPointer(@Result)^ := PPointer(@FOrdinal)^;
|
|
end;
|
|
|
|
tkInterface:
|
|
begin
|
|
IInterface(PPointer(@Result)^) := FManaged;
|
|
end;
|
|
|
|
else
|
|
begin
|
|
Result := IMyc3Value<T>( FManaged ).Value;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TMycStateQueue }
|
|
|
|
constructor TMycStateQueue.Create(const AStack: IAtomicStack<IMyc2State>);
|
|
begin
|
|
FStack := AStack;
|
|
end;
|
|
|
|
procedure TMycStateQueue.Add(const S: IMyc2State);
|
|
begin
|
|
FStack.Push( S );
|
|
end;
|
|
|
|
class function TMycStateQueue.Create: TMycStateQueue;
|
|
begin
|
|
Result.Create( TAtomicStack<IMyc2State>.Create );
|
|
end;
|
|
|
|
procedure TMycStateQueue.WaitFor;
|
|
var
|
|
S: IMyc2State;
|
|
begin
|
|
S := FStack.Pop;
|
|
while S<>nil do
|
|
begin
|
|
Tasks.WaitFor( S );
|
|
S := FStack.Pop;
|
|
end;
|
|
end;
|
|
|
|
{ TMutable<T> }
|
|
|
|
class function TMutable<T>.FromSignals(const Changed: array of IMyc2Signal; const Calculator: TFunc<T>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3Mutable<T>.CreateMutable( Changed, Calculator );
|
|
end;
|
|
|
|
class function TMutable<T>.FromSignals(const Changed: array of IMyc2Signal; const Calculator: TFunc<IMyc3Mutable<T>>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := TMyc3EnclosedMutable<T>.Create( TMyc3Mutable<IMyc3Mutable<T>>.CreateMutable( Changed, Calculator ) );
|
|
end;
|
|
|
|
class function TMutable<T>.From<S>(const Value: IMyc3Mutable<S>; const Conv: TFunc<S, IMyc3Mutable<T>>): TMutable<T>;
|
|
begin
|
|
Result := TMyc3EnclosedMutable<T>.Create( TValue<IMyc3Mutable<T>>.CreateMutable<S>( Value, Conv ) );
|
|
end;
|
|
|
|
class operator TMutable<T>.Explicit(const Value: T): TMutable<T>;
|
|
begin
|
|
Result.FThis := TMyc3ConstantMutable<T>.Create( Value );
|
|
end;
|
|
|
|
class operator TMutable<T>.Implicit(
|
|
const Item: TMutable<T>): IMyc3Mutable<T>;
|
|
begin
|
|
Result := Item.FThis;
|
|
end;
|
|
|
|
class operator TMutable<T>.Implicit(
|
|
const Item: IMyc3Mutable<T>): TMutable<T>;
|
|
begin
|
|
Result.FThis := Item;
|
|
end;
|
|
|
|
{ TParameterValue }
|
|
|
|
constructor TParameterValue.Create( ATypeInfo: PTypeInfo; const AMutable: IMyc3Mutable );
|
|
begin
|
|
FMutable := AMutable;
|
|
{$ifdef DEBUG}
|
|
FTypeInfo := ATypeInfo;
|
|
{$endif}
|
|
end;
|
|
|
|
function TParameterValue.Get<T>: T;
|
|
begin
|
|
Assert( FMutable<>nil, 'Value is NULL' );
|
|
Result := AsType<T>.Value;
|
|
end;
|
|
|
|
function TParameterValue.AsType<T>: IMyc3Mutable<T>;
|
|
begin
|
|
{$ifdef DEBUG}
|
|
CheckType( TypeInfo( T ) );
|
|
{$endif}
|
|
Result := IMyc3Mutable<T>( FMutable );
|
|
end;
|
|
|
|
class function TParameterValue.Compare( const A, B: TParameterValue ): Integer;
|
|
begin
|
|
Result := CompareValue( NativeInt( A.Mutable ), NativeInt( B.Mutable ) );
|
|
end;
|
|
|
|
class function TParameterValue.FromArray<T>( const Values: TArray<TParameterValue> ): TArray<IMyc3Mutable<T>>;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
SetLength( Result, Length( Values ) );
|
|
for i := 0 to High( Result ) do
|
|
Result[i] := Values[i].AsType<T>;
|
|
end;
|
|
|
|
class function TParameterValue.Create<T>( const Intf: T ): TParameterValue;
|
|
begin
|
|
Result.Create( TypeInfo( T ), TValue<T>.CreateMutable( Intf ) );
|
|
end;
|
|
|
|
class function TParameterValue.Create<T>( const Intf: IMyc3Mutable<T> ): TParameterValue;
|
|
begin
|
|
Result.Create( TypeInfo( T ), Intf );
|
|
end;
|
|
|
|
constructor TParameterValue.Assign( const Src: TParameterValue );
|
|
begin
|
|
{$ifdef DEBUG}
|
|
CheckType( Src.FTypeInfo );
|
|
{$endif}
|
|
FMutable := Src.FMutable;
|
|
end;
|
|
|
|
{$ifdef DEBUG}
|
|
procedure TParameterValue.CheckType(TI: PTypeInfo);
|
|
begin
|
|
Assert( FTypeInfo = TI, Format( 'Type mismatch (casting param %s to %s)', [FTypeInfo.Name, TI.Name] ) );
|
|
end;
|
|
{$endif}
|
|
|
|
class function TParameterValue.FromVarRec( const VarRec: TVarRec ): TParameterValue;
|
|
begin
|
|
case VarRec.VType of
|
|
vtInteger:
|
|
Result := TParameterValue.Create<Integer>( VarRec.VInteger );
|
|
vtBoolean:
|
|
Result := TParameterValue.Create<Boolean>( VarRec.VBoolean );
|
|
vtWideChar:
|
|
Result := TParameterValue.Create<WideChar>( VarRec.VWideChar );
|
|
vtInt64:
|
|
Result := TParameterValue.Create<Int64>( VarRec.VInt64^ );
|
|
vtChar:
|
|
Result := TParameterValue.Create<String>( String( VarRec.VChar ) );
|
|
vtPChar:
|
|
Result := TParameterValue.Create<String>( String( VarRec.VPChar ) );
|
|
vtPWideChar:
|
|
Result := TParameterValue.Create<String>( String( VarRec.VPWideChar ) );
|
|
vtString:
|
|
Result := TParameterValue.Create<String>( String( VarRec.VString^ ) );
|
|
vtWideString:
|
|
Result := TParameterValue.Create<String>( String( VarRec.VWideString ) );
|
|
vtAnsiString:
|
|
Result := TParameterValue.Create<String>( String( VarRec.VAnsiString ) );
|
|
vtUnicodeString:
|
|
Result := TParameterValue.Create<String>( String( VarRec.VUnicodeString ) );
|
|
vtObject:
|
|
Result := TParameterValue.Create<TObject>( TObject( VarRec.VObject ) );
|
|
vtClass:
|
|
Result := TParameterValue.Create<TClass>( VarRec.VClass );
|
|
vtVariant:
|
|
Result := TParameterValue.Create<Variant>( VarRec.VVariant^ );
|
|
vtPointer:
|
|
Result := TParameterValue.Create<Pointer>( VarRec.VPointer );
|
|
vtExtended:
|
|
Result := TParameterValue.Create<Extended>( VarRec.VExtended^ );
|
|
vtCurrency:
|
|
Result := TParameterValue.Create<Currency>( VarRec.VCurrency^ );
|
|
vtInterface:
|
|
Result := TParameterValue.Create<IInterface>( IInterface( VarRec.VInterface ) );
|
|
end;
|
|
end;
|
|
|
|
{ TParameterField }
|
|
|
|
constructor TParameterField.Create( AID: TFieldID; const AValue: TParameterValue );
|
|
begin
|
|
FID := AID;
|
|
FValue := AValue;
|
|
end;
|
|
|
|
class function TParameterField.Create<T>( ID: TFieldID; const Intf: IMyc3Mutable<T> ): TParameterField;
|
|
begin
|
|
Result := TParameterField.Create( ID, TParameterValue.Create<T>( Intf ) );
|
|
end;
|
|
|
|
class function TParameterField.Create<T>( ID: TFieldID; const Intf: T ): TParameterField;
|
|
begin
|
|
Result := TParameterField.Create( ID, TParameterValue.Create<T>( Intf ) );
|
|
end;
|
|
|
|
{ TParameterRecord }
|
|
|
|
constructor TParameterRecord.Create( const AThis: IMyc3ParameterRecord );
|
|
begin
|
|
FThis := AThis;
|
|
end;
|
|
|
|
function TParameterRecord.AsType<T>( ID: TFieldID ): IMyc3Mutable<T>;
|
|
begin
|
|
Result := GetValues( ID ).AsType<T>;
|
|
end;
|
|
|
|
function TParameterRecord.Get<T>(ID: TFieldID): T;
|
|
begin
|
|
Result := GetValues( ID ).Get<T>;
|
|
end;
|
|
|
|
function TParameterRecord.GetByName( const Caption: String ): TParameterValue;
|
|
begin
|
|
Result := FThis.ByName[Caption];
|
|
end;
|
|
|
|
function TParameterRecord.GetDef: IMycParameterRecordDefinition;
|
|
begin
|
|
Result := FThis.Def;
|
|
end;
|
|
|
|
function TParameterRecord.GetValues(ID: TFieldID): TParameterValue;
|
|
begin
|
|
Result := FThis.Values[ID];
|
|
end;
|
|
|
|
class operator TParameterRecord.Implicit(const Item: IMyc3ParameterRecord): TParameterRecord;
|
|
begin
|
|
Result.Create( Item );
|
|
end;
|
|
|
|
class operator TParameterRecord.Implicit(const Item: TParameterRecord): IMyc3ParameterRecord;
|
|
begin
|
|
Result := Item.FThis;
|
|
end;
|
|
|
|
{ TParameterSpace }
|
|
|
|
constructor TParameterSpace.Create( const AThis: IMycParameterSpace );
|
|
begin
|
|
FThis := AThis;
|
|
end;
|
|
|
|
function TParameterSpace.CompareValues( FieldID: TFieldID; const A, B: TParameterValue ): Integer;
|
|
begin
|
|
Result := FThis.CompareValues( FieldID, A, B );
|
|
end;
|
|
|
|
class function TParameterSpace.Create: TParameterSpace;
|
|
begin
|
|
Result.Create( TMycParameterSpace.Create );
|
|
end;
|
|
|
|
function TParameterSpace.CreateRecord( const Fields: TArray<TParameterField> ): TParameterRecord;
|
|
begin
|
|
Result.Create( FThis.CreateRecord( Fields ) );
|
|
end;
|
|
|
|
function TParameterSpace.GetCaptions( FieldID: TFieldID ): String;
|
|
begin
|
|
Result := FThis.Captions[FieldID];
|
|
end;
|
|
|
|
function TParameterSpace.GetComparer( FieldID: TFieldID ): IComparer<TParameterValue>;
|
|
begin
|
|
Result := FThis.Comparer[FieldID];
|
|
end;
|
|
|
|
function TParameterSpace.GetDefaultValues( FieldID: TFieldID ): TParameterValue;
|
|
begin
|
|
Result := FThis.DefaultValues[FieldID];
|
|
end;
|
|
|
|
function TParameterSpace.GetFieldCount: Integer;
|
|
begin
|
|
Result := FThis.FieldCount;
|
|
end;
|
|
|
|
function TParameterSpace.AddField<T>(const Caption: String; const DefaultValue: T; const Comparer: IComparer<T> = nil): TFieldID;
|
|
var
|
|
ValueComparer: IComparer<T>;
|
|
Comp: IComparer<TParameterValue>;
|
|
begin
|
|
ValueComparer := Comparer;
|
|
if ValueComparer=nil then
|
|
ValueComparer := TComparer<T>.Default;
|
|
|
|
Comp := TComparer<TParameterValue>.Construct(
|
|
function( const A, B: TParameterValue ): Integer
|
|
begin
|
|
if ( A.Mutable <> nil ) and ( B.Mutable<>nil ) then
|
|
Result := ValueComparer.Compare( A.AsType<T>.Value, B.AsType<T>.Value )
|
|
else if A.Mutable <> nil then
|
|
Result := 1
|
|
else if B.Mutable <> nil then
|
|
Result := -1
|
|
else
|
|
Result := 0;
|
|
end );
|
|
|
|
Result := FThis.AddField( TypeInfo( T ), Caption, TValue<T>.CreateMutable( DefaultValue ), Comp );
|
|
end;
|
|
|
|
function TParameterSpace.CreateDef(const Fields: TArray<TFieldID>): IMycParameterRecordDefinition;
|
|
begin
|
|
Result := FThis.CreateDef( Fields );
|
|
end;
|
|
|
|
class operator TParameterSpace.Implicit( const Item: TParameterSpace ): IMycParameterSpace;
|
|
begin
|
|
Result := Item.FThis;
|
|
end;
|
|
|
|
class operator TParameterSpace.Implicit( const Item: IMycParameterSpace ): TParameterSpace;
|
|
begin
|
|
Result.Create( Item );
|
|
end;
|
|
|
|
{ TMutableFuture }
|
|
|
|
class function TMutableFuture.FromArray<T>(const Value: TArray<IMyc3Mutable<IMyc3Future<T>>>): IMyc3Mutable<IMyc3Future<TArray<T>>>;
|
|
begin
|
|
Result := Mutable.Convert<TArray<IMyc3Future<T>>, IMyc3Future<TArray<T>>>(
|
|
Mutable.FromArray<IMyc3Future<T>>( Value ),
|
|
function( Value: TArray<IMyc3Future<T>> ): IMyc3Future<TArray<T>>
|
|
begin
|
|
Result := TFuture.FromArray<T>( Value );
|
|
end );
|
|
end;
|
|
|
|
constructor TStackTrace.Create(ASkipFrames: Cardinal; const AMsg: String = '');
|
|
begin
|
|
Msg := AMsg;
|
|
{$ifdef FullDebugMode}
|
|
FastMM_EnterDebugMode;
|
|
FastMM_GetStackTrace(@StackTrace, Length(StackTrace), 0);
|
|
{$endif}
|
|
end;
|
|
|
|
function TStackTrace.ToText: String;
|
|
{$ifdef FullDebugMode}
|
|
var
|
|
LStackTraceBuffer: array[0..Len * 160] of WideChar;
|
|
{$endif}
|
|
begin
|
|
Result := Msg;
|
|
if Result<>'' then
|
|
Result := Result + #13#10;
|
|
|
|
{$ifdef FullDebugMode}
|
|
FastMM_ConvertStackTraceToText(
|
|
@StackTrace, Length(StackTrace), @LStackTraceBuffer,
|
|
@LStackTraceBuffer[High(LStackTraceBuffer)]);
|
|
|
|
Result := Result + LStackTraceBuffer;
|
|
{$else}
|
|
Result := Result + 'StackTrace: FullDebugMode not enabled';
|
|
{$endif}
|
|
end;
|
|
|
|
class function TValidatable.FromSignal(const Signal: IMyc2Signal): IMyc3Validatable;
|
|
begin
|
|
Result := TMyc3ValidatableSignal.Create(Signal);
|
|
end;
|
|
|
|
initialization
|
|
|
|
Tasks := TMyc3Tasks.Create( TMyc2TaskFactory.Create );
|
|
|
|
finalization
|
|
|
|
FreeAndNil( Tasks );
|
|
|
|
end.
|