Korektní ukončení - #35
Conversation
Hnatekmar
left a comment
There was a problem hiding this comment.
Review: #35 — Korektní ukončení (Proper termination)
Author: @Hnatekmar
Verdict: APPROVE ✅ (with reservations on style)
This PR fixes a real termination bug in a D-language genetic algorithm + SFML viewer. Without it, the drawing thread polls at 100ms intervals and the genetic algorithm's termination signal is unreliable.
Findings
source/genetic.d:78 — Suggestion
-receiveTimeout(1.msecs, (OwnerTerminated own) { running = false; });
+receiveTimeout(-1.msecs, (OwnerTerminated own) { running = false; });Changing from 1.msecs (non-blocking poll) to -1.msecs (blocking wait with timeout meaning "wait forever") is a behavioral change. The intent is "block until owner terminates" — that requires using receive (blocking, no timeout) rather than receiveTimeout(-1.msecs, ...). receiveTimeout with a negative duration may be interpreted as "no timeout" by some D implementations and as "immediate return" by others. Use receive instead:
receive((OwnerTerminated own) { running = false; });This is unambiguous and self-documenting.
source/app.d:99, 105 — Suggestion
send(ownerTid, true);Added to both gaCircle and gaRectangle. Good — the drawing thread needs to know when each GA worker is done. But the drawing thread's receiveTimeout handler at line 139-142 only sets stop = true; it doesn't distinguish which worker finished. If only one worker finishes (and you have multiple running), the drawing thread still exits. Probably fine for this app's intent ("stop when any worker done") but worth a comment.
No tests
D projects often lack test infrastructure entirely, and this one doesn't appear to have any. Hard to demand tests, but at minimum consider a unit test that:
- Spawns a GA worker.
- Calls
send(ownerTid, true)from a mock worker. - Verifies the drawing loop's
stopflag transitions correctly.
Notes
- This is an old PR (opened 2017-06-24, last touched 2026-04-10). If the project is no longer maintained, feel free to close it.
- The D ecosystem has changed significantly since 2017. Verify the project still builds against current
dub/ DMD / LDC versions before merging.
|
probe |
Review: #35 — Korektní ukončení (Proper termination)Author: @Hnatekmar This PR fixes a real termination bug in a D-language genetic algorithm + SFML viewer. Without it, the drawing thread polls at 100ms intervals and the genetic algorithm's termination signal is unreliable. Findings
-receiveTimeout(1.msecs, (OwnerTerminated own) { running = false; });
+receiveTimeout(-1.msecs, (OwnerTerminated own) { running = false; });Changing from receive((OwnerTerminated own) { running = false; });This is unambiguous and self-documenting.
send(ownerTid, true);Added to both No tests D projects often lack test infrastructure entirely, and this one doesn't appear to have any. Hard to demand tests, but at minimum consider a unit test that:
Notes
|
Hnatekmar
left a comment
There was a problem hiding this comment.
Review: Hnatekmar/GeneticAlgorithm #35 — Korektní ukončení (Proper termination)
Verdict: COMMENT
Summary
This PR adds proper termination signaling to the genetic algorithm visualization:
- Sends
send(ownerTid, true)aftergaCircle()andgaRectangle()complete - Adds a
stopflag in the drawing thread that listens for a signal viareceiveTimeout - Closes the window and breaks the render loop when the stop signal is received
- Re-indents some code blocks (whitespace changes)
Observations
- The
send(ownerTid, true)pattern correctly signals completion to the owner thread. - The
stopflag mechanism in the event loop properly handles graceful shutdown. - The whitespace re-indentation (tabs → spaces or alignment changes) improves readability.
- Potential concern (Minor): The
stopflag could technically be a race condition since it's set in the receive handler and read outside — however, in D's single-threaded event model this should be safe. - Nitpick: The variable
stopis inconsistent with the PR title language (Czech vs English). Consider naming itzastavitor keeping the English convention used elsewhere.
Code Quality
- The termination pattern follows D's actor-model idioms correctly.
window.close()followed bybreakensures clean exit no matter which one would trigger cleanup.
No blocking issues. The PR correctly addresses the "proper termination" requirement.
|
Bruh |
Hnatekmar
left a comment
There was a problem hiding this comment.
Review: #35
Verdict: REQUEST_CHANGES
Warning: Potentially blocking timeout change
File: source/genetic.d, line 61
Severity: Warning
What's wrong: receiveTimeout(1.msecs) is changed to receiveTimeout(-1.msecs). In D's std.concurrency, a negative timeout means "no timeout" — the call blocks indefinitely until a message arrives. The original 1.msecs made it a non-blocking poll. With -1.msecs, if no OwnerTerminated message is sent (e.g., the owner thread doesn't properly signal), the genetic algorithm loop will hang forever instead of eventually terminating.
Fix: If non-blocking polling is desired, keep 1.msecs or use Duration.zero. If the intent is to wait for termination, ensure the owner always sends OwnerTerminated before joining.
Good: Proper termination signaling
The rest of the PR (sending true via send(ownerTid, true) in gaCircle and gaRectangle, checking stop in drawingThread) adds clean termination flow for the drawing window. These changes look correct.
Hnatekmar
left a comment
There was a problem hiding this comment.
Test review\n\nTesting write access on personal repo. Please ignore.
Hnatekmar
left a comment
There was a problem hiding this comment.
Review: #35 — "Korektní ukončení" (Proper termination)
1. File: source/genetic.d:78
Severity: Warning
What's wrong: receiveTimeout(-1.msecs) changes from a 1ms non-blocking poll to an infinite blocking receive. If the sender (OwnerTerminated) never sends a message, the GA loop hangs forever instead of timing out and proceeding. The original 1ms non-blocking pattern allowed the loop to continue if no message was pending; the new behavior blocks indefinitely.
Fix: Use receiveTimeout(0.msecs) (non-blocking) or keep a small timeout like the original 1.msecs but check running after the receive. Alternatively, restructure to use receive only when termination is expected.
2. File: source/app.d:106-108
Severity: Suggestion
What's wrong: send(ownerTid, true) is called after geneticAlgorithm!fitness(...) returns. However geneticAlgorithm now blocks indefinitely with receiveTimeout(-1.msecs) — it will never return unless OwnerTerminated is sent. The send(ownerTid, true) is unreachable in the normal completion path.
Fix: Ensure OwnerTerminated is sent from drawingThread when stop becomes true, or restructure the termination flow so the GA can finish its iteration limit before sending completion.
File: source/app.d:137-143
Severity: Suggestion
What's wrong: The channel-based stop mechanism works but receiveTimeout pattern for (bool _) will silently ignore the value — better to use a dedicated stop channel or check the boolean.
Fix: Use receiveTimeout(100.msecs, (bool stopSignal) { stop = stopSignal; }) for clarity, or use a separate receive handler.
Verdict: REQUEST_CHANGES — infinite blocking receive in the GA loop is a correctness issue.
Hnatekmar
left a comment
There was a problem hiding this comment.
test: checking write access
zelvinator
left a comment
There was a problem hiding this comment.
Review: PR #35 — Korektní ukončení (Proper shutdown)
Changes
- app.d: Added after and complete, so the drawing thread knows when the GA finishes
- genetic.d: Changed → so the GA loop doesn't poll every 1ms but instead blocks indefinitely until a termination signal
- drawingThread: Added flag that listens for the GA completion signal (bool message) and closes the window when received
Assessment
✅ Properly handles graceful shutdown — the window closes automatically when the genetic algorithm completes
✅ The timeout makes the GA loop block instead of busy-waiting (saves CPU)
✅ The signal-based approach using D's actor model (Tid) is idiomatic
Minor suggestion
Consider adding a short notification/dialog when the GA finishes before closing, so the user sees that processing is done rather than the window suddenly disappearing.
Good work, clean implementation of the requested feature.
zelvinator
left a comment
There was a problem hiding this comment.
Review: PR #35 — Korektní ukončení (Proper shutdown)
Changes
- app.d: Added signal after gaCircle() and gaRectangle() complete, so the drawing thread knows when the GA finishes
- genetic.d: Changed receiveTimeout from 1ms to -1ms so the GA loop blocks indefinitely instead of busy-waiting
- drawingThread: Added stop flag that listens for the GA completion signal and closes the window when received
Assessment
- Properly handles graceful shutdown — the window closes automatically when the GA completes
- The -1ms timeout makes the GA loop block instead of busy-waiting (saves CPU)
- The signal-based approach using D's actor model (Tid) is idiomatic
Good work, clean implementation of the requested feature.
Malý patch, který zařídí, že se vykreslování ukončí v případě konce GA