{"id":16900441,"url":"https://github.com/d0nutptr/talaria","last_synced_at":"2025-03-22T10:30:57.461Z","repository":{"id":217274486,"uuid":"740230507","full_name":"d0nutptr/talaria","owner":"d0nutptr","description":"A high performance, cyclic message passing library.","archived":false,"fork":false,"pushed_at":"2024-01-21T09:26:30.000Z","size":159,"stargazers_count":19,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T10:21:23.381Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://crates.io/crates/talaria","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d0nutptr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2024-01-07T22:19:25.000Z","updated_at":"2024-03-12T00:31:58.000Z","dependencies_parsed_at":"2024-01-21T10:28:07.270Z","dependency_job_id":null,"html_url":"https://github.com/d0nutptr/talaria","commit_stats":null,"previous_names":["d0nutptr/talaria"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d0nutptr%2Ftalaria","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d0nutptr%2Ftalaria/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d0nutptr%2Ftalaria/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d0nutptr%2Ftalaria/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d0nutptr","download_url":"https://codeload.github.com/d0nutptr/talaria/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244943657,"owners_count":20536274,"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-13T17:54:40.716Z","updated_at":"2025-03-22T10:30:57.034Z","avatar_url":"https://github.com/d0nutptr.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# talaria\n\n`talaria` is a high performance, cyclic message passing library with bounded FIFO semantics.\n\n\u003e [!CAUTION]\n\u003e While `talaria` has been validated with *some* correctness tests, it should still be considered unstable and unproven at this time.\n\n`talaria` is broken up into three main concepts:\n* Channels\n* Partitions\n* Reservations\n\n# Channels\n`talaria`'s channels are similar to bounded channels found in the standard library. A couple of\ndifferences exist, though.\n\nFor one, channels need to be provided a fixed collection of objects to manage ahead of time.\nSecondly, channels are constructed with at least two partitions.\n\n# Partitions\nPartitions can be thought of as \"states\" for the data managed by the channel. \nWhy not consider partitions as \"owners\" of data? Well, partitions can be configured to either be\n`exclusive` or `concurrent`, which describes whether multiple instances of the partition can be held simultaneously.\nSo, when all partitions are in \"exclusive\" mode, it might make sense to consider them as distinct \"owners\",\nbut concurrent access to a partition changes this somewhat. The data is managed by the partition, but holding\na reference to a partition (_unless it's an exclusive partition_) does not guarantee that the data is exclusively\nowned by this context.\n\nPartitions are used to reserve one or more objects currently owned by the partition. Once the\nobjects are no longer in use (e.g. go out of scope), they are \"transferred\" to the next logical\npartition. So, objects go from partition `0` to partition `1`, from partition `1` to partition\n`2`, and so on and so forth. Once an object in the final partition is unreserved, it is returned\nto partition `0`.\n\nIt's helpful to think of partitions more as \"states\" in a cycle, rather than \"sender\" and\n\"receiver\" pairs. In fact, this was the original motivation for the library - to use partitions\nto represent states of an object in its lifecycle, allowing for simple state transitions, and\naccess by multiple owners if desired. This, of course, lends itself to message passing, assuming\nmutability of the data inside the partitions.\n\n# Reservations\nReservations represent exclusive ownership of some data. Reservations are created from a\npartition. Once available, a [reservation](partition::Reservation) is created which holds\nexclusive ownership to the objects requested. This means that once you hold a reservation, it is\ncompletely safe to read and write to these objects.\n\nOnce the reservation goes out of scope, or is explicitly dropped, the ownership of the objects\nare \"transferred\" to the next logical partition. Notably, for concurrent partitions, multiple\nreservations can be requested at a time on one partition. Holding a reservation still guarantees\nexclusive ownership of the objects managed by the reservation, but dropping the reservation can\ntemporarily block execution until the prior reservations have also been passed along. That is to\nsay, reservations respect FIFO ordering - a reservation created first, must be dropped first and\nlater reservations will wait until this is possible.\n\n# How to use\n\nThere are three steps to using `talaria`:\n\n1. Create a channel\n2. Get a partition\n3. Acquire a reservation\n\nHere's an example of using `talaria` to pass \"Ping/Pong\" messages between two threads, indefinitely.\n\n```rust\nuse talaria::channel::Channel;\n\n#[derive(Clone)]\nenum Message {\n    Ping, \n    Pong,\n}\n\nfn main() {\n    // id of the partition we'll access on the main thread\n    const MAIN_PARTITION: usize = 0;\n    // id of the partition we'll access on worker thread\n    const THREAD_PARTITION: usize = 1;\n    \n    let channel = Channel::builder()\n        .add_exclusive_partition()\n        .add_exclusive_partition()\n        .build(vec![Message::Ping; 16])\n        .unwrap();\n\n    let channel_clone = channel.clone();\n    \n    // spin up a worker thread\n    // it will do what the main thread is doing, but in reverse..\n    let thread_handle = std::thread::spawn(move || {\n        let mut partition = channel_clone\n            .get_exclusive_partition(THREAD_PARTITION)\n            .unwrap();\n        \n        while let Ok(mut reservation) = partition.reserve(1) {\n            reservation[0] = match \u0026reservation[0] {\n                Message::Pong =\u003e Message::Ping,\n                Message::Ping =\u003e panic!(\"unexpected message!\")\n            };\n        }\n    });\n\n    let mut partition = channel\n        .get_exclusive_partition(MAIN_PARTITION)\n        .unwrap();\n\n    // reserve an item at a time\n    while let Ok(mut reservation) = partition.reserve(1) {\n        reservation[0] = match \u0026reservation[0] {\n            // if the first (and only) element is a \"ping\" message,\n            // set it to \"pong\" and forward it\n            Message::Ping =\u003e Message::Pong,\n            //  otherwise we got an unexpected message!\n            Message::Pong =\u003e panic!(\"unexpected message!\")\n        };\n    }\n    \n    thread_handle.join().unwrap();\n}\n```\n\n# Benchmarking\n\n`talaria` uses Criterion for benching and only requires you run `cargo bench` to begin benchmarking.\n\nBenchmarks are written for both exclusive and concurrent two-thread partition scenarios, as well as\nthe equivalent tests with `std::sync::mpsc` and `crossbeam`'s bounded channels.\n\nThe following is a sample of benchmarking on my machine (i9-9900k, 64Gb 3200mhz RAM):\n\n## Exclusive\n![Exclusive Partition Benchmark](imgs/exclusive.svg)\n\n## Concurrent\n![Concurrent Partition Benchmark](imgs/concurrent.svg)\n\n## std::sync::mpsc\n![std::sync::mpsc Benchmark](imgs/mpsc.svg)\n\n## crossbeam\n![crossbeam Benchmark](imgs/crossbeam.svg)\n\n# Correctness Tests\n`talaria` comes with a (relatively incomplete) suite of correctness tests using both [`loom`](https://github.com/tokio-rs/loom)\nand [`shuttle`](https://github.com/awslabs/shuttle). To run them, do the following:\n\n## Loom\n`RUSTFLAGS=\"--cfg loom\" cargo test`\n\n## Shuttle\n`RUSTFLAGS=\"--cfg shuttle\" cargo test`\n\nSome tests are timebound to prevent them from running either indefinitely or an excessively long while. Expect tests to take a few minutes, though.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd0nutptr%2Ftalaria","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd0nutptr%2Ftalaria","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd0nutptr%2Ftalaria/lists"}