Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 2026-02-27

### Added
- **Async Support**: New `tokio` feature flag for async task execution
- **AsyncRunnable trait**: Define async tasks that can be executed with Tokio runtime
- **TokioTask trait**: Extension trait providing `async_start()` method for spawning async tasks
- **TokioParallelRun trait**: Run multiple async tasks in parallel with `async_par_run()` method
- **Custom Thread Builder**: `start_with_builder()` method for customizing thread properties (name, stack size, etc.)
- **Parallel Execution**: `ParallelRun` trait for running multiple tasks in parallel across CPU cores
- Comprehensive documentation for all features
- Examples for async usage, parallel execution, and custom thread configuration

### Changed
- Enhanced documentation with detailed examples for all traits
- Improved README with feature descriptions and usage examples

## [1.0.0] - Initial Release

### Added
- **Runnable trait**: Define tasks as structs implementing a simple trait
- **Thread trait**: Extension trait providing `start()` method for spawning threads
- Basic documentation and examples

30 changes: 29 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "struct-threads"
version = "1.0.1"
version = "1.1.0"
edition = "2024"
authors = ["Davíd Lishchyshen <david@daika.dev>"]
description = "A simple library providing a Thread extension trait for Runnable tasks."
Expand All @@ -9,11 +9,18 @@ readme = "README.md"
repository = "https://github.com/AsfhtgkDavid/struct-threads"
keywords = ["thread", "runnable", "struct", "task"]
categories = ["concurrency", "rust-patterns"]

[features]
default = []
tokio = ["dep:tokio"]

[dependencies]
tokio = { version = "1.49.0", optional = true,features = ["rt"] }

[dev-dependencies]
criterion = "0.8.2"
tokio = { version = "1.49.0", features = ["rt", "rt-multi-thread", "time", "macros"] }

[[bench]]
name = "par_run"
harness = false
harness = false
146 changes: 146 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,23 @@ While `std::thread::spawn` is powerful, complex thread logic often requires pass
- **Simplifies testing** by allowing you to instantiate thread state without immediately spawning it.
- **Provides a clear contract** for the thread's return value via associated types.

## Features

- **Default**: Provides `Runnable`, `Thread`, and `ParallelRun` traits for standard thread-based execution
- **`tokio`**: Adds `AsyncRunnable`, `TokioTask`, and `TokioParallelRun` traits for async task execution with Tokio runtime

## Installation

Install using `cargo`:

```bash
cargo add struct-threads
```

For async support with Tokio:

```bash
cargo add struct-threads --features tokio
```

## Basic Usage
Expand Down Expand Up @@ -59,6 +69,68 @@ fn main() {

```

## Advanced Usage: Parallel Execution

You can run multiple tasks in parallel using the `ParallelRun` trait:

```rust
use struct_threads::{Runnable, ParallelRun};

struct ComputeTask(i32);

impl Runnable for ComputeTask {
type Output = i32;

fn run(self) -> Self::Output {
// Perform some heavy computation
self.0 * self.0
}
}

fn main() {
let tasks = (0..100)
.map(ComputeTask)
.collect::<Vec<_>>();

// Runs tasks in parallel across available CPU cores
let results = tasks.par_run().unwrap();

println!("Computed {} results", results.len());
}
```

## Advanced Usage: Custom Thread Configuration

Use `start_with_builder` to customize thread properties:

```rust
use std::thread::Builder;
use struct_threads::{Runnable, Thread};

struct MyTask(i32);

impl Runnable for MyTask {
type Output = i32;

fn run(self) -> Self::Output {
self.0 * 2
}
}

fn main() {
let task = MyTask(21);

let builder = Builder::new()
.name("my-custom-thread".to_string())
.stack_size(4 * 1024 * 1024); // 4 MB stack

let handle = task.start_with_builder(builder);
let result = handle.join().unwrap();

println!("Result: {}", result);
}
```

## Advanced Usage: Channels

This pattern truly shines when your thread needs to communicate with the main thread or hold more complex state, like channels.
Expand Down Expand Up @@ -92,6 +164,80 @@ fn main() {
let result = rx.recv().unwrap();
println!("Received: {}", result);
}
```

## Async Support (Tokio)

Enable the `tokio` feature to use async tasks:

```toml
[dependencies]
struct-threads = { version = "1.0", features = ["tokio"] }
tokio = { version = "1", features = ["rt", "macros"] }
```

### Basic Async Usage

```rust
use struct_threads::{AsyncRunnable, TokioTask};

struct AsyncTask(i32);

impl AsyncRunnable for AsyncTask {
type Output = i32;

fn run(self) -> impl std::future::Future<Output = Self::Output> + Send {
async move {
// Perform async work
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
self.0 * 2
}
}
}

#[tokio::main]
async fn main() {
let task = AsyncTask(21);

// The .async_start() method is provided by the TokioTask trait
let handle = task.async_start();

// Await the result
let result = handle.await.unwrap();

println!("Result: {}", result);
}
```

### Parallel Async Execution

```rust
use struct_threads::{AsyncRunnable, TokioParallelRun};

struct AsyncComputeTask(i32);

impl AsyncRunnable for AsyncComputeTask {
type Output = i32;

fn run(self) -> impl std::future::Future<Output = Self::Output> + Send {
async move {
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
self.0 * self.0
}
}
}

#[tokio::main]
async fn main() {
let tasks = (0..100)
.map(AsyncComputeTask)
.collect::<Vec<_>>();

// Runs async tasks in parallel
let results = tasks.async_par_run().await.unwrap();

println!("Computed {} results", results.len());
}

```

Expand Down
Loading