-
-
Notifications
You must be signed in to change notification settings - Fork 12
feat: impl OnceMap #107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: impl OnceMap #107
Conversation
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request implements OnceMap, a concurrent hash map that ensures computation happens only once per key and caches results. It also reorganizes tests for the once module primitives and enhances singleflight::Group to support generic key queries.
Changes:
- Implements
OnceMapwith thread-safe single-execution-per-key semantics - Adds
try_workmethod tosingleflight::Groupfor fallible computations - Reorganizes tests by moving them from centralized test modules into their respective implementation submodules
- Enhances
singleflight::Group::forgetto accept generic key types via theBorrowtrait
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| mea/src/once/once_map/mod.rs | New OnceMap implementation with compute/try_compute methods and HashMap-like interface |
| mea/src/once/once_map/tests.rs | Comprehensive tests for OnceMap covering basic operations, concurrency, and error handling |
| mea/src/once/once/mod.rs | Adds test module declaration |
| mea/src/once/once/tests.rs | Extracted Once tests from the centralized test file |
| mea/src/once/once_cell/mod.rs | Adds test module declaration |
| mea/src/once/once_cell/tests.rs | Removed Once tests that were moved to once/tests.rs, updated imports |
| mea/src/once/mod.rs | Adds once_map module and exports OnceMap |
| mea/src/singleflight/mod.rs | Adds try_work method for fallible operations, updates forget signature to support Borrow, removes comment |
| mea/src/lib.rs | Documents OnceMap in module-level documentation |
| README.md | Adds OnceMap to the list of primitives |
| CHANGELOG.md | Documents new features |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| pub async fn try_work<E, F>(&self, key: K, func: F) -> Result<V, E> | ||
| where | ||
| F: AsyncFnOnce() -> Result<V, E>, | ||
| { | ||
| // 1. Get or create the OnceCell. | ||
| let cell = { | ||
| let mut map = self.map.lock(); | ||
| map.entry(key.clone()) | ||
| .or_insert_with(|| Arc::new(OnceCell::new())) | ||
| .clone() | ||
| }; | ||
|
|
||
| // 2. Try to initialize the cell. | ||
| // OnceCell::get_or_try_init guarantees that only one task executes the closure. | ||
| let res = cell | ||
| .get_or_try_init(async || { | ||
| let result = func().await?; | ||
|
|
||
| // Cleanup: remove the key from the map. | ||
| // We must ensure we remove the entry corresponding to *this* cell. | ||
| let mut map = self.map.lock(); | ||
| if let Some(existing) = map.get(&key) { | ||
| // Check if the map still points to our cell. | ||
| if Arc::ptr_eq(&cell, existing) { | ||
| map.remove(&key); | ||
| } | ||
| } | ||
|
|
||
| Ok(result) | ||
| }) | ||
| .await?; | ||
|
|
||
| Ok(res.clone()) | ||
| } |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new try_work method lacks test coverage. While there is a doc test example, there should be unit tests in the test module to verify the behavior, especially testing scenarios like: concurrent callers when the first fails and the second succeeds, behavior when both fail, and ensuring proper cleanup after failures.
Some pending issues:
onceprimitives tests. (DONE)Mutex<HashMap>andDashMap(and perhaps move the map interface to theinternalmodule). (LATER)Q: ?SizedwhereK: Borrow<Q>andQ: Hash + Eqlike std's HashMap. (DONE)