Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 12/28/21 in all areas

  1. I've heard about the Omni Thread Library for years, authored by Primož Gabrijelcic, but have never more than glanced at it. Most of the examples I've seen have been fairly basic, and I didn't have any reason to suspect it might be more than what you find in Delphi's PPL. Boy, I couldn't have been more wrong! It took an amazing amount of digging around to find stuff, and after all of this I thought it would be helpful to memorialize my discoveries here for everybody to see. This is truly a remarkable piece of work. The library itself is FOSS, and Primož has posted stuff in his blog about it over time -- which spans 10 years now! It's a LOT of material to go through. You can get the latest source code (V3.07.9) on github here: https://github.com/gabr42/OmniThreadLibrary The version in GetIt is a bit outdated (3.07.7) Rather than publish a detailed Help guide or online resource, he chose to publish a book that can be purchased here: https://leanpub.com/omnithreadlibrary NOTE: you can get the book + the 3 webinars described later for even less than it says below at the LeanPub link. For the record, I don't particularly like digging through source code trying to figure things out, so I started hunting around for other resources. I found a recording (33 min) of CodeRage talk he gave at CodeRage 6 in 2011, and a free replay (MP4 download) of it can be found here: https://cc.embarcadero.com/item/28591 I watched that video and discovered that this is an UTTERLY AMAZING treasure trove of material, and it covers things I never imagined to see! It actually has seven (7) high-level abstract APIs (if you will) that really surprised me to see -- I'd figured it was mostly just the first few that are found in most threading libraries. * Async -- start a background task and continue -- this is similar to, yet more than what Delphi's PPL does * Future -- start background task, do some work, then wait to retrieve the result * ParallelTask -- start multiple copies of one task (for background procesing) and then wait for them all to complete * Join -- start several different background tasks and then wait for them to complete * Fork/Join -- do a divide and conquer, in parallel * ForEach -- perform a parallel iteration over an integer range, or on the contents of any container with built-in iterators (ie, that support for-in) * Pipeline -- run a multi-stage process I found a post here referring to an article using Deplhi's TCountdownEvent that has a bunch of code that does what Fork/Join does in just a handful of lines of code. What really blew my socks off were the ForEach and the Pipeline methods. I wanted more and kept digging.... eventually I found this: https://thedelphigeek.gumroad.com There you can find three hour-long tutorial videos on all of those high-level APIs. The link I found only went to the first video. I took a wild guess and found #3 that had the info on ForEach and Parallel, which is what I wanted, and bought that one. They're $10 each. Later I found out you can get all three for $25. ** EDIT: you can get these with the book at the LeanPub link above for just $5 more. NOTE: I'm mentioning this stuff here because it's so damn hard to find these things anywhere! You'll never find them searching for the term "video" because they're only referred to as "webinars". The couple of links I found on his blog specifically for these VIDEOS were dead and the ones in another place were wrong. I only found these because of one very brief and cryptic reply to a random question way down on one blog entry from 2015. I didn't notice them on LeanPub because I wasn't looking for "webinars". I started this search because I've been going around in circles trying to figure out the best way to deal with a collection of data displayed in a TListView with some data objects attached to the ListItems' .Data property, and I want to allow the user to hit a "Go!" button and have the code process the whole lot in parallel. They need to issue a bunch of REST service calls, so mostly they're just sitting idle waiting for replies, and I suspect they can all complete in the time it takes for the longest one to run. It turns out the ForEach<T> lets you iterate over the Listview's Items property using it's existing Iterator, and pass each TListItem into an anonymous Proc (by type!) and process it directly -- with each one running in parallel. You can easily do something when each of those threads finishes running, and also when the entire list is processed, all without having to send messages or go through crazy contortions to effect a fork/join operation. It's all handled invisibly. WHOA! The Pipeline abstraction is really something to behold. Many years ago I spent 9 months building a system that implemented a multi-step pipeline process that literally was spread out over a half-dozen different PCs on a LAN. Today they could all be done on one multi-core CPU, and using this bit of code would let me build it in less than a week (assuming all of the component parts were already working). In fact, i've built a few other systems that could have benefitted from this abstraction as well. And I can think of one coming up that might be able to use it. In summary ... maybe a lot of folks discovered this library when it was first published in 2010, but it seems to have virtually disappeared aside from an occasional mention in comparison to Delphi's Parallel Processing Library. Personally, I don't even think they're comparable. If you've never looked at it and are doing parallel programming stuff, take a look. And if you're famliar with it but may not have remembered all it does, give it another look and see if there's anything new worth studying. BTW, one thing that it had been criticized about was no way to Cancel threads in several places; the latest version (3.07.9) that's on github fixes that. It's relatively new, and not in the GetIt version.
  2. How about this Project?
  3. vfbb

    Your Delphi verion does not support COMMAND

    Fix: I think he meant below Professional (Starter, Community and Trial). I looked at each Feature Matrix of the RAD Studio versions and questioned him, the compilation via command line feature varies a lot from version to version including from update to update. Some in the Starter edition only have the command line for Win32, others not even for Win32.
  4. Vincent Parrett

    Omni Thread Library resources

    I've been telling anyone who would listen for years that Omni is the best thing since sliced bread. We use it in the stepping engine in FinalBuilder. Some of the low level stuff is hard to grok though, I struggle with it when I haven't worked on it for a while, but the high level stuff is simple to use.
  5. // Return child form of a given class. Create new form if not in Components list yet function TfrmMDIMain.GetChildForm(ChildFormClass: TFormClass): TForm; var i: Integer; begin // Seach by class // Not via MDIChildren because there are non-MDI as well (frmReport) for i := 0 to ComponentCount - 1 do if Components[i] is ChildFormClass then begin Result := TForm(Components[i]); Exit; end; // create new if not found. Owner is set so child form is destroyed automatically on close Result := ChildFormClass.Create(Self); end; // Sample usage - specific init procedure TfrmMDIMain.NPersonsIndexClick(Sender: TObject); begin with TfrmPersons(GetChildForm(TfrmPersons)) do begin SetPersonType(TPersonType(-1)); BringToFront; end; end; // Sample usage - no explicit init procedure TfrmMDIMain.NSpecsIndexClick(Sender: TObject); begin GetChildForm(TfrmSpecs).BringToFront; end; Here's how I do it in my MDI app (DB client with several UIs for table editing). Note that there could be only one form of a particular class. Also closed forms remain in memory thus consuming resources - not an issue in my case but a subject to note. As for modal windows, I don't bother excess lines and just use procedure TfrmMDIMain.NImportClick(Sender: TObject); begin with TfrmImport.Create(nil) do try ShowModal; finally Free; end; end; I also extend TForm class with some customizations and derive child forms from it without the need to install this as component by magic type override trick: // Form with common actions on create and close: save/restore size, ctx help, zoom etc TCustomMDIChildForm = class(TForm) procedure DoCreate; override; procedure DoClose(var Action: TCloseAction); override; end; and FormSmth.pas: // magic! TForm = TCustomMDIChildForm; TfrmSmth= class(TForm) ... end;
×