| // Copyright 2024 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 http_test | |
| import ( | |
| "errors" | |
| "internal/synctest" | |
| ) | |
| var errStillRunning = errors.New("async op still running") | |
| type asyncResult[T any] struct { | |
| donec chan struct{} | |
| res T | |
| err error | |
| } | |
| // runAsync runs f in a new goroutine. | |
| // It returns an asyncResult which acts as a future. | |
| // | |
| // Must be called from within a synctest bubble. | |
| func runAsync[T any](f func() (T, error)) *asyncResult[T] { | |
| r := &asyncResult[T]{ | |
| donec: make(chan struct{}), | |
| } | |
| go func() { | |
| defer close(r.donec) | |
| r.res, r.err = f() | |
| }() | |
| synctest.Wait() | |
| return r | |
| } | |
| // done reports whether the function has returned. | |
| func (r *asyncResult[T]) done() bool { | |
| _, err := r.result() | |
| return err != errStillRunning | |
| } | |
| // result returns the result of the function. | |
| // If the function hasn't completed yet, it returns errStillRunning. | |
| func (r *asyncResult[T]) result() (T, error) { | |
| select { | |
| case <-r.donec: | |
| return r.res, r.err | |
| default: | |
| var zero T | |
| return zero, errStillRunning | |
| } | |
| } | |