A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
113
Task/History-variables/Go/history-variables.go
Normal file
113
Task/History-variables/Go/history-variables.go
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// data type for history variable (its an int)
|
||||
type history struct {
|
||||
timestamp tsFunc
|
||||
hs []hset
|
||||
}
|
||||
|
||||
// data type for timestamp generator
|
||||
type tsFunc func() time.Time
|
||||
|
||||
// data type for a "set" event
|
||||
type hset struct {
|
||||
int // new value
|
||||
t time.Time // timestamp
|
||||
}
|
||||
|
||||
// newHistory creates a history variable
|
||||
func newHistory(ts tsFunc) history {
|
||||
return history{ts, []hset{{t: ts()}}}
|
||||
}
|
||||
|
||||
// int returns the current value
|
||||
func (h history) int() int {
|
||||
return h.hs[len(h.hs)-1].int
|
||||
}
|
||||
|
||||
// set does what you expect and returns the timestamp recorded for the event
|
||||
func (h *history) set(x int) time.Time {
|
||||
t := h.timestamp()
|
||||
h.hs = append(h.hs, hset{x, t})
|
||||
return t
|
||||
}
|
||||
|
||||
// dump displays a complete history
|
||||
func (h history) dump() {
|
||||
for _, hs := range h.hs {
|
||||
fmt.Println(hs.t.Format(time.StampNano), hs.int)
|
||||
}
|
||||
}
|
||||
|
||||
// recall recalls the value stored in the history variable at time t.
|
||||
// if the variable had not been created yet, ok is false.
|
||||
func (h history) recall(t time.Time) (int, /*ok*/ bool) {
|
||||
i := sort.Search(len(h.hs), func(i int) bool {
|
||||
return h.hs[i].t.After(t)
|
||||
})
|
||||
if i > 0 {
|
||||
return h.hs[i-1].int, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// newTimestamper returns a function that generates unique timestamps.
|
||||
// Use a single timestamper for multiple history variables to preserve
|
||||
// an unambiguous sequence of assignments across the multiple history
|
||||
// variables within a single goroutine.
|
||||
func newTimestamper() tsFunc {
|
||||
var last time.Time
|
||||
return func() time.Time {
|
||||
if t := time.Now(); t.After(last) {
|
||||
last = t
|
||||
} else {
|
||||
last.Add(1)
|
||||
}
|
||||
return last
|
||||
}
|
||||
}
|
||||
|
||||
// newProtectedTimestamper generates unique timestamps for concurrent
|
||||
// goroutines.
|
||||
func newProtectedTimestamper() tsFunc {
|
||||
var last time.Time
|
||||
var m sync.Mutex
|
||||
return func() (t time.Time) {
|
||||
t = time.Now()
|
||||
m.Lock() // m protects last
|
||||
if t.After(last) {
|
||||
last = t
|
||||
} else {
|
||||
last.Add(1)
|
||||
t = last
|
||||
}
|
||||
m.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// enable history variable support appropriate for single goroutine.
|
||||
ts := newTimestamper()
|
||||
// define a history variable
|
||||
h := newHistory(ts)
|
||||
// assign three values. (timestamps kept for future reference.)
|
||||
ref := []time.Time{h.set(3), h.set(1), h.set(4)}
|
||||
// non-destructively display history
|
||||
fmt.Println("History of variable h:")
|
||||
h.dump()
|
||||
// recall the three values. (this is non-destructive as well, but
|
||||
// different than the dump in that values are recalled by time.)
|
||||
fmt.Println("Recalling values:")
|
||||
for _, t := range ref {
|
||||
rv, _ := h.recall(t)
|
||||
fmt.Println(rv)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue