Skip to content

Commit 84d96c7

Browse files
committed
feat!: Make messaging functions thread-safe by taking shared borrow and requring Sync.
That way it's possible to share the `RawProgress` object across threads and emit messages, much like a logging system that's more integrated with rendering.
1 parent 8941f4b commit 84d96c7

File tree

5 files changed

+49
-39
lines changed

5 files changed

+49
-39
lines changed

src/progress/log.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl Progress for Log {
136136
self.id
137137
}
138138

139-
fn message(&mut self, level: MessageLevel, message: impl Into<String>) {
139+
fn message(&self, level: MessageLevel, message: impl Into<String>) {
140140
let message: String = message.into();
141141
match level {
142142
MessageLevel::Info => log::info!("ℹ{} → {}", self.name, message),

src/progress/utils.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl Progress for Discard {
3838
crate::progress::UNKNOWN
3939
}
4040

41-
fn message(&mut self, _level: MessageLevel, _message: impl Into<String>) {}
41+
fn message(&self, _level: MessageLevel, _message: impl Into<String>) {}
4242

4343
fn counter(&self) -> Option<StepShared> {
4444
None
@@ -144,7 +144,7 @@ where
144144
todo!()
145145
}
146146

147-
fn message(&mut self, level: MessageLevel, message: impl Into<String>) {
147+
fn message(&self, level: MessageLevel, message: impl Into<String>) {
148148
match self {
149149
Either::Left(l) => l.message(level, message),
150150
Either::Right(r) => r.message(level, message),
@@ -247,7 +247,7 @@ where
247247
self.0.id()
248248
}
249249

250-
fn message(&mut self, level: MessageLevel, message: impl Into<String>) {
250+
fn message(&self, level: MessageLevel, message: impl Into<String>) {
251251
self.0.message(level, message)
252252
}
253253

@@ -321,7 +321,7 @@ impl<T: Progress> Progress for ThroughputOnDrop<T> {
321321
self.0.id()
322322
}
323323

324-
fn message(&mut self, level: MessageLevel, message: impl Into<String>) {
324+
fn message(&self, level: MessageLevel, message: impl Into<String>) {
325325
self.0.message(level, message)
326326
}
327327

src/traits.rs

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::time::Instant;
33
use crate::{messages::MessageLevel, progress, progress::Id, Unit};
44

55
/// A trait for describing hierarchical progress.
6-
pub trait Progress: Send {
6+
pub trait Progress: Send + Sync {
77
/// The type of progress returned by [`add_child()`][Progress::add_child()].
88
type SubProgress: Progress;
99

@@ -87,7 +87,7 @@ pub trait Progress: Send {
8787
///
8888
/// Use this to provide additional,human-readable information about the progress
8989
/// made, including indicating success or failure.
90-
fn message(&mut self, level: MessageLevel, message: impl Into<String>);
90+
fn message(&self, level: MessageLevel, message: impl Into<String>);
9191

9292
/// If available, return an atomic counter for direct access to the underlying state.
9393
///
@@ -98,19 +98,19 @@ pub trait Progress: Send {
9898
}
9999

100100
/// Create a message providing additional information about the progress thus far.
101-
fn info(&mut self, message: impl Into<String>) {
101+
fn info(&self, message: impl Into<String>) {
102102
self.message(MessageLevel::Info, message)
103103
}
104104
/// Create a message indicating the task is done successfully
105-
fn done(&mut self, message: impl Into<String>) {
105+
fn done(&self, message: impl Into<String>) {
106106
self.message(MessageLevel::Success, message)
107107
}
108108
/// Create a message indicating the task failed
109-
fn fail(&mut self, message: impl Into<String>) {
109+
fn fail(&self, message: impl Into<String>) {
110110
self.message(MessageLevel::Failure, message)
111111
}
112112
/// A shorthand to print throughput information
113-
fn show_throughput(&mut self, start: Instant) {
113+
fn show_throughput(&self, start: Instant) {
114114
let step = self.step();
115115
match self.unit() {
116116
Some(unit) => self.show_throughput_with(start, step, unit, MessageLevel::Info),
@@ -126,7 +126,7 @@ pub trait Progress: Send {
126126
}
127127

128128
/// A shorthand to print throughput information, with the given step and unit, and message level.
129-
fn show_throughput_with(&mut self, start: Instant, step: progress::Step, unit: Unit, level: MessageLevel) {
129+
fn show_throughput_with(&self, start: Instant, step: progress::Step, unit: Unit, level: MessageLevel) {
130130
use std::fmt::Write;
131131
let elapsed = start.elapsed().as_secs_f32();
132132
let steps_per_second = (step as f32 / elapsed) as progress::Step;
@@ -159,7 +159,7 @@ pub trait Progress: Send {
159159
/// It differs by not being able to add child progress dynamically, but in turn is object safe. It's recommended to
160160
/// use this trait whenever there is no need to add child progress, at the leaf of a computation.
161161
// NOTE: keep this in-sync with `Progress`.
162-
pub trait RawProgress: Send {
162+
pub trait RawProgress: Send + Sync {
163163
/// Initialize the Item for receiving progress information.
164164
///
165165
/// If `max` is `Some(…)`, it will be treated as upper bound. When progress is [set(…)](./struct.Item.html#method.set)
@@ -227,7 +227,7 @@ pub trait RawProgress: Send {
227227
///
228228
/// Use this to provide additional,human-readable information about the progress
229229
/// made, including indicating success or failure.
230-
fn message(&mut self, level: MessageLevel, message: String);
230+
fn message(&self, level: MessageLevel, message: String);
231231

232232
/// If available, return an atomic counter for direct access to the underlying state.
233233
///
@@ -238,19 +238,19 @@ pub trait RawProgress: Send {
238238
}
239239

240240
/// Create a message providing additional information about the progress thus far.
241-
fn info(&mut self, message: String) {
241+
fn info(&self, message: String) {
242242
self.message(MessageLevel::Info, message)
243243
}
244244
/// Create a message indicating the task is done successfully
245-
fn done(&mut self, message: String) {
245+
fn done(&self, message: String) {
246246
self.message(MessageLevel::Success, message)
247247
}
248248
/// Create a message indicating the task failed
249-
fn fail(&mut self, message: String) {
249+
fn fail(&self, message: String) {
250250
self.message(MessageLevel::Failure, message)
251251
}
252252
/// A shorthand to print throughput information
253-
fn show_throughput(&mut self, start: Instant) {
253+
fn show_throughput(&self, start: Instant) {
254254
let step = self.step();
255255
match self.unit() {
256256
Some(unit) => self.show_throughput_with(start, step, unit, MessageLevel::Info),
@@ -266,7 +266,7 @@ pub trait RawProgress: Send {
266266
}
267267

268268
/// A shorthand to print throughput information, with the given step and unit, and message level.
269-
fn show_throughput_with(&mut self, start: Instant, step: progress::Step, unit: Unit, level: MessageLevel) {
269+
fn show_throughput_with(&self, start: Instant, step: progress::Step, unit: Unit, level: MessageLevel) {
270270
use std::fmt::Write;
271271
let elapsed = start.elapsed().as_secs_f32();
272272
let steps_per_second = (step as f32 / elapsed) as progress::Step;
@@ -400,31 +400,31 @@ mod impls {
400400
<T as Progress>::id(self)
401401
}
402402

403-
fn message(&mut self, level: MessageLevel, message: String) {
403+
fn message(&self, level: MessageLevel, message: String) {
404404
<T as Progress>::message(self, level, message)
405405
}
406406

407407
fn counter(&self) -> Option<StepShared> {
408408
<T as Progress>::counter(self)
409409
}
410410

411-
fn info(&mut self, message: String) {
411+
fn info(&self, message: String) {
412412
<T as Progress>::info(self, message)
413413
}
414414

415-
fn done(&mut self, message: String) {
415+
fn done(&self, message: String) {
416416
<T as Progress>::done(self, message)
417417
}
418418

419-
fn fail(&mut self, message: String) {
419+
fn fail(&self, message: String) {
420420
<T as Progress>::fail(self, message)
421421
}
422422

423-
fn show_throughput(&mut self, start: Instant) {
423+
fn show_throughput(&self, start: Instant) {
424424
<T as Progress>::show_throughput(self, start)
425425
}
426426

427-
fn show_throughput_with(&mut self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
427+
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
428428
<T as Progress>::show_throughput_with(self, start, step, unit, level)
429429
}
430430
}
@@ -487,32 +487,32 @@ mod impls {
487487
self.deref().id()
488488
}
489489

490-
fn message(&mut self, level: MessageLevel, message: impl Into<String>) {
491-
self.deref_mut().message(level, message)
490+
fn message(&self, level: MessageLevel, message: impl Into<String>) {
491+
self.deref().message(level, message)
492492
}
493493

494494
fn counter(&self) -> Option<StepShared> {
495495
self.deref().counter()
496496
}
497497

498-
fn info(&mut self, message: impl Into<String>) {
499-
self.deref_mut().info(message)
498+
fn info(&self, message: impl Into<String>) {
499+
self.deref().info(message)
500500
}
501501

502-
fn done(&mut self, message: impl Into<String>) {
503-
self.deref_mut().done(message)
502+
fn done(&self, message: impl Into<String>) {
503+
self.deref().done(message)
504504
}
505505

506-
fn fail(&mut self, message: impl Into<String>) {
507-
self.deref_mut().fail(message)
506+
fn fail(&self, message: impl Into<String>) {
507+
self.deref().fail(message)
508508
}
509509

510-
fn show_throughput(&mut self, start: Instant) {
511-
self.deref_mut().show_throughput(start)
510+
fn show_throughput(&self, start: Instant) {
511+
self.deref().show_throughput(start)
512512
}
513513

514-
fn show_throughput_with(&mut self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
515-
self.deref_mut().show_throughput_with(start, step, unit, level)
514+
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
515+
self.deref().show_throughput_with(start, step, unit, level)
516516
}
517517
}
518518
}

src/tree/item.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ impl Item {
292292
///
293293
/// Use this to provide additional,human-readable information about the progress
294294
/// made, including indicating success or failure.
295-
pub fn message(&mut self, level: MessageLevel, message: impl Into<String>) {
295+
pub fn message(&self, level: MessageLevel, message: impl Into<String>) {
296296
let message: String = message.into();
297297
self.messages.lock().push_overwrite(
298298
level,
@@ -396,7 +396,7 @@ impl crate::Progress for Item {
396396
Item::id(self)
397397
}
398398

399-
fn message(&mut self, level: MessageLevel, message: impl Into<String>) {
399+
fn message(&self, level: MessageLevel, message: impl Into<String>) {
400400
Item::message(self, level, message)
401401
}
402402

tests/raw_progress/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,13 @@ fn dyn_safe() {
99
let mut child_of_child = child.add_child("there");
1010
needs_dyn(&mut child_of_child);
1111
}
12+
13+
#[test]
14+
fn thread_safe() {
15+
fn needs_send<'a, T: Send + 'a>(_p: T) {}
16+
let root = prodash::tree::Root::new();
17+
let mut child = root.add_child("hello");
18+
needs_send(&child);
19+
let child_of_child = child.add_child("there");
20+
needs_send(&child_of_child);
21+
}

0 commit comments

Comments
 (0)