#thread #methods #cowboy #sheriff

cowboy

Safe & convenient container for quick prototyping

14 releases

Uses new Rust 2024

new 0.1.14 May 11, 2025
0.1.13 May 11, 2025

#752 in Encoding

Download history

378 downloads per month

MIT license

22KB
332 lines

Cowboy 🤠

A thread-safe wrapper for shared data with a focus on ergonomics.

Designed for quick prototyping, when you don't really want to think about lifetimes and just want to get something working as fast as possible.

What is it?

Cowboy<T> is just a wrapper for Arc<RwLock<T>> that's designed to be as low-boilerplate as possible. It has more concise method names, and lots of trait implementations that make it work in more situations. (It implements Eq, Hash, Ord, and so on as long as the underlying type supports it).

Features

  • Thread-safe shared data with interior mutability.
  • Simple API: just use .r() to read and .w() to write.
  • Implements common traits like Clone, PartialEq, Hash, etc.
  • Unsafe methods for those who want to break the rules.
  • SHERIFF for global cowboy storage.
  • Zero-boilerplate serialization and deserialization.

Quick Start

I think we can all agree that you shouldn't use Cowboy or SHERIFF in production code, but I'm hopeful it can be useful for when you're prototyping and want the borrow checker to get out of your way. Here's how they work:

Basic usage

use cowboy::*;

// use `.cowboy()` on any value to get a Cowboy version of it.
let counter = 0.cowboy();

println!("Counter: {counter}");

// Cloning a cowboy gives you a pointer to the same underlying data
let counter_2 = counter.clone();

// Modify the value
*counter.w() += 1;

// Both counter and counter_2 were modified
assert_eq!(counter, counter_2); 

Global storage with SHERIFF

use cowboy::*;

let counter = 0.cowboy();

// You can register cowboys with the SHERIFF using any key type
SHERIFF.register("counter", counter.clone());
SHERIFF.register(42, counter.clone());

// Access from anywhere
let counter_1 = SHERIFF.get::<_, i32>("counter");
let counter_2 = SHERIFF.get::<_, i32>(42); // Note: not &42

*counter.w() += 1;
*counter_1.w() += 2;
*counter_2.w() += 3;

// All counters should have the same value since they're all
// clones of the same original counter
assert_eq!(counter_1, counter_2);
println!("Counter: {counter}");

Zero-boilerplate saving and loading

use cowboy::*;

let counter = 0.cowboy();

counter.save("counter.json");

let new_counter = Cowboy::<i64>::load("counter.json");

println!("Counter: {counter}");

Examples

Check out the examples directory for more usage patterns:

  • basic.rs: Simple usage
  • shared_data.rs: Sharing data between threads
  • unsafe_methods.rs: Demonstrating the unsafe methods

License

MIT

Dependencies

~1.2–7MB
~29K SLoC