Jump to content

Anders Melander

Members
  • Content Count

    2771
  • Joined

  • Last visited

  • Days Won

    147

Everything posted by Anders Melander

  1. Anders Melander

    UsesCleaner Issue...

    It would be stellar if we had a switch that could disable this behavior completely. I'm sick and tired of cleaning up the uses clause before commit, every time I have had a form open in the IDE during debug. Particularly since DevExpress keeps adding stupid dependencies between their units which causes the uses list to grow and grow for no good reason.
  2. Anders Melander

    Datamodule with ImageCollection of PNGs loading with packages

    That's not how you use coInitialize/coUninitialize. First of all check the return value of coInitialize and don't call coUnititialize unless the return status indicated that it succeeded. Read the documentation. And don't call coUninitialize until you are sure that everything using the thread apartment is done with it. Since you're doing this in the main thread and you don't know what else is using it you are best of doing it just before the final end. Normally this is something that would be done in the initialization and finalization sections of a unit. Finally, use coInitializeEx instead.
  3. Anders Melander

    DUnitX: How can I load HTML files within unit test?

    If the logic that does the HTTP request, extract the HTML and scrapes the HTML are all nicely separated then I don't see why you'd need a mock (personally I try to avoid them as they just become one more piece of code to maintain). For example if your scraper reads from a stream, then just have the unit test pass it a TFileStream and Bob's your uncle/aunt/non-binary auncle.
  4. Anders Melander

    UsesCleaner Issue...

    Or if earlier versions are to be supported: $IFDEF CONDITIONALEXPRESSIONS} {$IF CompilerVersion >= 14.0} Variants, {$IFEND} {$ENDIF} If not, then Variants might just as well be moved outside the conditional.
  5. Anders Melander

    Interesting way to copy dynamic arrays.

    It's in the documentation... So probably not 🙂
  6. Anders Melander

    Interesting way to copy dynamic arrays.

    There's DynArrayUnique but it's undocumented and not really fit for direct use: procedure DynArrayUnique(var A: Pointer; typeInfo: Pointer); begin if (A <> nil) and (PDynArrayRec(PByte(A) - SizeOf(TDynArrayRec))^.RefCnt > 1) then DynArrayCopy(A, A, typeInfo); end;
  7. Anders Melander

    Interesting way to copy dynamic arrays.

    A simple "yes" would have been enough 🙂
  8. Anders Melander

    Interesting way to copy dynamic arrays.

    Read what I wrote again.
  9. Anders Melander

    Interesting way to copy dynamic arrays.

    I still don't get it. Just start with the assignment and use B:= Copy(B) when you need it to be unique.... Ah, I think I get it now. You don't want to keep track of the arrays reference count. So it's like UniqueString for dynamic arrays? Does nothing if the reference count is already 1, otherwise makes a unique copy. Right?
  10. Anders Melander

    Interesting way to copy dynamic arrays.

    B := A makes them the same array. SetLength just makes B unique (and contains an implicit copy). I don't get what advantage assignment followed by SetLength gives you over a simple Copy. With Copy the intent is explicit.
  11. Anders Melander

    SudokuHelper - Example for uncoupled design via interfaces

    I like this quote from Graig (in the comments): Wise words.
  12. Anders Melander

    FormStyle in legacy code

    Because the implementation wasn't designed to handle it. IMO there are better solutions. Docking for example (just not the VCL's docking - it's broken beyond repair).
  13. Anders Melander

    FormStyle in legacy code

    Here you go. I've only included the stuff that directly deals with switching between SDI and MDI. The original code had a lot of logic related to positioning of the child windows, different layouts and and such. MDI_SDI.zip
  14. Good thing we got that settled. *cough*Asperger*cough* 🙂
  15. I once worked at a place that made calculation software for the construction business. When I started there all numbers were stored internally as strings. Apparently someone there knew about the problems associated with floating point numbers and had decided to solve the problem by representing all values as decimal formatted strings instead. Problem solved, right? Well, not exactly because every time they needed to recalculate values (i.e. just about every time the user did anything in the application) the strings were converted to floats, recalculated and then back to strings. Need to adjust the precision? Easy; Just truncate the length of the string. Clever, Eh? Unfortunately this little "pearl" was the least of their design problems. The whole calculation was represented internally as a tree structure and what do you do when you need a tree structure? You use a TTreeView of course! No need to reinvent the wheel. A good example of what can happen when you turn your mockup or proof of concept into a product without a rewrite.
  16. Anders Melander

    FormStyle in legacy code

    I'll see if I can find time to create a proof of concept for you tomorrow.
  17. Anders Melander

    FormStyle in legacy code

    Okay. But just so you know, it is possible to do without any visual artifacts - but you need to do few things to get it to work.
  18. Anders Melander

    FormStyle in legacy code

    Why shouldn't it be done? I've previously worked on an application where the user, at run-time, could change between MDI and SDI if they wanted to (*). I had to do a few things to avoid flicker but apart from that it worked fine. *) Apparently some user gets confused by MDI and others by SDI.
  19. Anders Melander

    SudokuHelper - Example for uncoupled design via interfaces

    Ah, yes. I missed that. Easily solved though (I think): var FSingleton: ISingleton = nil; function Singleton: ISingleton; const MagicValue = pointer(1); begin if (FSingleton = nil) then if (TInterlocked.CompareExchange(pointer(FSingleton), MagicValue, nil) = nil) then begin // Create instance and reference interface (RefCount=1) var Instance: ISingleton := TSingleton.Create; // Copy interface pointer value (RefCount=1) pointer(FSingleton) := pointer(Instance); // Clear interface reference without ref counting (RefCount=1) pointer(Instance) := nil; end; // Wait for value to become valid while (pointer(FSingleton) = MagicValuel) do YieldProcessor; Result := FSingleton; end;
  20. Anders Melander

    SudokuHelper - Example for uncoupled design via interfaces

    Yes, I originally had a test for nil before the CompareExchange but removed it "for clarity". Why do you say it doesn't work with interfaces? After all an interface reference is just a pointer and the object construction and assignment should take care of the initial reference count. var FSingleton: ISingleton = nil; function Singleton: ISingleton; const MagicValue = pointer(1); begin if (FSingleton = nil) then // Hapy now? :-) if (TInterlocked.CompareExchange(pointer(FSingleton), MagicValue, nil) = nil) then FSingleton := TSingleton.Create; // Wait for value to become valid while (pointer(FSingleton) = MagicValuel) do YieldProcessor; Result := FSingleton; end; What am I missing?
  21. Anders Melander

    Skia versus VCL for plotting points

    Yes, as long as all implementations set pixels via direct memory access then they should perform the same and then benchmarking is pointless. I haven't looked at the new revision to see if that is the case.
  22. Anders Melander

    Skia versus VCL for plotting points

    If you're focusing on performance then you should perform the pixel loop in Y-X order instead of X-Y order. - and replace all the constant divisions with reciprocal multiplications. E.g. x/50 = x * (1/50).
  23. Anders Melander

    SudokuHelper - Example for uncoupled design via interfaces

    Okay. Here goes: You can but don't need to do bit fiddling. We just need to store 3 different states in the pointer; Unassigned Assigned Locked - being assigned It's easy to identify the first two states; If the pointer value is nil then the pointer is unassigned, if it's non-nil then it's assigned. But what about the locked state? Well, for a pointer to an object we can take advantage of the fact that memory allocations are aligned so the lower n bits will always be zero and can be (mis)used to store a lock flag. However since it's a pointer we can just as well just use a pointer value that are known never to be returned by the memory manager. For example ordinal 1. var FSingleton: TSingleton = nil; function Singleton: pointer; const MagicValue = pointer(1); begin if (TInterlocked.CompareExchange(FSingleton, MagicValue, nil) = nil) then FSingleton := TSingleton.Create; // Wait for value to become valid while (FSingleton = MagicValuel) do YieldProcessor; Result := FSingleton; end; Now you're mixing two different arguments. I'm not opposing full pointer exchange. I'm opposing the optimistic object instantiation (which presumably will cause a lock in the memory manager but regardless will be costlier than doing an explicit lock).
  24. Anders Melander

    Hot Reload in Delphi?

    I don't think we're talking about the same.
  25. The entry point is the begin...end block in the dpr file. You can instantiate whatever you want from there. The default is to create the mainform (and whatever "autocreate" forms/modules you have configured) in there. The first form to be created with Application.CreateForm becomes the main form. If you don't want a main form then just don't use Application.CreateForm. Oh, and btw, Application.Run is the message loop.
×