Jump to content

Leaderboard


Popular Content

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

  1. This is probably the best example I've seen on proper use of the parallel libs and how to keep the UI responsive and updated (on multiple platforms). It doesn't cover all the corners of the parallel lib - but it is an excellent example of how beautifully simple multithreading can be.
  2. Developer: "So, about this mockup presentation I did yesterday: Are we going forward with this project?" Manager: "You mean that program you showed us yesterday? Of course we're going forward! It looked pretty much finished. How much time do you need to polish it a bit so we can put it into production?" Developer: head -> desk
  3. Ian Branch

    Build 3715 fails for D2007.

    Hi Thomas, 2007 fails per below. D10.4.2 & D11 are OK. Regards, Ian
  4. Achim Kalwa

    Menu captions with images are hard to read under Windows 11

    Embarcadero has fixed the menu font color problem in V11 update 2. I really would like to know why Microsoft discarded the well-looking menu colors from Windows 10 and now uses the Windows-2000-colors for menus. And the selection bar height is 2 pixel too small on Windows 11, which makes font decenders difficult to see. At least Microsoft has "fixed" the bar height on recent Windows 11 builds.
  5. Lajos Juhász

    Simple JSON parsing

    You're missing not in the if statement (you would like to continue in case when the JSON is correct): var Text: string; Command: string; JsonValue: TJSONValue; JsonValueArg: TJSONValue; begin // parse json JSONValue := TJSONObject.ParseJSONValue('{"cmd":"program.add.text", "txt":"for I := 0 to 100 do"}'); if not (JSONValue is TJSONObject) then Exit; // gets command type (in Command I've found the "cmd" value "program.add.text". ALL RIGHT!!!) if not JSONValue.TryGetValue('cmd', Command) then Exit; // gets command argument txt (does not found the "txt" value and program EXITS!!!) if not JSONValue.TryGetValue('txt', Text) then Exit;  //...
  6. David Schwartz

    SudokuHelper - Example for uncoupled design via interfaces

    I'm reading this debate and it triggers a lot of memories from a project I led in the first job I had out of college. I also searched for that TInterlocked.CompareExchange function and found quite an interesting discussion on SO that reminded me that we're really lucky there was a bug in Intel's 80286 chip that killed their protected-mode OS efforts and actually derailed their whole segmented memory architecture. I hope some of you enjoy this. For the record, this all happened in the 1979-86 time-frame. There's also something useful here related to this thread. ================================================================ In my first job out of college, I was hired to work at an Intel facility that created and built their line of Single Board Computers (SBCs) that used their MultiBus backplane. (It was an industrial design; most people are familiar with the analogous but much simpler S-100 bus that IBM introduced in their PCs.) I was assigned a simple project one day: to write a driver for their 8-bit real-time embedded OS (RMX-80) that ran on an SBC with an 8-bit CPU (8080 or 8085) and talked with another SBC that simply had four UARTs on it (UARTs are 8-bit serial communication devices, aka "comm ports") used for RS-232 connections. The code itself had to fiddle with things via the IN and OUT instructions because Intel's chips infamously did not do memory-mapped IO like Moto's 6800, or the 6500 used by Woz in the first Apple computer. I talked with a hardware guy and was assured this was safe to do because the MultiBus ensured one clock cycle atomicity. So we could have an 8080 or 8085 board with any number of these 4-port serial controllers plugged in, and run IN and OUT (single-byte I/O) instructions to get and fetch data from/to each UART on each serial card using different 'ports' and there would be no need to deal with locks. YAY! One weekend, some guy in Marketing started noodling around and made a grid with all 27 of the boards we made and that were in development listed along the X and Y axes, and in the intersecting cells he made an 'X' if it made sense for the two boards to communicate. Then he decided it might be a Good Idea to make this a more generic solution and took it to a Product Planning Committee. A couple of weeks later, I was informed that my "simple" project had just been considerably expanded. It was renamed "Multibus Message Exchange" or "MMX" for short. And yes, if "MMX" seems familiar, it was recycled years later for something completely different. The original thing got absorbed into their OS designs and eventually became obsolete. Here's where it gets interesting (and quite boring if you're not familiar with computer hardware)... We had SBCs that had a variety of CPUs on them: 8080, 8085, 8086, 8088, 80286 (in development) and 80386 (still being defined). Each CPU has two busses: an Address bus and a Data bus. The 8080 and 8085 had 8-bit busses for both. The 8086 and 8088 had a 16-bit Addr bus; the 80286 had a 20-bit Addr bus; and the 80386 was planned to have a 32-bit Addr bus. Meanwhile, the 8080, 8085, and 8088 had an 8-bit Data bus; the 80286 had a 16-bit Data bus; and the 80386 had a 32-bit Data bus. The Multibus had both 16-bit Data and Addr busses. With the pending design of the 80386, they widened the Multibus to support 32-bit Data and Addr busses. Some of the boards also had 8048 MPUs on them (the chips that were in early PC keyboards) that were also 8-bit devices, eventually replaced with 8051 chips. Also, some had "shared memory" on them, which was a big block of memory where the address on the outside looking in (from another board with a larger address space) was almost always different than what the code running on that board's CPU saw on its end. If you're keeping score of combinations, we're at a pretty big number for such a simple idea. This thing that started out as a simple little project now had to support the ability to send messages from one OS on one CPU to a possibly different OS on a different CPU; sometimes using shared memory that had a different address range on either side; where they both could have different sized data and address busses; and the MultiBus backplane itself could not be locked for more than one clock cycle. They were working on a "smart 4-port UART" board that had an 8085 controlling the four UARTs and 16 KB of shared memory. The 8085 had a 16-bit (64KB) address space, but the OS ran in a ROM that was hardwired to the first 16KB because when you grounded the RESET pin momentarily, it reset the CPU and set the IP to start executing at address 0. Needless to say, when you had a 16-bit or 32-bit data bus on one side and the other only had an 8-bit data bus, this caused a problem because the data could only be seen one byte at a time on one side, but it was 2 or 4 bytes wide on the other. It was also impossible to pass pointers between boards with CPUs on both sides. This made memory-mapped I/O highly problematic, which I think is one reason Intel went with the IN and OUT instructions instead. This mess was due in part to the fact that the MultiBus only had one clock cycle atomicity. We could not write 16-bit or 32-bit values to a shared memory address and ensure they would be received without getting corrupted because the shorter receiving side had to do multiple reads, which toggled the MultiBus' clock with each read. (Until this point, the engineers had no reason to design an 8-bit board to read 16- and 32-bit wide data and multiplex it into a series of 8-bit data bytes.) <sigh> If anybody remembers the old "small", "medium", "large", and "compact" memory models in old Intel compilers, this is part of what those designations were intended to address. It was a frigging nighmare. Those model designations first showed up while I was working on this project, and we got an updated compiler with a note about this apologizing that it was the only way to deal with the segmented memory model in the 80286 other than forcing everybody to use the same model, which was totally unworkable. We BEGGED the engineers in charge of the Multibus to add an explicit LOCK signal to it so boards with mis-matched data and/or address busses could have something to ensure that an INTEGER of ANY WIDTH could be transferred atomically across that damned bus that they loved to extoll was "the most advanced bus in the industry!" We succeeded in getting the Product Planning Committee to take it up for discussion, and they agreed, but they chose not to go back and fix any existing boards -- it would only be implemented going forward. Meaning we were stuck having to deal with that mess on all of the existing board combinations they decided needed to be supported. Ugh. --------------------------------------- I did a ton of research and stumbled upon something that someone at IBM had just published in one of their journals that seemed to anticipate our exact situation. It was a short article that simply explained a reliable way of building a lock or semaphore without any hardware support. All it required was an atomic TestAndSet that worked on both sides with at least one bit. We had atomic byte-sized TestAndSet operations that worked everywhere, so that's what we used. TestAndSet reads the value of a memory location and returns its value, and writes a 1 into that location, in a single atomic uninterruptible action. Most semaphores issue a lock, try to grab a flag, then either proceed or release the lock and try again. In this case, a lock isn't needed. It's done through a protocol that everybody follows. You do a TestAndSet, and if the value returned is 1 then you sleep for a bit and retry until you get it. If you get a 0, then you do it again on a second location. If you get back a zero the second time, then you have a green light to proceed. If not, you clear the first flag, sleep a bit, then try again with the first flag. When you're done, you clear the second flag, then clear the first flag. For us, this was like cutting the Gordian Knot! (The paper went into a bunch of details about why this works realiably. I don't recall them.) ========================================================================= PS: if you're read this far, I'll let you in on a little secret related to this that very few people know about the history of the 80286 and the bug that kept it from working in protected mode... The 80286 architecture was created by some guys from Honeywell that were trying to build a simplified version of their Multics secure computing system. Part of the magic was that the OS had some support in the hardware. Our OS guys worked closely with the chip designers to ensure that the 80286 chip supported all of the magic stuff that the OS needed to be secure. They had a big meeting and everybody signed off on the chip design and the chip guys went off to build it while the OS guys started working on the fancy new OS. I was hired a few months after that meeting to work on that very OS. Our hardware guys had been working in parallel to design a MultiBus SBC that they could drop the 80286 chip into and it should just work. For new chip designs, Intel would first create an In-Circuit Emulator (ICE) that they'd use for hardware testing. We got some of them and they worked properly as expected. But when we finally got the first prototype chips, they failed some tests. We sent the results back to the chip guys and were told "we're working on it" for months. We got back a couple more iterations of 286 chips and they fixed some problems, but one seems to persist. Apparently, after the final meeting and agreement on the chip design, the chip guys built the ICE units based on that design, but then decided to optimize something in the microcode and made some changes in the on-chip wiring that simplified a bunch of other logic, and they never ran it by the OS team. They also didn't update the ICE unit's design to reflect these changes, believing they were simple "refactorings" that would have no side-effects. They kept dodging the OS team's attempts to meet and help with this. When the OS team finally got their hands on the T-Spec, they went ballistic, because the chip guys basically broke the security model with their "refactoring". Seems that what they did caused the CPU's Stack PUSH instruction to be non-atomic when the chip was running in "protected mode". Meaning that if an interrupt came in while an address was being pushed onto the stack, it could be interrupted after the segment register (16 bit base index) was pushed onto the stack, but not the 16 bits (offset part) of the IP -- because they came from different registers. The result was that when the interrupt popped the return address off the stack, it got the segment register value, but the next word was NOT the IP address. Obviously, it went off into the weeds and typically generated an address fault. Unfortunately, they decided they couldn't fix it without delaying the chip's release by 6 months or so. That was getting too close to the release of the next chip, the 80386, so they decided to accelerate the release of the 80386 instead and wave-off use of "protected mode" in ALL 80286 designs. (Customers were not happy!) In fact, IBM and some other companies (besides us) had been working very diligently to build a secure OS that was supposed to run on the 80286 in "protected mode". But the 286 never worked in "protected mode" because they never fixed this problem. When we released the 80286 chip, IBM and others sold an upgraded OS that ran on it, but not what they had planned. The 80386 was released earlier, but nobody ran it in "protected mode" either because that required the segmented memory model which everybody HATED. The 80386 was supposed to have a bunch of new features, and only ended up with a few in order to get it out the door faster. But the one that captured the industry's attention the most was its support for a "flat memory model". That was the point where Intel threw in the towel and shifted entirely to a "flat memory model", doing away with all of those crazy "small", "medium", "large", and "compact" compiler models and all of that nonsense that came with a segmented addressing scheme. (Never mind that it was actually modeled after IBM's mainframes, which is one reason IBM loved its design.) Ok, now get back to work!
  7. A very long time ago and what feels like a far off galaxy A very long time ago and what feels like a far off galaxy A very long time ago and what feels like a far off galaxy A very long time ago and what feels like a far off galaxy A very long time ago and what feels like a far off galaxy..... I was part of a small team than wrote accounting software for our UK and international customers. All the prices, totals, decimal quantities, fractional quantities were represented as integers or long integers. The long integers having 15 digits of significance; not a floating point number in sight. All decimal places and fractial separators were implicit until it came to displaying them. No rounding errors crept in. I remember this as an example of a good design choice by the lead developer.
  8. Lars Fosdal

    Parnassus Bookmarks for Delphi 11 Alexandria?

    I was signed up but didn't have time to watch it - when I tried some of the interesting replays, they were not working. Why don't they do a blog post about it and indicate a timeframe for availability? In a way, it is good that they have HighDPI issues since that means proper dogfooding, but I fear that we will be talking about update 1, and not a December hotfix. Judging from all the HighDPI issues I've seen discussed, the right thing to do would be to break the mold and do it right. The current approach with kludges and workarounds = tech debt++.
  9. Serge_G

    Custom ListBox Layout in fmx

    I had this problem long time ago but don't remember how I manage it! Indeed, a test with D10 reproduces this behavior (I only had to change a few lines of your program, and use default style removing default, renaming windows 7 to blank -> default). If you read French (google trad can be a friend), I wrote a tutorial long time ago (https://delphi.developpez.com/tutoriels/firemonkey/intro-styles-firemonkey-xe4/). Ideas : Try yo use standard stylenames i.e. txt,icon (especially this one) mystyle : here icon and text can be accessed via ListboxItem.StylesData['txt']:='Data hello'; ListBoxItem.ItemData.Bitmap.LoadFromFile('D:\XE8\icons8-planète-terre-48.png'); As you can see, stile using findstyleresource coding it works better (only speedbutton hidden) but if you code (here, I test my new style) ListboxItem.StylesData['button.text']:='Data btn'; ListboxItem.StylesData['speedbtn.text']:='speed btn'; instead of sequence // Itembtn := ListBoxItem.FindStyleResource('button') as TSpeedButton; // if Assigned(Itembtn) then // Itembtn.Text := 'Btn Hello!'; the whole stuff works as expected. Nowadays, I use more often Listview (dynamic appearance) than ListBox, Writing this other tutorial, I bang another time in this "empty object problem" I override also playing with link (disabling/enabling) and not only with the BeginUpdate/EndUpdate. However I never tested with the new versions to find out if this potential bug had been fixed.
×