{"id":15031622,"url":"https://github.com/atilaneves/fearless","last_synced_at":"2025-04-10T00:21:43.988Z","repository":{"id":71432305,"uuid":"134472795","full_name":"atilaneves/fearless","owner":"atilaneves","description":"Safe concurrency in D (`shared` made easier)","archived":false,"fork":false,"pushed_at":"2024-04-22T17:36:09.000Z","size":42,"stargazers_count":54,"open_issues_count":0,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-24T02:05:32.636Z","etag":null,"topics":["concurrency","d","dip1000","dlang","dlanguage","lifetimes","multithread","multithreading","mutex","mutex-synchronisation","nogc","ownership","reference-counting","rust","rust-lang","rust-language","rustlang","safe","safety","threading"],"latest_commit_sha":null,"homepage":"","language":"D","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atilaneves.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":"2018-05-22T20:34:15.000Z","updated_at":"2024-11-21T09:58:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"d2a5776e-379f-4ba2-9f96-aa40eb7732b7","html_url":"https://github.com/atilaneves/fearless","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Ffearless","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Ffearless/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Ffearless/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Ffearless/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atilaneves","download_url":"https://codeload.github.com/atilaneves/fearless/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248132122,"owners_count":21052977,"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":["concurrency","d","dip1000","dlang","dlanguage","lifetimes","multithread","multithreading","mutex","mutex-synchronisation","nogc","ownership","reference-counting","rust","rust-lang","rust-language","rustlang","safe","safety","threading"],"created_at":"2024-09-24T20:16:12.242Z","updated_at":"2025-04-10T00:21:43.956Z","avatar_url":"https://github.com/atilaneves.png","language":"D","readme":"# fearless\n\n[![Build Status](https://travis-ci.org/atilaneves/fearless.png?branch=master)](https://travis-ci.org/atilaneves/fearless)\n[![Coverage](https://codecov.io/gh/atilaneves/fearless/branch/master/graph/badge.svg)](https://codecov.io/gh/atilaneves/fearless)\n\nSafe concurrency in D\n\nThis package implements `@safe` easy sharing of mutable data between threads without having\nto cast from shared and lock/unlock a mutex. It does so by using `scope` and\n[DIP1000](https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md). It was inspired by\nRust's [std::sync::Mutex](https://doc.rust-lang.org/1.21.0/std/sync/struct.Mutex.html).\n\nThe main type is `Exclusive!T` which is safely shareable between\nthreads even if T is not `immutable` or `shared`. To create one, call\none of `gcExclusive` or `rcExclusive` with the parameters to the\nconstructor to create a type T. Passing an already created T would not\nbe safe since references to it or its internal data might exist\nelsewhere.\n\nAs the names indicate, `gcExclusive` allocates on the GC heap, whereas `rcExclusive` uses\n`RefCounted` from [automem](https://github.com/atilaneves/automem). This works automatically\nif automem can be imported, which is always the case when automem is listed as a DUB\ndependency.\n\nTo actually get access to the protected value, use `.lock()` (`borrow`\nexists as an alias) to get exclusive access for the current block of\ncode.\n\nAn example (notice that `main` is `@safe`):\n\n```d\nimport fearless;\n\n\nstruct Foo {\n    int i;\n}\n\nint* gEvilInt;\n\n\nvoid main() @safe {\n\n    // create an instance of Exclusive!Foo allocated on the GC heap\n    auto foo = gcExclusive!Foo(42);\n    // from now the value inside `foo` can only be used by calling `lock`\n\n    {\n        int* oldIntPtr;  // only here to demonstrate scopes, see below\n        auto xfoo = foo.lock();  // get exclusive access to the data (this locks a mutex)\n\n        safeWriteln(\"i: \", xfoo.i);\n        xfoo.i = 1;\n        safeWriteln(\"i: \", xfoo.i);\n\n        // can't escape to a global\n        static assert(!__traits(compiles, gEvilInt = \u0026xfoo.i));\n\n        // ok to assign to a local that lives less\n        int* intPtr;\n        static assert(__traits(compiles, intPtr = \u0026xfoo.i));\n\n        // not ok to assign to a local that lives longer\n        static assert(!__traits(compiles, oldIntPtr = \u0026xfoo.i));\n    }\n\n    // Demonstrate sending to another thread and mutating\n    auto tid = spawn(\u0026func, thisTid);\n    tid.send(foo);\n    receiveOnly!Ended;\n    safeWriteln(\"i: \", foo.lock.i);\n}\n\nstruct Ended{}\n\nvoid func(Tid tid) @safe {\n    receive(\n        // ref Exclusive!Foo doesn't compile, use pointer instead\n        (Exclusive!Foo* m) {\n            auto xfoo = m.lock;\n            xfoo.i++;\n        },\n    );\n\n    tid.send(Ended());\n}\n\n\nvoid safeWriteln(A...)(auto ref A args) { // for some reason the writelns here are all @system\n    import std.stdio: writeln;\n    import std.functional: forward;\n    () @trusted { writeln(forward!args); }();\n}\n\n```\n\nThis program prints:\n\n```\ni: 42\ni: 1\ni: 2\n```\n\nPlease consult the examples directory and/or unit tests for more.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatilaneves%2Ffearless","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatilaneves%2Ffearless","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatilaneves%2Ffearless/lists"}