@@ -64,6 +64,7 @@ import (
64
64
"io"
65
65
"os"
66
66
"sync"
67
+ "sync/atomic"
67
68
"time"
68
69
)
69
70
@@ -245,7 +246,7 @@ type Pin struct {
245
246
message string
246
247
messageMu sync.RWMutex
247
248
stopChan chan struct {}
248
- isRunning bool
249
+ isRunning int32
249
250
spinnerColor Color
250
251
textColor Color
251
252
doneSymbol rune
@@ -298,25 +299,25 @@ func New(message string, opts ...Option) *Pin {
298
299
// Note: Canceling the returned function stops the spinner without printing
299
300
// a final message. To print a final message, use the Stop() method.
300
301
func (p * Pin ) Start (ctx context.Context ) context.CancelFunc {
301
- if p .isRunning {
302
+ if p .IsRunning () {
302
303
return func () {}
303
304
}
304
305
305
306
if ! isTerminal (p .out ) {
306
307
ctx , cancel := context .WithCancel (ctx )
307
- p .isRunning = true
308
+ p .setRunning ( true )
308
309
p .messageMu .RLock ()
309
310
msg := p .message
310
311
p .messageMu .RUnlock ()
311
312
_ , _ = fmt .Fprintln (p .out , msg )
312
313
go func () {
313
314
<- ctx .Done ()
314
- p .isRunning = false
315
+ p .setRunning ( false )
315
316
}()
316
317
return cancel
317
318
}
318
319
319
- p .isRunning = true
320
+ p .setRunning ( true )
320
321
321
322
ctx , cancel := context .WithCancel (ctx )
322
323
ticker := time .NewTicker (100 * time .Millisecond )
@@ -329,7 +330,7 @@ func (p *Pin) Start(ctx context.Context) context.CancelFunc {
329
330
case <- p .stopChan :
330
331
return
331
332
case <- ctx .Done ():
332
- p .isRunning = false
333
+ p .setRunning ( false )
333
334
_ , _ = fmt .Fprint (p .out , "\r \033 [K" )
334
335
return
335
336
case <- ticker .C :
@@ -369,15 +370,15 @@ func (p *Pin) Start(ctx context.Context) context.CancelFunc {
369
370
370
371
// Stop halts the spinner animation and optionally displays a final message.
371
372
func (p * Pin ) Stop (message ... string ) {
372
- if ! p .isRunning {
373
+ if ! p .IsRunning () {
373
374
return
374
375
}
375
376
376
377
if p .handleNonTerminal (message ... ) {
377
378
return
378
379
}
379
380
380
- p .isRunning = false
381
+ p .setRunning ( false )
381
382
p .stopChan <- struct {}{}
382
383
p .wg .Wait ()
383
384
@@ -391,15 +392,15 @@ func (p *Pin) Stop(message ...string) {
391
392
// Fail halts the spinner animation and displays a failure message.
392
393
// This method is similar to Stop but uses a distinct symbol and color scheme to indicate an error state.
393
394
func (p * Pin ) Fail (message ... string ) {
394
- if ! p .isRunning {
395
+ if ! p .IsRunning () {
395
396
return
396
397
}
397
398
398
399
if p .handleNonTerminal (message ... ) {
399
400
return
400
401
}
401
402
402
- p .isRunning = false
403
+ p .setRunning ( false )
403
404
p .stopChan <- struct {}{}
404
405
p .wg .Wait ()
405
406
@@ -412,7 +413,7 @@ func (p *Pin) Fail(message ...string) {
412
413
413
414
// UpdateMessage changes the message shown next to the spinner.
414
415
func (p * Pin ) UpdateMessage (message string ) {
415
- if ! p .isRunning {
416
+ if ! p .IsRunning () {
416
417
return
417
418
}
418
419
@@ -508,7 +509,7 @@ func (p *Pin) handleNonTerminal(message ...string) bool {
508
509
if len (message ) > 0 {
509
510
_ , _ = fmt .Fprintln (p .out , message [0 ])
510
511
}
511
- p .isRunning = false
512
+ p .setRunning ( false )
512
513
return true
513
514
}
514
515
return false
@@ -521,5 +522,14 @@ func (p *Pin) Message() string {
521
522
522
523
// IsRunning returns whether the spinner is active.
523
524
func (p * Pin ) IsRunning () bool {
524
- return p .isRunning
525
+ return atomic .LoadInt32 (& p .isRunning ) == 1
526
+ }
527
+
528
+ // setRunning sets the running state of the spinner.
529
+ func (p * Pin ) setRunning (running bool ) {
530
+ var val int32
531
+ if running {
532
+ val = 1
533
+ }
534
+ atomic .StoreInt32 (& p .isRunning , val )
525
535
}
0 commit comments