thread_share/enhanced.rs
1//! # Enhanced Module - EnhancedThreadShare<T>
2//!
3//! This module provides `EnhancedThreadShare<T>`, a powerful extension of `ThreadShare<T>`
4//! that adds automatic thread management capabilities.
5//!
6//! ## 🚀 Overview
7//!
8//! `EnhancedThreadShare<T>` eliminates the need for manual thread management by providing:
9//!
10//! - **Automatic Thread Spawning**: Spawn threads with a single method call
11//! - **Built-in Thread Tracking**: Monitor active thread count and status
12//! - **Automatic Thread Joining**: Wait for all threads to complete with `join_all()`
13//! - **Thread Naming**: Give meaningful names to threads for debugging
14//! - **All ThreadShare Features**: Inherits all capabilities from `ThreadShare<T>`
15//!
16//! ## Key Benefits
17//!
18//! ### 🎯 Simplified Thread Management
19//! ```rust
20//! // Old way: Manual thread management
21//! use thread_share::share;
22//! use std::thread;
23//!
24//! let data = share!(vec![1, 2, 3]);
25//! let clone1 = data.clone();
26//! let clone2 = data.clone();
27//!
28//! let handle1 = thread::spawn(move || { /* logic */ });
29//! let handle2 = thread::spawn(move || { /* logic */ });
30//!
31//! handle1.join().expect("Failed to join");
32//! handle2.join().expect("Failed to join");
33//!
34//! // New way: Enhanced thread management
35//! use thread_share::enhanced_share;
36//!
37//! let enhanced = enhanced_share!(vec![1, 2, 3]);
38//!
39//! enhanced.spawn("worker1", |data| { /* logic */ });
40//! enhanced.spawn("worker2", |data| { /* logic */ });
41//!
42//! enhanced.join_all().expect("Failed to join");
43//! ```
44//!
45//! ### 📊 Real-time Monitoring
46//! ```rust
47//! use thread_share::enhanced_share;
48//!
49//! let enhanced = enhanced_share!(vec![1, 2, 3]);
50//!
51//! enhanced.spawn("processor", |data| { /* logic */ });
52//! enhanced.spawn("validator", |data| { /* logic */ });
53//!
54//! println!("Active threads: {}", enhanced.active_threads());
55//!
56//! // Wait for completion
57//! enhanced.join_all().expect("Failed to join");
58//!
59//! assert!(enhanced.is_complete());
60//! ```
61//!
62//! ## Architecture
63//!
64//! `EnhancedThreadShare<T>` wraps a `ThreadShare<T>` and adds:
65//!
66//! - **`inner: ThreadShare<T>`** - The underlying shared data
67//! - **`threads: Arc<Mutex<HashMap<String, JoinHandle<()>>>>`** - Thread tracking
68//!
69//! ## Thread Lifecycle
70//!
71//! 1. **Creation**: `EnhancedThreadShare::new(data)` or `enhanced_share!(data)`
72//! 2. **Spawning**: `enhanced.spawn(name, function)` creates named threads
73//! 3. **Execution**: Threads run with access to shared data
74//! 4. **Monitoring**: Track active threads with `active_threads()`
75//! 5. **Completion**: Wait for all threads with `join_all()`
76//!
77//! ## Example Usage
78//!
79//! ### Basic Thread Management
80//! ```rust
81//! use thread_share::{enhanced_share, spawn_workers};
82//!
83//! let data = enhanced_share!(vec![1, 2, 3]);
84//!
85//! // Spawn individual threads
86//! data.spawn("sorter", |data| {
87//! data.update(|v| v.sort());
88//! });
89//!
90//! data.spawn("validator", |data| {
91//! assert!(data.get().is_sorted());
92//! });
93//!
94//! // Wait for completion
95//! data.join_all().expect("Failed to join");
96//! ```
97//!
98//! ### Using Macros
99//! ```rust
100//! use thread_share::share;
101//!
102//! let data = share!(String::from("Hello"));
103//! let clone = data.clone();
104//!
105//! // Spawn a simple thread
106//! std::thread::spawn(move || {
107//! clone.update(|s| s.push_str(" World"));
108//! });
109//!
110//! // Wait a bit and check result
111//! std::thread::sleep(std::time::Duration::from_millis(100));
112//! println!("Updated: {}", data.get());
113//! ```
114//!
115//! ### Real-world Example
116//! ```rust
117//! use thread_share::share;
118//! use std::time::Duration;
119//!
120//! #[derive(Clone)]
121//! struct Server {
122//! port: u16,
123//! is_running: bool,
124//! connections: u32,
125//! }
126//!
127//! let server = share!(Server {
128//! port: 8080,
129//! is_running: false,
130//! connections: 0,
131//! });
132//!
133//! let server_clone = server.clone();
134//!
135//! // Spawn a simple server thread
136//! std::thread::spawn(move || {
137//! server_clone.update(|s| {
138//! s.is_running = true;
139//! s.connections = 5;
140//! });
141//! });
142//!
143//! // Wait a bit and check result
144//! std::thread::sleep(Duration::from_millis(100));
145//! let final_state = server.get();
146//! println!("Server running: {}, connections: {}", final_state.is_running, final_state.connections);
147//! ```
148//!
149//! ## Performance Characteristics
150//!
151//! - **Thread Spawning**: Minimal overhead over standard `thread::spawn`
152//! - **Thread Tracking**: Constant-time operations for thread management
153//! - **Memory Usage**: Small overhead for thread tracking structures
154//! - **Scalability**: Efficient for up to hundreds of threads
155//!
156//! ## Best Practices
157//!
158//! 1. **Use descriptive thread names** for easier debugging
159//! 2. **Keep thread functions focused** on single responsibilities
160//! 3. **Always call `join_all()`** to ensure proper cleanup
161//! 4. **Monitor thread count** with `active_threads()` for debugging
162//! 5. **Handle errors gracefully** from `join_all()` and `spawn()`
163//!
164//! ## Error Handling
165//!
166//! ```rust
167//! use thread_share::share;
168//!
169//! let data = share!(0);
170//! let clone = data.clone();
171//!
172//! // Spawn thread with error handling
173//! let handle = std::thread::spawn(move || {
174//! clone.update(|x| *x = *x + 1);
175//! });
176//!
177//! // Handle join errors
178//! if let Err(e) = handle.join() {
179//! eprintln!("Thread execution failed: {:?}", e);
180//! }
181//! ```
182//!
183//! ## Thread Safety
184//!
185//! `EnhancedThreadShare<T>` automatically implements `Send` and `Sync` traits
186//! when `T` implements them, making it safe to use across thread boundaries.
187//!
188//! ## Integration with Macros
189//!
190//! This module works seamlessly with the library's macros:
191//!
192//! - **`enhanced_share!`** - Creates `EnhancedThreadShare<T>` instances
193//! - **`spawn_workers!`** - Spawns multiple threads with single macro call
194//!
195//! ## Comparison with Manual Thread Management
196//!
197//! | Aspect | Manual Management | EnhancedThreadShare |
198//! |--------|-------------------|-------------------|
199//! | **Thread Creation** | `thread::spawn()` calls | `enhanced.spawn()` |
200//! | **Thread Tracking** | Manual `JoinHandle` storage | Automatic tracking |
201//! | **Thread Joining** | Manual `join()` calls | `join_all()` |
202//! | **Error Handling** | Per-thread error handling | Centralized error handling |
203//! | **Debugging** | No thread identification | Named threads |
204//! | **Code Complexity** | High | Low |
205
206use crate::core::ThreadShare;
207use std::collections::HashMap;
208use std::sync::{Arc, Mutex};
209use std::thread;
210
211/// Enhanced ThreadShare with built-in thread management
212///
213/// `EnhancedThreadShare<T>` extends `ThreadShare<T>` with automatic thread management
214/// capabilities, eliminating the need for manual thread spawning and joining.
215///
216/// ## Key Features
217///
218/// - **Automatic Thread Spawning**: Spawn threads with a single method call
219/// - **Built-in Thread Tracking**: Monitor active thread count and status
220/// - **Automatic Thread Joining**: Wait for all threads to complete with `join_all()`
221/// - **Thread Naming**: Give meaningful names to threads for debugging
222/// - **All ThreadShare Features**: Inherits all capabilities from `ThreadShare<T>`
223///
224/// ## Example
225///
226/// ```rust
227/// use thread_share::{enhanced_share, spawn_workers};
228///
229/// let data = enhanced_share!(vec![1, 2, 3]);
230///
231/// // Spawn individual threads
232/// data.spawn("sorter", |data| {
233/// data.update(|v| v.sort());
234/// });
235///
236/// data.spawn("validator", |data| {
237/// assert!(data.get().is_sorted());
238/// });
239///
240/// // Wait for completion
241/// data.join_all().expect("Failed to join");
242/// ```
243///
244/// ## Thread Lifecycle
245///
246/// 1. **Creation**: `EnhancedThreadShare::new(data)` or `enhanced_share!(data)`
247/// 2. **Spawning**: `enhanced.spawn(name, function)` creates named threads
248/// 3. **Execution**: Threads run with access to shared data
249/// 4. **Monitoring**: Track active threads with `active_threads()`
250/// 5. **Completion**: Wait for all threads with `join_all()`
251///
252/// ## Performance
253///
254/// - **Thread Spawning**: Minimal overhead over standard `thread::spawn`
255/// - **Thread Tracking**: Constant-time operations for thread management
256/// - **Memory Usage**: Small overhead for thread tracking structures
257/// - **Scalability**: Efficient for up to hundreds of threads
258pub struct EnhancedThreadShare<T> {
259 inner: ThreadShare<T>,
260 threads: Arc<Mutex<HashMap<String, thread::JoinHandle<()>>>>,
261}
262
263impl<T> EnhancedThreadShare<T> {
264 /// Creates a new EnhancedThreadShare
265 ///
266 /// This method creates a new `EnhancedThreadShare<T>` instance with the provided data.
267 /// The data is wrapped in a `ThreadShare<T>` for safe sharing between threads.
268 ///
269 /// ## Arguments
270 ///
271 /// * `data` - The initial data to share between threads
272 ///
273 /// ## Returns
274 ///
275 /// A new `EnhancedThreadShare<T>` instance.
276 ///
277 /// ## Example
278 ///
279 /// ```rust
280 /// use thread_share::EnhancedThreadShare;
281 ///
282 /// let enhanced = EnhancedThreadShare::new(0);
283 /// let enhanced = EnhancedThreadShare::new(String::from("Hello"));
284 /// let enhanced = EnhancedThreadShare::new(vec![1, 2, 3]);
285 /// ```
286 pub fn new(data: T) -> Self {
287 Self {
288 inner: ThreadShare::new(data),
289 threads: Arc::new(Mutex::new(HashMap::new())),
290 }
291 }
292
293 /// Spawns a thread with access to this shared data
294 ///
295 /// This method creates a new thread with the given name and function.
296 /// The thread receives a clone of the shared data and can safely modify it.
297 ///
298 /// ## Arguments
299 ///
300 /// * `name` - A descriptive name for the thread (useful for debugging)
301 /// * `f` - A function that receives `ThreadShare<T>` and performs the thread's work
302 ///
303 /// ## Requirements
304 ///
305 /// The function `F` must:
306 /// - Implement `FnOnce(ThreadShare<T>)` - called once with shared data
307 /// - Implement `Send` - safe to send across thread boundaries
308 /// - Have `'static` lifetime - no borrowed references
309 ///
310 /// The type `T` must implement `Send + Sync + 'static`.
311 ///
312 /// ## Returns
313 ///
314 /// `Ok(())` on success, `Err(String)` if thread spawning fails.
315 ///
316 /// ## Example
317 ///
318 /// ```rust
319 /// use thread_share::EnhancedThreadShare;
320 ///
321 /// let enhanced = EnhancedThreadShare::new(0);
322 ///
323 /// // Spawn a worker thread
324 /// enhanced.spawn("worker", |data| {
325 /// for _ in 0..100 {
326 /// data.update(|x| *x += 1);
327 /// std::thread::sleep(std::time::Duration::from_millis(10));
328 /// }
329 /// }).expect("Failed to spawn worker");
330 ///
331 /// // Spawn a monitor thread
332 /// enhanced.spawn("monitor", |data| {
333 /// for _ in 0..10 {
334 /// std::thread::sleep(std::time::Duration::from_millis(100));
335 /// println!("Current value: {}", data.get());
336 /// }
337 /// }).expect("Failed to spawn monitor");
338 /// ```
339 pub fn spawn<F>(&self, name: &str, f: F) -> Result<(), String>
340 where
341 F: FnOnce(ThreadShare<T>) + Send + 'static,
342 T: Send + Sync + 'static,
343 {
344 let thread_name = name.to_string();
345 let thread_data = self.inner.clone();
346
347 let handle = thread::spawn(move || {
348 f(thread_data);
349 });
350
351 self.threads.lock().unwrap().insert(thread_name, handle);
352 Ok(())
353 }
354
355 /// Spawns multiple threads with different names and functions
356 ///
357 /// This method spawns multiple threads from a vector of configurations.
358 /// Each configuration contains a thread name and a function.
359 ///
360 /// ## Arguments
361 ///
362 /// * `thread_configs` - Vector of `(name, function)` tuples
363 ///
364 /// ## Requirements
365 ///
366 /// The function `F` must implement `Clone` in addition to the standard requirements.
367 ///
368 /// ## Returns
369 ///
370 /// `Ok(())` on success, `Err(String)` if any thread spawning fails.
371 /// ```
372 pub fn spawn_multiple<F>(&self, thread_configs: Vec<(&str, F)>) -> Result<(), String>
373 where
374 F: FnOnce(ThreadShare<T>) + Send + Clone + 'static,
375 T: Send + Sync + 'static,
376 {
377 for (name, func) in thread_configs {
378 self.spawn(name, func)?;
379 }
380 Ok(())
381 }
382
383 /// Spawns multiple threads with boxed closures
384 ///
385 /// This method spawns multiple threads using boxed closures, which allows
386 /// for different function types in the same vector.
387 ///
388 /// ## Arguments
389 ///
390 /// * `thread_configs` - Vector of `(name, boxed_function)` tuples
391 ///
392 /// ## Returns
393 ///
394 /// `Ok(())` on success, `Err(String)` if any thread spawning fails.
395 ///
396 /// ## Example
397 ///
398 /// ```rust
399 /// use thread_share::EnhancedThreadShare;
400 ///
401 /// let enhanced = EnhancedThreadShare::new(0);
402 ///
403 /// let configs = vec![
404 /// ("worker1", Box::new(|data: thread_share::ThreadShare<i32>| { data.update(|x| *x = *x + 1); }) as Box<dyn FnOnce(thread_share::ThreadShare<i32>) + Send>),
405 /// ("worker2", Box::new(|data: thread_share::ThreadShare<i32>| { data.update(|x| *x = *x + 2); }) as Box<dyn FnOnce(thread_share::ThreadShare<i32>) + Send>),
406 /// ];
407 ///
408 /// enhanced.spawn_multiple_boxed(configs).expect("Failed to spawn threads");
409 /// ```
410 pub fn spawn_multiple_boxed(
411 &self,
412 thread_configs: Vec<(&str, Box<dyn FnOnce(ThreadShare<T>) + Send>)>,
413 ) -> Result<(), String>
414 where
415 T: Send + Sync + 'static,
416 {
417 for (name, func) in thread_configs {
418 let thread_data = self.inner.clone();
419 let handle = thread::spawn(move || {
420 func(thread_data);
421 });
422 self.threads
423 .lock()
424 .unwrap()
425 .insert(name.to_string(), handle);
426 }
427 Ok(())
428 }
429
430 /// Waits for all spawned threads to complete
431 ///
432 /// This method blocks until all spawned threads have finished execution.
433 /// It joins each thread and returns an error if any thread panics.
434 ///
435 /// ## Returns
436 ///
437 /// `Ok(())` when all threads complete successfully, `Err(String)` if any thread fails.
438 ///
439 /// ## Example
440 ///
441 /// ```rust
442 /// use thread_share::EnhancedThreadShare;
443 ///
444 /// let enhanced = EnhancedThreadShare::new(0);
445 ///
446 /// enhanced.spawn("worker", |data| {
447 /// data.update(|x| *x = *x + 100);
448 /// }).expect("Failed to spawn worker");
449 ///
450 /// // Wait for all threads to complete
451 /// enhanced.join_all().expect("Thread execution failed");
452 ///
453 /// // Now safe to access the final result
454 /// assert_eq!(enhanced.get(), 100);
455 /// ```
456 pub fn join_all(&self) -> Result<(), String> {
457 let mut threads = self.threads.lock().unwrap();
458 let thread_handles: Vec<_> = threads.drain().collect();
459 drop(threads);
460
461 for (name, handle) in thread_handles {
462 let result = handle.join();
463 if let Err(e) = result {
464 return Err(format!("Thread '{}' failed: {:?}", name, e));
465 }
466 }
467 Ok(())
468 }
469
470 /// Gets the number of active threads
471 ///
472 /// This method returns the current number of threads that are still running.
473 ///
474 /// ## Returns
475 ///
476 /// The number of active threads.
477 ///
478 /// ## Example
479 ///
480 /// ```rust
481 /// use thread_share::EnhancedThreadShare;
482 /// use std::time::Duration;
483 ///
484 /// let enhanced = EnhancedThreadShare::new(0);
485 ///
486 /// enhanced.spawn("worker", |data| {
487 /// std::thread::sleep(Duration::from_millis(100));
488 /// }).expect("Failed to spawn worker");
489 ///
490 /// println!("Active threads: {}", enhanced.active_threads()); // Prints: 1
491 ///
492 /// // Wait for completion
493 /// enhanced.join_all().expect("Failed to join");
494 ///
495 /// println!("Active threads: {}", enhanced.active_threads()); // Prints: 0
496 /// ```
497 pub fn active_threads(&self) -> usize {
498 self.threads.lock().unwrap().len()
499 }
500
501 /// Checks if all threads have completed
502 ///
503 /// This method returns `true` if there are no active threads, `false` otherwise.
504 ///
505 /// ## Returns
506 ///
507 /// `true` if all threads have completed, `false` if any threads are still running.
508 ///
509 /// ## Example
510 ///
511 /// ```rust
512 /// use thread_share::EnhancedThreadShare;
513 ///
514 /// let enhanced = EnhancedThreadShare::new(0);
515 ///
516 /// enhanced.spawn("worker", |data| {
517 /// data.update(|x| *x = *x + 1);
518 /// }).expect("Failed to spawn worker");
519 ///
520 /// assert!(!enhanced.is_complete()); // Thread is still running
521 ///
522 /// enhanced.join_all().expect("Failed to join");
523 ///
524 /// assert!(enhanced.is_complete()); // All threads completed
525 /// ```
526 pub fn is_complete(&self) -> bool {
527 self.threads.lock().unwrap().is_empty()
528 }
529
530 /// Delegates all ThreadShare methods
531 ///
532 /// Gets a copy of the shared data.
533 ///
534 /// ## Requirements
535 ///
536 /// The type `T` must implement `Clone` trait.
537 ///
538 /// ## Returns
539 ///
540 /// A copy of the current data.
541 ///
542 /// ## Example
543 ///
544 /// ```rust
545 /// use thread_share::EnhancedThreadShare;
546 ///
547 /// let enhanced = EnhancedThreadShare::new(42);
548 /// let value = enhanced.get();
549 /// assert_eq!(value, 42);
550 /// ```
551 pub fn get(&self) -> T
552 where
553 T: Clone,
554 {
555 self.inner.get()
556 }
557
558 /// Sets new data and notifies waiting threads
559 ///
560 /// This method replaces the current data and notifies all threads
561 /// waiting for changes.
562 ///
563 /// ## Arguments
564 ///
565 /// * `new_data` - The new data to set
566 ///
567 /// ## Example
568 ///
569 /// ```rust
570 /// use thread_share::EnhancedThreadShare;
571 ///
572 /// let enhanced = EnhancedThreadShare::new(0);
573 /// enhanced.set(100);
574 /// assert_eq!(enhanced.get(), 100);
575 /// ```
576 pub fn set(&self, new_data: T) {
577 self.inner.set(new_data);
578 }
579
580 pub fn update<F>(&self, f: F)
581 where
582 F: FnOnce(&mut T),
583 {
584 self.inner.update(f);
585 }
586
587 pub fn read<F, R>(&self, f: F) -> R
588 where
589 F: FnOnce(&T) -> R,
590 {
591 self.inner.read(f)
592 }
593
594 pub fn write<F, R>(&self, f: F) -> R
595 where
596 F: FnOnce(&mut T) -> R,
597 {
598 self.inner.write(f)
599 }
600
601 pub fn wait_for_change(&self, timeout: std::time::Duration) -> bool {
602 self.inner.wait_for_change(timeout)
603 }
604
605 pub fn wait_for_change_forever(&self) {
606 self.inner.wait_for_change_forever();
607 }
608
609 pub fn clone(&self) -> Self {
610 Self {
611 inner: self.inner.clone(),
612 threads: Arc::new(Mutex::new(HashMap::new())),
613 }
614 }
615}
616
617impl<T> Clone for EnhancedThreadShare<T> {
618 fn clone(&self) -> Self {
619 self.clone()
620 }
621}
622
623/// Macro for creating enhanced thread share with automatic thread management
624#[macro_export]
625macro_rules! enhanced_share {
626 ($data:expr) => {
627 $crate::enhanced::EnhancedThreadShare::new($data)
628 };
629}
630
631/// Macro for simplified multi-threaded setup
632#[macro_export]
633macro_rules! spawn_workers {
634 ($shared:expr, { $($name:ident: $func:expr),* }) => {
635 {
636 $(
637 $shared.spawn(stringify!($name), $func).expect(&format!("Failed to spawn {}", stringify!($name)));
638 )*
639 }
640 };
641}