{"id":16918447,"url":"https://github.com/poignardazur/scoped_tasks_prototype","last_synced_at":"2025-03-22T11:30:45.571Z","repository":{"id":172261552,"uuid":"649067973","full_name":"PoignardAzur/scoped_tasks_prototype","owner":"PoignardAzur","description":"A quick-and-dirty attempt to get scoped tasks in Rust.","archived":false,"fork":false,"pushed_at":"2023-06-04T10:24:07.000Z","size":10,"stargazers_count":14,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-23T12:17:29.741Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PoignardAzur.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-03T17:08:55.000Z","updated_at":"2023-06-10T12:48:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"2769deba-c3d7-4aab-9261-069f65fc4d3a","html_url":"https://github.com/PoignardAzur/scoped_tasks_prototype","commit_stats":null,"previous_names":["poignardazur/scoped_tasks_prototype"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PoignardAzur%2Fscoped_tasks_prototype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PoignardAzur%2Fscoped_tasks_prototype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PoignardAzur%2Fscoped_tasks_prototype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PoignardAzur%2Fscoped_tasks_prototype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PoignardAzur","download_url":"https://codeload.github.com/PoignardAzur/scoped_tasks_prototype/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244951087,"owners_count":20537315,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T19:39:53.944Z","updated_at":"2025-03-22T11:30:45.199Z","avatar_url":"https://github.com/PoignardAzur.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# scoped_tasks_prototype\n\nA quick-and-dirty attempt to get scoped tasks in Rust.\n\nThis library tries to provide an interface similar to\n[scoped threads](https://doc.rust-lang.org/stable/std/thread/fn.scope.html),\naccessible from tasks. See\n[Tyler Mandry's article for why this is non-trivial](https://tmandry.gitlab.io/blog/posts/2023-03-01-scoped-tasks/).\nThis crate explores the \"Restricting Borrowing\" option described in that post.\n\nTo be specific, this crate creates three concepts:\n\n- A **Bank**, where your task is stored.\n- **Vaults**, located inside the Bank.\n- **Loans** which point to contents of the Vaults.\n\nWhen you want to run scoped tasks, you call the `scope` function:\n\n```rust\nscope(|bank| async move {\n    // code that will spawn tasks\n})\n```\n\nThis function accepts a callback which returns a promise (alas, no async\nclosures yet); that callback will be given a `Bank`, which represents _the\nunderlying memory the promise is stored in_.\n\nInside the callback, you can use the `vault!` macro to pin values to that\nunderlying storage (it's literally a slightly modified version of the standard\n`pin!` macro):\n\n```rust\nlet a = vault!(vec![1, 2, 3]);\nlet x = vault!(0);\n```\n\nFinally, you can use that vault and the bank to get loans. Loans are `'static`\nvalues storing a reference to a vault, _and_ a shared reference to the bank. The\nbank can't possibly be dropped until all loans are dropped, even if the parent\ntask is dropped, which means that a loan is always safe to deref:\n\n```rust\nlet a = a.loan(\u0026bank);\nlet mut x = x.loan_mut(\u0026bank);\ntokio::spawn(async move {\n    let a = a.deref();\n    let x = x.deref_mut();\n    *x += a[0] + a[2];\n})\n```\n\nTaken together, this means it's possible with some overhead to run scoped tasks\nwith a syntax similar to scoped threads:\n\n```rust\nasync fn foobar() {\n    scope(|bank| async move {\n        let a = vault!(vec![1, 2, 3]);\n        let x = vault!(0);\n\n        let t1 = {\n            let a = a.loan(\u0026bank);\n            tokio::spawn(async move {\n                let a = a.deref();\n                // We can borrow `a` here.\n                println!(\"hello from the first scoped task: {:?}\", a);\n            })\n        };\n\n        let t2 = {\n            let a = a.loan(\u0026bank);\n            let mut x = x.loan_mut(\u0026bank);\n            tokio::spawn(async move {\n                let a = a.deref();\n                let x = x.deref_mut();\n\n                println!(\"hello from the second scoped task\");\n                // We can even mutably borrow `x` here,\n                // because no other tasks are using it.\n                *x += a[0] + a[2];\n            })\n        };\n\n        t1.await.unwrap();\n        t2.await.unwrap();\n    })\n    .await;\n}\n```\n\n## How safe is this?\n\n:shrug_emoji:\n\nThis is very much at the proof-of-concept stage.\n\nSo far I've only tried to run examples in the repo, including the threads\nexample with MIRI, which reported no error. It does not immediately blow up my\ncomputer, which is honestly better than I expected.\n\nIf people are interested, I would strongly encourage them to poke at this at the\nseams and see if any parts of the crate are unsound. I have virtually no\nexperience whatsoever with unsafe, so I'm curious if I missed something.\n\nMore importantly, I'm hoping this serves as inspiration to the writers of async\nruntimes for including similar concepts in their crates. Scoped tasks aren't\nimpossible, there's just a lot of design space we need to explore before they\ncan really become convenient to use. This is just one very early attempt.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoignardazur%2Fscoped_tasks_prototype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpoignardazur%2Fscoped_tasks_prototype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoignardazur%2Fscoped_tasks_prototype/lists"}