Jump to content

Primož Gabrijelčič

Members
  • Content Count

    88
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by Primož Gabrijelčič

  1. Primož Gabrijelčič

    Delphi 5 FOR Loop problem (W10-64bit)

    It uses "banker's rounding", after all. 😉
  2. Primož Gabrijelčič

    Delphi 5 FOR Loop problem (W10-64bit)

    http://docwiki.embarcadero.com/RADStudio/en/Declarations_and_Statements_(Delphi)#For_Statements
  3. Primož Gabrijelčič

    Delphi 5 FOR Loop problem (W10-64bit)

    That behavior is correct. `for` loop will execute once with `i` being set to 0.
  4. Primož Gabrijelčič

    ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio

    Uwe's post clearly states: HKEY_CURRENT_USER\Software\Parnassus OU\Core
  5. Primož Gabrijelčič

    ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio

    Works like a charm! Thank you!
  6. Primož Gabrijelčič

    ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio

    Great idea, but unfortunately it doesnt work. Setting it to "($BDS)\Experts" fails in the same way.
  7. Primož Gabrijelčič

    ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio

    @David Millington Can you - or Embarcadero - please publish Bookmarks and Navigator 1.6 for older platforms? Or create a version that does not depend on share "Core" DLL? I think the community would very much appreciate it. I know I would.
  8. Primož Gabrijelčič

    ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio

    I have C:\Users\gabr\Documents\Embarcadero\Studio\20.0\CatalogRepository\ParnassusCoreEditor-1.0\ParnassusCoreEditor.dll (modified 15.2.2019) and C:\Users\gabr\AppData\Roaming\Parnassus OU\Common\ParnassusCoreEditor_XBerlin.dll (modified 20.5.2016) So I don't see why the 1.6 install in Rio would break Berlin at all 😞
  9. Primož Gabrijelčič

    ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio

    Installed Bookmarks & Navigator in Rio. Now my Berlin reports "Access violation at address 07E8D047 in module 'ParnassusCoreEditor.dll'. Read of address 00000000." when I start the IDE. I get the same error when loading a project and then Bookmarks doesn't work. I also get a bunch of errors when I open a form unit and then I get into "Access violation at address 20837CFB in module 'coreide240.bpl'. Read of address 00000018." which repeats indefinitely. 😠 I have Bookmarks 1.5.1 installed in Berlin. Is there anything I can do to have working Bookmarks both in Berlin and Rio?
  10. Primož Gabrijelčič

    Omni for Multi Platform?

    Indeed, I'm working on it. Now that I have finished my book, OTL will again become a top priority side project. It's hard to tell how much work is yet to be done as at the moment some very basic parts are still missing and I don't know how much time I'll need for them. A crowdfund would be nice - one where you can give me additional time inside a day. 30h per day would be good to have 😉
  11. Primož Gabrijelčič

    Generating one-to-many on the fly with Live Bindings

    I'm playing with Live Bindings and looking at how far I can push it 🙂 ... I wanted to see if I can take a single-item source (edit box) and bind it to a list-type control (list box), somehow splitting the data in the process. This is what I ended at: 1. Bind expression that binds Edit1, Text to ListBox1, Items.DelimitedText. 2. OnAssigningValue event for that bind expression: procedure TForm85.BindExpression1AssigningValue(Sender: TObject; AssignValueRec: TBindingAssignValueRec; var Value: TValue; var Handled: Boolean); begin Value := StringReplace(Value.AsString, ', ', ',', [rfReplaceAll]); end; (This allows me to type in "1, 2, 3" or "1,2,3" and both split into "1", "2", and "3".) 3. Edit1.OnChangeTracking which updates the expression: procedure TForm85.Edit1ChangeTracking(Sender: TObject); begin BindingsList1.Notify(Sender, 'Text'); end; 4. Some initialization for DelimitedText to work correctly: ListBox1.Items.Delimiter := ','; ListBox1.Items.StrictDelimiter := true; Demo project is attached. Does anyone see a better solution for that? (Better = requires writing less code.) (No need to tell me that my problem is stupid and that I should redesign my app so that I don't have to do any splitting of data. I know that. This is an exercise.) liveb.zip
  12. Primož Gabrijelčič

    Generating one-to-many on the fly with Live Bindings

    Nice additions, Andrea 🙂 Whether for the good or bad, who can tell 😉 My initial approach was trying to get too much from LiveBindings anyway (intentionally). Your changes are definitely in direction of making my messy code more maintainable so they make it better. They, however, introduce more code, so from my original viewpoint they make it worse. 😉
  13. No, and don't expect one soon. There are more urgent issues to be fixed before.
  14. Primož Gabrijelčič

    Freeing tasks memory

    Great that you got it working! Re 4000 tasks I was thinking more about - what if you set up a Parallel.BackgroundWorker with multiple workers and then schedule work units to it? You would have one always running execution engine (i.e. background worker) and instead of 4000 tasks you would have 4000 work units.
  15. Primož Gabrijelčič

    Object destroyed too soon?

    Dear all, I'm being stupid and I can't figure why in the following code the `TTestObj` is destroyed before its owner. Can you please help? Full code is available here and is also posted at the end of this post. Basically, I have an interface `IWorkItem` which owns record `TOmniValue` which owns interface `IAutoDestroyObject`. The code creates an instance of `IWorkItem` and then calls: procedure Test(const workItem: IWorkItem); begin workItem.Result.AsOwnedObject := TTestObj.Create; end; This sets the `IAutoDestroyObject` field of the nested `TOmniValue` record. When the `Test` function exits (during the procedure finalization code) this `TTestObj` gets destroyed, and I can't figure out why. program ObjectDestroyedTooSoon; {$APPTYPE CONSOLE} {$R *.res} uses Winapi.Windows, System.SysUtils; type TTestObj = class public destructor Destroy; override; end; IAutoDestroyObject = interface ['{30CF4CCF-9383-41C0-BBA3-E24F7C4EFF71}'] function GetObj: TObject; property Obj: TObject read GetObj; end; TAutoDestroyObject = class(TInterfacedObject, IAutoDestroyObject) strict private FObject: TObject; protected function GetObj: TObject; public constructor Create(obj: TObject); destructor Destroy; override; property Obj: TObject read GetObj; end; TOmniValue = record private FOwnedObject: IAutoDestroyObject; function GetAsOwnedObject: TObject; procedure SetAsOwnedObject(const Value: TObject); public property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; end; IWorkItem = interface ['{7C583FC8-90DD-46A5-81B9-81B911AA1CBE}'] function GetResult: TOmniValue; procedure SetResult(const Value: TOmniValue); property Result: TOmniValue read GetResult write SetResult; end; TWorkItem = class(TInterfacedObject, IWorkItem) strict private FResult: TOmniValue; strict protected function GetResult: TOmniValue; procedure SetResult(const Value: TOmniValue); public destructor Destroy; override; property Result: TOmniValue read GetResult write SetResult; end; { TTestObj } destructor TTestObj.Destroy; begin Writeln('TTestObj destroyed'); inherited; end; { TWorkItem } destructor TWorkItem.Destroy; begin Writeln('TWorkItem destroyed'); inherited; end; function TWorkItem.GetResult: TOmniValue; begin Result := FResult; end; procedure TWorkItem.SetResult(const Value: TOmniValue); begin FResult := Value; end; { TOmniValue } function TOmniValue.GetAsOwnedObject: TObject; begin Result := FOwnedObject.Obj; end; procedure TOmniValue.SetAsOwnedObject(const Value: TObject); begin FOwnedObject := TAutoDestroyObject.Create(Value); end; { TAutoDestroyObject } constructor TAutoDestroyObject.Create(obj: TObject); begin inherited Create; FObject := obj; end; destructor TAutoDestroyObject.Destroy; begin FreeAndNil(FObject); inherited; end; function TAutoDestroyObject.GetObj: TObject; begin Result := FObject; end; { main } procedure Test(const workItem: IWorkItem); begin workItem.Result.AsOwnedObject := TTestObj.Create; end; var workItem: IWorkItem; begin try workItem := TWorkItem.Create; Test(workItem); Writeln('After Test'); workItem := nil; Writeln('workItem destroyed'); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
  16. Primož Gabrijelčič

    Object destroyed too soon?

    Got it. type POmniValue = ^TOmniValue; TOmniValue = record private FOwnedObject: IAutoDestroyObject; function GetAsOwnedObject: TObject; procedure SetAsOwnedObject(const Value: TObject); public class operator Implicit(var ov: TOmniValue): POmniValue; static; property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; end; IWorkItem = interface ['{7C583FC8-90DD-46A5-81B9-81B911AA1CBE}'] function GetResult: POmniValue; procedure SetResult(const Value: POmniValue); property Result: POmniValue read GetResult write SetResult; end; TWorkItem = class(TInterfacedObject, IWorkItem) strict private FResult: TOmniValue; strict protected function GetResult: POmniValue; procedure SetResult(const Value: POmniValue); public destructor Destroy; override; property Result: POmniValue read GetResult write SetResult; end; class operator TOmniValue.Implicit(var ov: TOmniValue): POmniValue; begin Result := @ov; end; function TWorkItem.GetResult: POmniValue; begin Result := @FResult; end; procedure TWorkItem.SetResult(const Value: POmniValue); begin FResult := Value^; end; It's quite possible that this breaks quite easily, though, as this solution looks quite fragile to me. It is simple and efficient, though. full code here
  17. Primož Gabrijelčič

    Object destroyed too soon?

    Yes, it is definitely not a fast solution. It is elegant for the user, though.
  18. Primož Gabrijelčič

    Object destroyed too soon?

    This works, but requires lots of code if I would want to implement it with the original (very rich) `TOmniValue` record: IOmniValueFwd = interface; TOmniValue = record private FOwnedObject: IAutoDestroyObject; function GetAsOwnedObject: TObject; procedure SetAsOwnedObject(const Value: TObject); public class operator Implicit(const ov: TOmniValue): IOmniValueFwd; property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; end; IOmniValueFwd = interface ['{4CCE0702-1CBF-4467-8185-8C38C37BA624}'] function GetAsOwnedObject: TObject; function GetValue: TOmniValue; procedure SetAsOwnedObject(const Value: TObject); property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; property Value: TOmniValue read GetValue; end; TOmniValueFwd = class(TInterfacedObject, IOmniValueFwd) strict private FOmniValue: TOmniValue; strict protected function GetAsOwnedObject: TObject; function GetValue: TOmniValue; procedure SetAsOwnedObject(const Value: TObject); public constructor Create(const ov: TOmniValue); property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; property Value: TOmniValue read GetValue; end; IWorkItem = interface ['{7C583FC8-90DD-46A5-81B9-81B911AA1CBE}'] function GetResult: IOmniValueFwd; procedure SetResult(const Value: IOmniValueFwd); property Result: IOmniValueFwd read GetResult write SetResult; end; I can then use: procedure Test(const workItem: IWorkItem); begin workItem.Result.AsOwnedObject := TTestObj.Create; end; or: procedure Test(const workItem: IWorkItem); var ov: TOmniValue; begin ov.AsOwnedObject := TTestObj.Create; workItem.Result := ov; end; And both work fine. full code here
  19. Primož Gabrijelčič

    Object destroyed too soon?

    I'm thinking about changing `IWorkItem.Result` into `TOmniValueClass = class ...` where `TOmniValueClass` exports same API as `TOmniValue` and forwards all requests to a private `TOmniValue` record. LTR: Meh, doesn't work. That makes the getter work fine, but again stops the setter from working 😞
  20. Primož Gabrijelčič

    Object destroyed too soon?

    Hmmm, I'll have to think about it. That can be a solution but I'm afraid I will cause too big mess. Thanks.
  21. You have: Renderer := Parallel.ParallelTask.NumTasks(numTasks).NoWait .Execute( procedure begin workItem := RenderQueue.Next; ... end); and then: for iTask := 0 to numTasks-1 do begin TileSource := workItem.Data['TileSource' + iTask.ToString]; RenderQueue.Add(TOmniValue.Create([iTask, TileSource])); end; If you change only the parameter to `ParallelTask.NumTasks`, some tasks won't ever get data because you'll schedule only `numTasks` items to `RenderQueue`.
  22. Primož Gabrijelčič

    Object destroyed too soon?

    Do we have any neat solution for that problem? I can change `IWorkItem` to: IWorkItem = interface ['{7C583FC8-90DD-46A5-81B9-81B911AA1CBE}'] function GetResult: POmniValue; procedure SetResult(const Value: TOmniValue); property Result: POmniValue read GetResult; end; This allows me to use: workItem.Result.AsOwnedObject := TTestObj.Create; But it also prevents me from doing: workItem.Result := TTestObj.Create; Which is more common usage. Grrrrr!
  23. `workItem.Result` is a record property. Because of that, this code: workItem.Result.AsOwnedObject := TBitmap32.Create(256,256); is equivalent to running: var tmp: TOmniValue; tmp := workItem.Result; tmp.AsOwnedObject := TBitmap32.Create(256,256); And that fails. You should change the code to: var tmp: TOmniValue; tmp.AsOwnedObject := TBitmap32.Create(256,256); workItem.Result := tmp; I'll see if I can change the implementation of `IOmniWorkitem` to prevent such problems.
  24. Primož Gabrijelčič

    Object destroyed too soon?

    Doh! I knew I was just stupid. To recap (for people who don't want to dig through ton of code). procedure Test(const workItem: IWorkItem); begin workItem.Result.AsOwnedObject := TTestObj.Create; end; is equivalent to: procedure Test(const workItem: IWorkItem); var tmp: TOmniValue; begin tmp := workItem.Result; tmp.AsOwnedObject := TTestObj.Create; end; To do it correctly, one must change the code to: procedure Test(const workItem: IWorkItem); var ov: TOmniValue; begin ov.AsOwnedObject := TTestObj.Create; workItem.Result := ov; end; Thank you, guys!
  25. Minimized problem: Maybe somebody can tell me what is going on because I'm clueless.
×