Jump to content

Anders Melander

Members
  • Content Count

    2771
  • Joined

  • Last visited

  • Days Won

    147

Everything posted by Anders Melander

  1. Anders Melander

    Component with sub-property event

    Decoupling. In this case the events belongs in the sub-property objects. They do not concern the main component. I understand what you are saying but IMO that view is driven by the fact that we are talking about "components" which is a RAD thing, thus design-time stuff, monolithic design and so on. I'm designing this like I would if there was no design-time to influence things. If I hadn't gotten this to work then the events simply wouldn't have been accessible at design-time. In fact, at the moment the sub-properties are objects that are statically created by the component. The next stage is to make the class type of the objects dynamic and configurable at design-time. And then there's no way I could expose those event on the component because they wouldn't be known at compile-time. So instead of a single class that handles many different button styles (like I have now - see screenshot): property ButtonOptions: TButtonOptions read FButtonOptions write SetButtonOptions; I will get one class for each button style: property ButtonOptions: TCustomButtonOptions read FButtonOptions write SetButtonOptions; property ButtonOptionsClass: TButtonOptionsClass read FButtonOptionsClass write SetButtonOptionsClass; and each class will expose the properties that are relevant to that style.
  2. Anders Melander

    Component with sub-property event

    I have a component which contains sub-properties; I.e. a component property which is itself an object that contains its own properties. The object is derived from TPersistent and one of its properties is an event. The problem I'm having is getting this event to appear in the object inspector. I'm pretty sure that I had it working at one point but whatever I've tried now I can't get the event property to appear in the OI. FWIW, it works without problems in the Lazarus IDE. I've looked through the source of the few ToolsAPI units we have available but I haven't found any clues there. As far as I can tell it should work. So what am I missing? The following source reproduces the problem: unit FooBar.Reg; interface uses Classes, DesignIntf; type TTestSub = class(TPersistent) private FOnEvent: TNotifyEvent; FTest: string; public procedure Assign(Source: TPersistent); override; published property Test: string read FTest; property OnTestEvent: TNotifyEvent read FOnEvent write FOnEvent; end; TTest = class(TComponent) private FSub: TTestSub; procedure SetSub(const Value: TTestSub); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property Sub: TTestSub read FSub write SetSub; end; procedure Register; implementation procedure Register; begin RegisterComponents('FooBar', [TTest]); end; { TTest } constructor TTest.Create(AOwner: TComponent); begin inherited; FSub := TTestSub.Create; FSub.FTest := 'Hello world'; end; destructor TTest.Destroy; begin FSub.Free; inherited; end; procedure TTest.SetSub(const Value: TTestSub); begin FSub.Assign(Value); end; { TTestSub } procedure TTestSub.Assign(Source: TPersistent); begin FOnEvent := TTestSub(Source).OnEvent; end; end.
  3. Anders Melander

    Component with sub-property event

    Don't worry. I'll post a link once it's ready for consumption but it's too much to post inline here. In short it involves declaring a placeholder property on the top level class registering a dedicated property editor for this property which in turn redirects to the actual sub-property and then enumerates the delegates/events of that object to create TNestedProperty property editors for each of them.
  4. Anders Melander

    Component with sub-property event

    Okay, so I got it working using the same method as DevExpress: The code required is pretty crazy. I'll post a link to it once it makes into the Graphics32 repository. Functionality like this is really something that ought to be standard.
  5. Anders Melander

    Component with sub-property event

    Yes, I know I could just use TComponent but nope; I'm not letting a deficiency of the IDE dictate my class design.
  6. Anders Melander

    Component with sub-property event

    Ohwaitamoment! I think DevExpress use a custom property editor to get the events listed. I'll investigate.
  7. Anders Melander

    Component with sub-property event

    Most of DevExpress' controls beg to disagree: The sub-properties are derived from TPersistent...
  8. Anders Melander

    Component with sub-property event

    Already tried that; Made no difference.
  9. Yes it does - but map2pdb just produces the pdb files required by the profilers. Profilers that works with pdb files includes Intel VTune and AMD μProf. I believe μProf works with both Intel and AMD processors while VTune only works with Intel processors but use the one that matches your processor to get the most precise results. I use VTune myself. Ask if you need instructions on how to get started. The process is very easy once you know how to do it but it can be challenging to get to that point 🙂
  10. Anders Melander

    Rapid.Generics revamp

  11. Yet you did. If you couldn't remember where you got the code from then you simply shouldn't have posted it without proper attribution. As it is now the code is nearly identical so it's not just "inspired" or "influenced". That's not a problem in itself, it's open source after all, but you have to at least keep the original license which is "MPL 1.1 or LGPL 2.1 with linking exception". I've created an issue at your repo to get that fixed.
  12. Anders Melander

    Realy ?

    In other news, Lazarus, the North Korean hacker group has released a statement saying it would be better for them if people would please click on the link in that email ebay has just just sent them asking to update their account details. "There's too much mistrust in the world today" said Park Jin Hyok, a spokeperson for Lazarus. "Just click it, godammit".
  13. For benchmarking, sure. But otherwise I would think it would be better to let Windows manage that. That code sure does look a lot like this one... https://github.com/graphics32/graphics32/blob/4fbc8d2a3083e42a00ca776eaa52af7cab2de34a/Source/GR32_System.pas#L399
  14. Do you really need reentrant locks? If not then just use the standard version. There's no need to complicate thing further. Also MREW only makes sense if you have more readers than writers. For single writer & single reader there's no reason for it. As I read it you are considering using a pool of reader in which case MREW might very well make sense (or "just" use a lock free queue). Btw, if you don't need to process the work packets "in order" then things become a little easier since a lock-free stack is often simpler to implement than a queue. A PWideChar doesn't necessarily mean that the source string is a Widestring. It would very well just be a pointer to regular unicode string. It's just not common to explicitly use PWideChar anymore since it is the same as PChar on unicode Delphi. Regardless, the message was more that you should avoid WideString unless you have a reason to use it. You can't really do anything about what your external lib uses internally. Good luck. You have many hours of debugging ahead of you 🙂
  15. I didn't investigate but I got a lot of leaks reported when existing the application when running in the debugger. Okay. It's expensive to start a thread but if you are launching the threads at application startup then it doesn't matter. If you create them on-demand then I would use TTask instead. The first task will take the worst of the pool initialization hit. https://en.delphipraxis.net/search/?q=profiling If you use a lock-free structure then you don't need locking. Hence the "free" in the name 🙂 And FTR, the term deadlock means a cycle where two threads each have some resource locked and each is waiting for the other to release their resource. I think what you meant was race condition; Two threads modifying the same resource at the same time. PWideChar is supposedly a pointer to a WideString? In that case, please don't. WideString is only for use in COM and it's horribly slow. No, what I meant was that instead of using dynamic strings (which are relatively slow because they must be allocated, sized, resized, freed, etc.) use a static array of chars: Buffer: array[BufferSize] of char. You will waste some bytes but it's fast.
  16. Anders Melander

    Rapid.Generics revamp

    Did you read the text you just quoted?
  17. Yes. For one you are running all the tests concurrently which means that you will be penalizing the tests that start later because they will be competing for CPU against the test that are already executing. Execute each test and wait for it to finish before you start the next test. You also seem to have massive memory leaks which probably means that some of the test have an unfair advantage because they don't consume time releasing their resources. If you are using thread pools (I'm not sure that your are (if not, you should be)) then you should ensure that the thread pool has been spun up before you start the test. Otherwise you will penalize the first threads with the startup overhead. Instead of just looking at the time from start to end and then guessing about why it is fast/slow/whatever, profile your code so you can see exactly where the bottlenecks are. Do this for each individual algorithm in turn. Apart from that, for something as simple as this, you don't need locking and you definitely don't need to use the Windows message queue as a work queue. Use a simple lock-free fifo queue instead. You could even use a fixed size lock-free ring buffer (just an array of records with two integer values as in/out indices). The fixed size buffer and the records would eliminate the allocation overhead of the queue itself. You should probably also try to eliminate the use of string and replace it with fixed size buffer if possible.
  18. Anders Melander

    Rapid.Generics revamp

    I really think it's more a question of lack of expertise, limited resources, and priorities. I think they would if they could but since they can't communicate that to the customer they instead come up with excuses that comes across as if they don't care.
  19. Anders Melander

    When will we have a 64-bit IDE version ?

    https://en.delphipraxis.net/search/?q="Delphi 12.3"&sortby=newest&search_and_or=or&page=1
  20. Anders Melander

    Rapid.Generics revamp

    Thanks for explaining that to me. Now I understand everything exactly like I did before. I don't have any code where anything in system.generics.collections or system.generics.defaults is anywhere near the bottleneck Better?
  21. Anders Melander

    Rapid.Generics revamp

    Nice! Unfortunately I don't have any code where generics is anywhere near the bottleneck or I would have had a go with it.
  22. Anders Melander

    Rapid.Generics revamp

    It looks to have the same interface but jeez it's a lot of code to maintain.
  23. Use an interposer for TDataModule. The datamodule base class (no DFM): unit Foo.Bar; interface uses Classes; type TBaseDataModule = class(TDataModule) private FFoobar: integer; public property Foobar: integer read FFoobar write FFoobar; end; implementation end. Your datamodule: unit Whatever; uses Classes, etc. etc., ... Foo.Bar; type // The interposer // You could have declared it in the Foo.Bar unit but I prefer to declare it explicitly // everywhere it's used to make it clear what is going on. TDataModule = TBaseDataModule; // Your regular TDataModule stuff type TMainDataModule = class(TDataModule) ... end; etc.
  24. Anders Melander

    formatting private const identifier = value

    Me too - and I would most often also start with the class vars and types. Of course it depends on the size and structure of the class; For a large class I would probably try to keep associated stuff close together as an overriding principle.
  25. Anders Melander

    formatting private const identifier = value

    type TClass = class(TObject) private FSomeField: integer; private const SomeConstant = 5; private type SomeType = integer; private class var SomeClassVar: integer; end; etc. etc.
×