Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 04/17/20 in all areas

  1. David Heffernan

    The interfaces in Delphi are bad?

    Is it unreasonable to expect that programmers have knowledge and skill?
  2. David Heffernan

    The interfaces in Delphi are bad?

    That post is worthless. Best to ignore it.
  3. A.M. Hoornweg

    The interfaces in Delphi are bad?

    I use interfaces all the time, and there are simple ways to make existing classes support interfaces with or without reference counting, without having to derive from a common base class like tInterfacedObject. If I want to modify any class in such a way that it supports interfaces without reference counting, I simply add dummy methods _AddRef, _Release, and QueryInterface: Type tNewObject = class(TOldObject, IInterface) protected // IInterface function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end; function tNewObject._AddRef: Integer; begin Result := -1; end; function tNewObject._Release: Integer; begin Result := -1; end; function tNewObject.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := S_OK else Result := E_NOINTERFACE; end; And similarly, it is possible to make any existing class support interfaces with reference counting, it just takes a few more methods: TNewObject = class(TOldObject, IInterface) protected FRefCount: Integer; function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; public procedure AfterConstruction; override; procedure BeforeDestruction; override; class function NewInstance: TObject; override; property RefCount: Integer read FRefCount; end; procedure TNewObject.AfterConstruction; begin // Release the constructor's implicit refcount InterlockedDecrement(FRefCount); Inherited; end; procedure TNewObject.BeforeDestruction; begin if RefCount <> 0 then Error(reInvalidPtr); Inherited; end; // Set an implicit refcount so that refcounting // during construction won't destroy the object. class function TNewObject.NewInstance: TObject; begin Result := inherited NewInstance; TNewObject(Result).FRefCount := 1; end; function TNewObject.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end; function TNewObject._AddRef: Integer; begin Result := InterlockedIncrement(FRefCount); end; function TNewObject._Release: Integer; begin Result := InterlockedDecrement(FRefCount); if Result = 0 then Destroy; end;
  4. I posted a blog article on this topic yesterday: https://www.ideasawakened.com/post/name-your-threads-even-the-ones-auto-created-by-delphi I'm curious how many others do this sort of thing. I think it really comes in handy sometimes. I also went looking for the reasons behind each of the Delphi-created threads, other than the main message loop. Do you have any info on that? I could swear I read an article on it years ago, but couldn't find it.
  5. David Schwartz

    looking for a lo-fi Delphi Style

    A common practice used by lots of web and mobile app devs is to do the basic design work using what's often called a "lo-fi" theme or style. It looks like hand-drawn figures on paper with handwritten lettering. Balsamic is a tool I found that offers this, but there are many others. I like using Delphi for basic prototyping, and I can often build a semi-functional prototype as quickly as graphic artists can build a static wire-frame model in drawing tools. Here's a decent article on the topic that I found with Google's help: https://www.justinmind.com/ui-kits/sketching-web-and-mobile-wireframes-with-justinminds-ui-kit The problem comes when the user sees what appears to be a fully-functional app, and thinks it's nearly finished. Uh, no, it's like a Hollywood sound stage. They can't tell, and I'm hard-pressed to prove it to them. I thought perhaps if there's a lo-fi style for Delphi, I could build something that LOOKS like it's hand-drawn so they don't mistake it for something more complete. Does anybody know of anything like this that's available?
  6. Jacek Laskowski

    Do you name your Threads for debugging?

    Unfortunatelly I don't. When it comes to the order of starting the "initialization" section it's not always the same, it all depends on the uses section, in my case your code is launched before RTL/VCL threads. I bypassed this problem by adding a anonymous thread with delay: procedure NameDelphiThreads(const pMainThreadId : THandle); begin TThread.CreateAnonymousThread( procedure var vSnapshot:THandle; vProcessId:THandle; vTE32:TThreadEntry32; i:Integer; begin Sleep(100); vProcessId := GetCurrentProcessId(); vSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, vProcessId); if vSnapshot <> INVALID_HANDLE_VALUE then begin [...] end; end ).Start; end;
  7. When you have DoS/DDoS protection in apache, for example with the usage of the qos_module, you will see that there will be a lot of failed requests in the output of the command. This happens, because the protection is indeed working and as mentioned, the ab tool basically floods your server with requests, so a lot of requests with the same IP will automatically be blocked by the apache module. Indeed I see that the performance of Delphi apache module or Indy web application, with Firedac and data middleware manipulation, under Linux is brilliant. I wait for the compiler optimization to redo a benchmark.
  8. The handling of PixelsPerInch has changed in recent Delphi versions with High DPI support. This may be the cause of what you see here.
  9. Please provide a minimal project, and describe the display settings on your machine.
  10. Eric Bonilha

    iOS handle incoming url

    @vfbb @Dave Nottage Thank you very much for both of you for your invaluable help. I was able to successfully make the Universal Links within my application. Indeed I had to change Delphi files but I made a local copy of the files and attached to my application (so FMX and RTL source is not changed) and when compiling, the compiler will use my local copy of the modified files and it works like a charm. Hopefully Embarcadero will implement these classes within the RTL in the future
  11. vfbb

    Which component to use as base class for SpeedPanel

    Because your stylelookup is empty and the default stylelookup of the TPanel is the 'panelstyle', and your new component don't have a default style. Just do this: procedure TForm1.InitSpeedPanel(sp: TSpeedPanelClass); var sb: TSpeedButton; begin sp.StyleLookup := 'panelstyle'; // <<<<<<<<< // ...
  12. Whatever function you come up with it will be susceptible to race conditions; After you have determined that the file isn't in use, but before you can open and lock it, another process can come in and open it - or vice versa. Working from Remy's example you need to keep the file open after FileCreate. As soon as the file is closed the test result is stale.
  13. To use a TFileStream just to check if the file is in use, you need to use fmOpenRead instead of fmCreate, and you definitely need to use fmShareExclusive instead of fmShareDenyNone, and note that the file could fail to open for any number of reasons, not all of which are related to the file being in use, so you have to check for that, eg: function FileReallyIsInUse(fName: string): boolean; begin Result := False; try TFileStream.Create(fName, fmOpenRead or fmShareExclusive).Free; except on E: EFOpenError do Result := GetLastError() in [ERROR_SHARING_VIOLATION, ERROR_LOCK_VIOLATION]; end; end; However, the exception doesn't carry the error code, and using GetLastError() after the exception is raised does not guarantee the original error code is preserved. You are better off simply calling the Win32 CreateFile() function directly instead (which avoids the need to allocate an object in memory, or invoke the overhead of exception handling): function FileReallyIsInUse(fName: string): boolean; var hFile: THandle; begin hFile := CreateFile(PChar(fName), GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); if hFile <> INVALID_HANDLE_VALUE then begin CloseHandle(hFile); Result := False; end else Result := GetLastError() in [ERROR_SHARING_VIOLATION, ERROR_LOCK_VIOLATION]; end; Or, the RTL's FileOpen() function: function FileReallyIsInUse(fName: string): boolean; var hFile: THandle; begin hFile := FileOpen(fName, fmOpenRead or fmShareExclusive); if hFile <> INVALID_HANDLE_VALUE then begin FileClose(hFile); Result := False; end else Result := GetLastError() in [ERROR_SHARING_VIOLATION, ERROR_LOCK_VIOLATION]; end;
  14. If everything was as you believed then there wouldn't be a problem. The debugger behavior you describe is the same for all versions and is as expected. If you don't want the OS to switch threads during single step then you need to suspend the other threads in the debugger. But you don't really need to single step to locate the problem. Just repeatedly pause the application when it exhibit the behavior you describe and examine the call stacks of the different threads. Sooner or later you will get a snapshop that reveals the cause of the problem. This simple approach almost always work for me.
×