Fix Race conditions
I believe this fixes https://github.com/SDWebImage/SDWebImageSwiftUI/issues/358
Summary by CodeRabbit
-
Bug Fixes
- Improves stability of image loading by ensuring progress and completion callbacks are invoked consistently under concurrent scenarios.
- Delivers progress updates reliably on the main thread, reducing missed or duplicated notifications.
- Reduces rare race-related crashes or hangs during rapid callback changes.
-
Refactor
- Internally synchronizes callback handling for more predictable behavior, with no changes to how you set or use callbacks.
Walkthrough
Introduces thread-safe storage and invocation for image loading callbacks in ImageManager by adding a private callback queue and backing closures. Public callback properties become computed with synchronized get/set. Progress and completion now capture local callback references and dispatch to the main thread, minimizing race conditions. No functional flow changes.
Changes
| Cohort / File(s) | Summary of Changes |
|---|---|
Thread-safe callback handlingSDWebImageSwiftUI/Classes/ImageManager.swift |
- Added callbackQueue and private _successBlock, _failureBlock, _progressBlock.- Converted successBlock, failureBlock, progressBlock to computed properties synchronized via callbackQueue.- Captured local callback copies for progress/completion before invoking on main thread. - Maintains existing loading flow and API surface behavior. |
Sequence Diagram(s)
sequenceDiagram
autonumber
participant View
participant ImageManager
participant SDWebImage
participant CallbackQueue as Callback Queue
participant MainThread
View->>ImageManager: set success/failure/progress blocks
ImageManager->>CallbackQueue: sync set _success/_failure/_progress
View->>ImageManager: load(url)
ImageManager->>SDWebImage: start request
SDWebImage-->>ImageManager: progress(received,total)
ImageManager->>CallbackQueue: sync get _progress
CallbackQueue-->>ImageManager: progressCallback
alt progressCallback exists
ImageManager->>MainThread: invoke progressCallback(received,total)
end
SDWebImage-->>ImageManager: completion(image,data,cacheType or error)
ImageManager->>CallbackQueue: sync get _success/_failure
CallbackQueue-->>ImageManager: successCallback/failureCallback
alt success
ImageManager->>MainThread: invoke successCallback(image,data,cacheType)
else failure
ImageManager->>MainThread: invoke failureCallback(error)
end
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
In burrows of bytes, I twitch with delight,
Queued little callbacks, kept snug and tight.
No races to chase, no hare-brained despair—
Progress hops softly, completion with care.
On the main meadow, we nuzzle the view,
Thread-safe thumps: thump-thump—swift and true.
✨ Finishing Touches
- [ ] 📝 Generate Docstrings
🧪 Generate unit tests
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
🪧 Tips
Chat
There are 3 ways to chat with CodeRabbit:
- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
-
I pushed a fix in commit <commit_id>, please review it. -
Open a follow-up GitHub issue for this discussion.
-
- Files and specific lines of code (under the "Files changed" tab): Tag
@coderabbitaiin a new review comment at the desired location with your query. - PR comments: Tag
@coderabbitaiin a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:-
@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase. -
@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
-
Support
Need help? Create a ticket on our support page for assistance with any issues or questions.
CodeRabbit Commands (Invoked using PR/Issue comments)
Type @coderabbitai help to get the list of available commands.
Other keywords and placeholders
- Add
@coderabbitai ignoreor@coderabbit ignoreanywhere in the PR description to prevent this PR from being reviewed. - Add
@coderabbitai summaryto generate the high-level summary at a specific location in the PR description. - Add
@coderabbitaianywhere in the PR title to generate the title automatically.
CodeRabbit Configuration File (.coderabbit.yaml)
- You can programmatically configure CodeRabbit by adding a
.coderabbit.yamlfile to the root of your repository. - Please see the configuration documentation for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation:
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
Status, Documentation and Community
- Visit our Status Page to check the current availability of CodeRabbit.
- Visit our Documentation for detailed information on how to use CodeRabbit.
- Join our Discord Community to get help, request features, and share feedback.
- Follow us on X/Twitter for updates and announcements.