From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- libgo/go/time/sleep.go | 151 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 libgo/go/time/sleep.go (limited to 'libgo/go/time/sleep.go') diff --git a/libgo/go/time/sleep.go b/libgo/go/time/sleep.go new file mode 100644 index 000000000..3538775ad --- /dev/null +++ b/libgo/go/time/sleep.go @@ -0,0 +1,151 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package time + +import ( + "os" + "syscall" + "sync" + "container/heap" +) + +// The event type represents a single After or AfterFunc event. +type event struct { + t int64 // The absolute time that the event should fire. + f func(int64) // The function to call when the event fires. + sleeping bool // A sleeper is sleeping for this event. +} + +type eventHeap []*event + +var events eventHeap +var eventMutex sync.Mutex + +func init() { + events.Push(&event{1 << 62, nil, true}) // sentinel +} + +// Sleep pauses the current goroutine for at least ns nanoseconds. +// Higher resolution sleeping may be provided by syscall.Nanosleep +// on some operating systems. +func Sleep(ns int64) os.Error { + _, err := sleep(Nanoseconds(), ns) + return err +} + +// sleep takes the current time and a duration, +// pauses for at least ns nanoseconds, and +// returns the current time and an error. +func sleep(t, ns int64) (int64, os.Error) { + // TODO(cw): use monotonic-time once it's available + end := t + ns + for t < end { + errno := syscall.Sleep(end - t) + if errno != 0 && errno != syscall.EINTR { + return 0, os.NewSyscallError("sleep", errno) + } + t = Nanoseconds() + } + return t, nil +} + +// After waits at least ns nanoseconds before sending the current time +// on the returned channel. +func After(ns int64) <-chan int64 { + c := make(chan int64, 1) + after(ns, func(t int64) { c <- t }) + return c +} + +// AfterFunc waits at least ns nanoseconds before calling f +// in its own goroutine. +func AfterFunc(ns int64, f func()) { + after(ns, func(_ int64) { + go f() + }) +} + +// after is the implementation of After and AfterFunc. +// When the current time is after ns, it calls f with the current time. +// It assumes that f will not block. +func after(ns int64, f func(int64)) { + t := Nanoseconds() + ns + eventMutex.Lock() + t0 := events[0].t + heap.Push(events, &event{t, f, false}) + if t < t0 { + go sleeper() + } + eventMutex.Unlock() +} + +// sleeper continually looks at the earliest event in the queue, marks it +// as sleeping, waits until it happens, then removes any events +// in the queue that are due. It stops when it finds an event that is +// already marked as sleeping. When an event is inserted before the first item, +// a new sleeper is started. +// +// Scheduling vagaries mean that sleepers may not wake up in +// exactly the order of the events that they are waiting for, +// but this does not matter as long as there are at least as +// many sleepers as events marked sleeping (invariant). This ensures that +// there is always a sleeper to service the remaining events. +// +// A sleeper will remove at least the event it has been waiting for +// unless the event has already been removed by another sleeper. Both +// cases preserve the invariant described above. +func sleeper() { + eventMutex.Lock() + e := events[0] + for !e.sleeping { + t := Nanoseconds() + if dt := e.t - t; dt > 0 { + e.sleeping = true + eventMutex.Unlock() + if nt, err := sleep(t, dt); err != nil { + // If sleep has encountered an error, + // there's not much we can do. We pretend + // that time really has advanced by the required + // amount and lie to the rest of the system. + t = e.t + } else { + t = nt + } + eventMutex.Lock() + e = events[0] + } + for t >= e.t { + e.f(t) + heap.Pop(events) + e = events[0] + } + } + eventMutex.Unlock() +} + +func (eventHeap) Len() int { + return len(events) +} + +func (eventHeap) Less(i, j int) bool { + return events[i].t < events[j].t +} + +func (eventHeap) Swap(i, j int) { + events[i], events[j] = events[j], events[i] +} + +func (eventHeap) Push(x interface{}) { + events = append(events, x.(*event)) +} + +func (eventHeap) Pop() interface{} { + // TODO: possibly shrink array. + n := len(events) - 1 + e := events[n] + events[n] = nil + events = events[0:n] + return e +} -- cgit v1.2.3