https://github.com/antouhou/anycow
A supercharged container for read-heavy, occasionally-updated data structures with multiple storage strategies
https://github.com/antouhou/anycow
data-container data-structures multithreading rust shared-ownership
Last synced: 3 months ago
JSON representation
A supercharged container for read-heavy, occasionally-updated data structures with multiple storage strategies
- Host: GitHub
- URL: https://github.com/antouhou/anycow
- Owner: antouhou
- License: mit
- Created: 2025-07-27T18:31:07.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2025-07-28T03:42:23.000Z (3 months ago)
- Last Synced: 2025-07-28T03:49:06.213Z (3 months ago)
- Topics: data-container, data-structures, multithreading, rust, shared-ownership
- Language: Rust
- Homepage: https://docs.rs/anycow
- Size: 28.3 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 🐄 AnyCow
[](https://crates.io/crates/anycow)
[](https://docs.rs/anycow)
[](LICENSE)> A supercharged container for read-heavy, occasionally-updated data structures
**AnyCow** is a versatile, high-performance container that extends the concept of `Cow` (Clone-on-Write) with multiple storage strategies optimized for different use cases. Perfect for scenarios where you need to read values frequently but update them only occasionally.
## 🚀 Features
- **Multiple Storage Strategies**: Choose the right storage for your use case
- `Borrowed` - Zero-cost references for temporary data
- `Owned` - Heap-allocated owned data via `Box`
- `Shared` - `Arc` for shared immutable data
- `Updatable` - Lock-free atomic updates using `arc-swap`
- `Lazy` - Lazy initialization with atomic updates for static contexts- **Lock-Free Updates**: The `Updatable` and `Lazy` variants use `arc-swap` for atomic, lock-free updates
- **Lazy Initialization**: The `Lazy` variant makes it possbile to create an `Updatable` in a static context
- **Flexible API**: Easy conversion between different storage types
- **Zero-Cost Abstractions**: Minimal overhead for common operations
- **Thread-Safe**: Share data safely across threads with `Shared`, `Updatable`, and `Lazy` variants## 📦 Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
anycow = "0.1"
```## 🎯 Use Cases
AnyCow shines in scenarios where you have:
- **Configuration data** that's read frequently but updated occasionally
- **Global/static data** that needs lazy initialization and atomic updates
- **Cached values** that need atomic updates without locks
- **Shared state** across multiple threads with infrequent modifications
- **Hot paths** where you want to minimize allocation overhead
- **APIs** that need to accept both borrowed and owned data flexibly## 🔥 Quick Start
```rust
use anycow::AnyCow;// Create from different sources
let borrowed = AnyCow::borrowed(&"hello");
let owned = AnyCow::owned(String::from("world"));
let shared = AnyCow::shared(std::sync::Arc::new(42));
let updatable = AnyCow::updatable(vec![1, 2, 3]);
let lazy = AnyCow::lazy(|| vec![7, 8, 9]);// Read values efficiently
println!("{}", *borrowed.borrow()); // "hello"
println!("{}", *owned.borrow()); // "world"// Atomic updates (lock-free!)
updatable.try_replace(vec![4, 5, 6]).unwrap();
lazy.try_replace(vec![10, 11, 12]).unwrap();
```## 💡 Examples
### Reading Configuration
```rust
use anycow::AnyCow;
use std::sync::Arc;#[derive(Clone, Debug)]
struct Config {
max_connections: usize,
timeout_ms: u64,
}// Create updatable config
let config = AnyCow::updatable(Config {
max_connections: 100,
timeout_ms: 5000,
});// Read frequently (very fast)
let current_config = config.borrow();
println!("Max connections: {}", current_config.max_connections);// Update occasionally (atomic, lock-free)
config.try_replace(Config {
max_connections: 200,
timeout_ms: 3000,
}).unwrap();
```### Flexible API Design
```rust
use anycow::AnyCow;fn process_data<'a>(data: AnyCow<'a, str>) {
// Works with borrowed, owned, or shared data
println!("Processing: {}", *data.borrow());
}// All of these work!
process_data(AnyCow::borrowed("borrowed string"));
process_data(AnyCow::owned(String::from("owned string")));
process_data(AnyCow::shared(std::sync::Arc::new(String::from("shared string"))));
```### Cache with Atomic Updates
```rust
use anycow::AnyCow;
use std::thread;
use std::sync::Arc;let cache = Arc::new(AnyCow::updatable(vec![1, 2, 3]));
// Spawn reader threads
let cache_clone = cache.clone();
let reader = thread::spawn(move || {
for _ in 0..1000 {
let data = cache_clone.borrow();
println!("Sum: {}", data.iter().sum::());
}
});// Update cache atomically
cache.try_replace(vec![4, 5, 6, 7, 8]).unwrap();reader.join().unwrap();
```### Lazy Global Configuration
```rust
use anycow::AnyCow;
use std::collections::HashMap;// Perfect for static/global data that's expensive to initialize
static CONFIG: AnyCow> = AnyCow::lazy(|| {
println!("Loading configuration..."); // Only runs once!
let mut config = HashMap::new();
config.insert("app_name".to_string(), "MyApp".to_string());
config.insert("version".to_string(), "1.0.0".to_string());
config
});fn main() {
// First access initializes the config
let app_name = CONFIG.borrow().get("app_name").cloned().unwrap();
println!("App: {}", app_name);
// Subsequent accesses are fast (no re-initialization)
let version = CONFIG.borrow().get("version").cloned().unwrap();
println!("Version: {}", version);
// Update the global config atomically
let mut new_config = HashMap::new();
new_config.insert("app_name".to_string(), "MyApp Pro".to_string());
new_config.insert("version".to_string(), "2.0.0".to_string());
CONFIG.try_replace(new_config).unwrap();
}## 🧠 Storage Strategy Guide
| Variant | Best For | Thread Safe | Mutable | Memory |
|---------|----------|-------------|---------|--------|
| `Borrowed` | Temporary refs, hot paths | ❌ | ❌ | Zero-copy |
| `Owned` | Exclusive ownership | ❌ | ✅ | Heap |
| `Shared` | Read-only sharing | ✅ | ❌ | Shared |
| `Updatable` | Concurrent reads + atomic updates | ✅ | Via `try_replace()` | Shared + Atomic |
| `Lazy` | Static/global data + atomic updates | ✅ | Via `try_replace()` | Lazy + Shared + Atomic |## 🔧 API Reference
### Construction
```rust
AnyCow::borrowed(&value) // From reference
AnyCow::owned(value) // From owned value (boxed)
AnyCow::shared(arc) // From Arc
AnyCow::updatable(value) // Create updatable variant
AnyCow::lazy(init_fn) // Create lazy variant with init function
```### Access
```rust
container.borrow() // Get reference to value
container.to_mut() // Get mutable reference (COW)
container.into_owned() // Convert to owned value
container.to_arc() // Convert to Arc
```### Updates
```rust
container.try_replace(new_value) // Atomic update (Updatable & Lazy only)
```## ⚡ Performance
AnyCow is designed for performance:
- **Zero-cost borrowing**: No allocation for `Borrowed` variant
- **Lazy initialization**: `Lazy` variant allow to create an `Updatable` in a static context
- **Lock-free updates**: `Updatable` and `Lazy` use `arc-swap` for atomic operations
- **Minimal overhead**: Smart enum design with efficient memory layout
- **Branch prediction friendly**: Common operations are optimized## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
## 📄 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
- Built with [`arc-swap`](https://crates.io/crates/arc-swap) for lock-free atomic operations
- Inspired by the standard library's `Cow` but supercharged for modern use cases---
Made with ❤️ for the Rust community. Happy coding! 🦀