Skip to content

Instantly share code, notes, and snippets.

@tylerstillwater
Last active July 18, 2019 20:57
Show Gist options
  • Save tylerstillwater/7da6cc6c2180f48da66f64af0f7cd428 to your computer and use it in GitHub Desktop.
Save tylerstillwater/7da6cc6c2180f48da66f64af0f7cd428 to your computer and use it in GitHub Desktop.
Simulate io blocking
// All material is licensed under the Apache License Version 2.0, January 2004
// http://www.apache.org/licenses/LICENSE-2.0
// This sample program demonstrates how the logger package works.
package main
import (
"fmt"
"log"
"os"
"os/signal"
"sync/atomic"
"time"
)
type device struct {
blocking int32
toggle int32
}
// toggleBlocking will toggle the blocking state of this device
func (d *device) toggleBlocking() {
toggle := 1 - d.toggle
atomic.CompareAndSwapInt32(&d.blocking, d.toggle, toggle)
d.toggle = toggle
}
// wait will wait until the device is ready for use
func (d *device) wait() {
for atomic.LoadInt32(&d.blocking) == 1 {
time.Sleep(100 * time.Millisecond)
}
}
// writer allows us to mock a writer we write logs to.
type writer struct {
d *device
}
// Write implements the io.Writer interface.
func (w *writer) Write(p []byte) (n int, err error) {
w.d.wait()
fmt.Print(string(p))
return len(p), nil
}
func main() {
// Number of goroutines that will be writing logs.
const grs = 10
// Create a logger value with a buffer of capacity
// for each goroutine that will be logging.
var d device
w := writer{d: &d}
l := log.New(&w, "prefix", 0)
// Generate goroutines, each writing to disk.
for i := 0; i < grs; i++ {
go func(id int) {
for {
l.Println(fmt.Sprintf("%d: log data", id))
time.Sleep(100 * time.Millisecond)
}
}(i)
}
// We want to control the simulated disk blocking. Capture
// interrupt signals to toggle device issues. Use <ctrl> z
// to kill the program.
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
for {
<-sigChan
d.toggleBlocking()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment