いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-125 (どれか一つが完了したら完了するコンテキスト, WhenAny)

概要

以前チャネルで同じような動きするものを記事にしました。

devlights.hatenablog.com

context.Contextを受けるバージョンもついでに作成。中で上の記事で作った関数を呼んでいるだけですがw

サンプル

package ctxs

import (
    "context"

    "github.com/devlights/gomy/chans"
)

// WhenAny は、chans.WhenAny() の context.Context 版です.
//
// 指定したコンテキストのどれかが完了したら完了となる context.Context を生成して返します.
//
// Example:
//
//         <-ctxs.WhenAny(procCtx, ctx1, ctx2, ctx3).Done()
//
func WhenAny(pCtx context.Context, c ...context.Context) context.Context {
    ctx, cancel := context.WithCancel(pCtx)
    go func(dones []<-chan struct{}) {
        defer cancel()

        select {
        case <-ctx.Done():
        case <-chans.WhenAny(dones...):
        }
    }(ToDoneCh(c...))
    return ctx
}

gomy/whenany.go at master · devlights/gomy · GitHub

実行イメージは以下の感じ

package ctxs_test

import (
    "context"
    "fmt"
    "testing"
    "time"

    "github.com/devlights/gomy/ctxs"
)

func ExampleWhenAny() {
    var (
        rootCtx             = context.Background()
        mainCtx, mainCancel = context.WithCancel(rootCtx)
        procCtx, procCancel = context.WithTimeout(mainCtx, 1*time.Second)
    )

    defer mainCancel()
    defer procCancel()

    ctx1 := ctxs.StartGoroutine(procCtx, 100*time.Millisecond)
    ctx2 := ctxs.StartGoroutine(procCtx, 200*time.Millisecond)
    ctx3 := ctxs.StartGoroutine(procCtx, 300*time.Millisecond)

    start := time.Now()
    <-ctxs.WhenAny(procCtx, ctx1, ctx2, ctx3).Done()
    elapsed := time.Since(start)

    fmt.Printf("elapsed: %vmsec\n", elapsed.Milliseconds())

    // Output:
    // elapsed: 100msec
}

gomy/whenany_test.go at master · devlights/gomy · GitHub

$ go test ./ctxs/ -v -run "^ExampleWhenAny$"
=== RUN   ExampleWhenAny
--- PASS: ExampleWhenAny (0.10s)
PASS
ok      github.com/devlights/gomy/ctxs  0.102s

最初に完了したタスクの時間で完了していますね。


過去の記事については、以下のページからご参照下さい。

  • いろいろ備忘録日記まとめ

devlights.github.io

サンプルコードは、以下の場所で公開しています。

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com