oselect

package module
v0.0.0-...-5951712 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 14, 2022 License: MIT Imports: 0 Imported by: 0

README

Ordered Select

This implements deterministic select for go1.18+. Two to 9 channels, plus a default case, are suppported. It utilizes the ast package for code generation & 1.18 generics to allow reading from arbitrary channel types.

Go Reference

To get started:

go get jonwillia.ms/oselect

FAQ

  1. Can I mix and match sends and receives?

    Use the Select family of functions.

  2. Would variadic templates remove the need for generating a function for every N-terms?

    No, because there's no way to generate a select block for an arbitrary number of of channels at compile time.

  3. Which functions perform best?

    The Recv/Send families appear to be faster that the general purpose Select family.

    go test -benchmem -bench '.'                                                                 main  ✭
    goos: linux
    goarch: amd64
    pkg: jonwillia.ms/oselect
    cpu: AMD Ryzen 7 2700X Eight-Core Processor         
    BenchmarkRecv4Default-16                           	 4983958	       236.3 ns/op	       0 B/op	       0 allocs/op
    BenchmarkSelect4Default_Recv-16                    	 2180769	       540.7 ns/op	      96 B/op	       4 allocs/op
    BenchmarkSelect4Default_Recv_preroll-16            	 4211283	       280.6 ns/op	       0 B/op	       0 allocs/op
    Benchmark_select_4_default-16                      	 5084107	       228.1 ns/op	       0 B/op	       0 allocs/op
    Benchmark_reflectDotSelect_4_default_preroll-16    	  592192	      2014 ns/op	     632 B/op	      23 allocs/op
    BenchmarkRecv4-16                                  	 4384048	       256.5 ns/op	       0 B/op	       0 allocs/op
    BenchmarkSelect4_Recv-16                           	 1925407	       585.1 ns/op	      96 B/op	       4 allocs/op
    BenchmarkSelect4_RecvOK-16                         	 3690008	       323.5 ns/op	       0 B/op	       0 allocs/op
    BenchmarkSelect4_Recv_preroll-16                   	 3730765	       316.2 ns/op	       0 B/op	       0 allocs/op
    Benchmark_select_4-16                              	 4705082	       255.5 ns/op	       0 B/op	       0 allocs/op
    PASS
    ok  	jonwillia.ms/oselect	14.923s
    
  4. The generated code for the Select functions is ugly.

    That isn't a question!

  5. Doesn't select just use selectgo under the hood anyway? Why not use reflect.Select?

    I believe it does. It looks like the compiler uses looping constructs under the hood for non-trivial cases.

    // The compiler rewrites selects that statically have
    // only 0 or 1 cases plus default into simpler constructs.
    

    Check out the benchmark for Benchmark_reflectDotSelect_4_default_preroll. Oof!

Documentation

Overview

Package oselect allows deterministic ordering for case labels in select statements. For example this contrived example of trying to prioritize ui events in a loop:

func busyLoop(ctx context.Context, uiMessages, ircMessages, twitterMessages chan <-any) {
	for {
		select {
		case <-ctx.Done():
			return
		default:
		}
		select {
		case <-ctx.Done():
			return
		case msg := <-uiMessages:
			dispatchEvent(msg)
			continue
		default:
		}
		select {
		case <-ctx.Done():
			return
		case msg := <-uiMessages:
			dispatchEvent(msg)
			continue
		case msg := <-ircMessages:
			dispatchIRC(msg)
			continue
		default:
		}
		select {
		case <-ctx.Done():
			return
		case msg := <-uiMessages:
			dispatchEvent(msg)
		case msg := <-ircMessages:
			dispatchIRC(msg)
		case msg := <-twitterMessages:
			dispatchTwitter(msg)
		}
	}
}

becomes:

func busyLoop(ctx context.Context, uiMessages, ircMessages, twitterMessages chan <-any) {
	for {
		var done bool
		Recv4(
			ctx.Done(), func() { done = true },
			uiMessages, dispatchEvent,
			ircMessages, dispatchIRC,
			twitterMessages, dispatchTwitter,
		)
		if done {
			return
		}
	}
}

Whether or not this is useful is left as an exercise to the reader.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Recv2

func Recv2[T0, T1 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1))

func Recv2Default

func Recv2Default[T0, T1 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), df func())

func Recv3

func Recv3[T0, T1, T2 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2))

func Recv3Default

func Recv3Default[T0, T1, T2 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), df func())

func Recv4

func Recv4[T0, T1, T2, T3 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3))

func Recv4Default

func Recv4Default[T0, T1, T2, T3 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), df func())

func Recv5

func Recv5[T0, T1, T2, T3, T4 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4))

func Recv5Default

func Recv5Default[T0, T1, T2, T3, T4 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), df func())

func Recv6

func Recv6[T0, T1, T2, T3, T4, T5 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), c5 <-chan T5, f5 func(T5))

func Recv6Default

func Recv6Default[T0, T1, T2, T3, T4, T5 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), c5 <-chan T5, f5 func(T5), df func())

func Recv7

func Recv7[T0, T1, T2, T3, T4, T5, T6 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), c5 <-chan T5, f5 func(T5), c6 <-chan T6, f6 func(T6))

func Recv7Default

func Recv7Default[T0, T1, T2, T3, T4, T5, T6 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), c5 <-chan T5, f5 func(T5), c6 <-chan T6, f6 func(T6), df func())

func Recv8

func Recv8[T0, T1, T2, T3, T4, T5, T6, T7 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), c5 <-chan T5, f5 func(T5), c6 <-chan T6, f6 func(T6), c7 <-chan T7, f7 func(T7))

func Recv8Default

func Recv8Default[T0, T1, T2, T3, T4, T5, T6, T7 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), c5 <-chan T5, f5 func(T5), c6 <-chan T6, f6 func(T6), c7 <-chan T7, f7 func(T7), df func())

func Recv9

func Recv9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), c5 <-chan T5, f5 func(T5), c6 <-chan T6, f6 func(T6), c7 <-chan T7, f7 func(T7), c8 <-chan T8, f8 func(T8))

func Recv9Default

func Recv9Default[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](c0 <-chan T0, f0 func(T0), c1 <-chan T1, f1 func(T1), c2 <-chan T2, f2 func(T2), c3 <-chan T3, f3 func(T3), c4 <-chan T4, f4 func(T4), c5 <-chan T5, f5 func(T5), c6 <-chan T6, f6 func(T6), c7 <-chan T7, f7 func(T7), c8 <-chan T8, f8 func(T8), df func())

func RecvOK2

func RecvOK2[T0, T1 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool))

func RecvOK2Default

func RecvOK2Default[T0, T1 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), df func())

func RecvOK3

func RecvOK3[T0, T1, T2 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool))

func RecvOK3Default

func RecvOK3Default[T0, T1, T2 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), df func())

func RecvOK4

func RecvOK4[T0, T1, T2, T3 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool))

func RecvOK4Default

func RecvOK4Default[T0, T1, T2, T3 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), df func())

func RecvOK5

func RecvOK5[T0, T1, T2, T3, T4 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool))

func RecvOK5Default

func RecvOK5Default[T0, T1, T2, T3, T4 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), df func())

func RecvOK6

func RecvOK6[T0, T1, T2, T3, T4, T5 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), c5 <-chan T5, f5 func(T5, bool))

func RecvOK6Default

func RecvOK6Default[T0, T1, T2, T3, T4, T5 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), c5 <-chan T5, f5 func(T5, bool), df func())

func RecvOK7

func RecvOK7[T0, T1, T2, T3, T4, T5, T6 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), c5 <-chan T5, f5 func(T5, bool), c6 <-chan T6, f6 func(T6, bool))

func RecvOK7Default

func RecvOK7Default[T0, T1, T2, T3, T4, T5, T6 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), c5 <-chan T5, f5 func(T5, bool), c6 <-chan T6, f6 func(T6, bool), df func())

func RecvOK8

func RecvOK8[T0, T1, T2, T3, T4, T5, T6, T7 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), c5 <-chan T5, f5 func(T5, bool), c6 <-chan T6, f6 func(T6, bool), c7 <-chan T7, f7 func(T7, bool))

func RecvOK8Default

func RecvOK8Default[T0, T1, T2, T3, T4, T5, T6, T7 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), c5 <-chan T5, f5 func(T5, bool), c6 <-chan T6, f6 func(T6, bool), c7 <-chan T7, f7 func(T7, bool), df func())

func RecvOK9

func RecvOK9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), c5 <-chan T5, f5 func(T5, bool), c6 <-chan T6, f6 func(T6, bool), c7 <-chan T7, f7 func(T7, bool), c8 <-chan T8, f8 func(T8, bool))

func RecvOK9Default

func RecvOK9Default[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](c0 <-chan T0, f0 func(T0, bool), c1 <-chan T1, f1 func(T1, bool), c2 <-chan T2, f2 func(T2, bool), c3 <-chan T3, f3 func(T3, bool), c4 <-chan T4, f4 func(T4, bool), c5 <-chan T5, f5 func(T5, bool), c6 <-chan T6, f6 func(T6, bool), c7 <-chan T7, f7 func(T7, bool), c8 <-chan T8, f8 func(T8, bool), df func())

func Select2

func Select2[T0, T1 any](p0 Param[T0], p1 Param[T1])

func Select2Default

func Select2Default[T0, T1 any](p0 Param[T0], p1 Param[T1], df func())

func Select3

func Select3[T0, T1, T2 any](p0 Param[T0], p1 Param[T1], p2 Param[T2])

func Select3Default

func Select3Default[T0, T1, T2 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], df func())

func Select4

func Select4[T0, T1, T2, T3 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3])

func Select4Default

func Select4Default[T0, T1, T2, T3 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], df func())

func Select5

func Select5[T0, T1, T2, T3, T4 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4])

func Select5Default

func Select5Default[T0, T1, T2, T3, T4 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], df func())

func Select6

func Select6[T0, T1, T2, T3, T4, T5 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], p5 Param[T5])

func Select6Default

func Select6Default[T0, T1, T2, T3, T4, T5 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], p5 Param[T5], df func())

func Select7

func Select7[T0, T1, T2, T3, T4, T5, T6 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], p5 Param[T5], p6 Param[T6])

func Select7Default

func Select7Default[T0, T1, T2, T3, T4, T5, T6 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], p5 Param[T5], p6 Param[T6], df func())

func Select8

func Select8[T0, T1, T2, T3, T4, T5, T6, T7 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], p5 Param[T5], p6 Param[T6], p7 Param[T7])

func Select8Default

func Select8Default[T0, T1, T2, T3, T4, T5, T6, T7 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], p5 Param[T5], p6 Param[T6], p7 Param[T7], df func())

func Select9

func Select9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], p5 Param[T5], p6 Param[T6], p7 Param[T7], p8 Param[T8])

func Select9Default

func Select9Default[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](p0 Param[T0], p1 Param[T1], p2 Param[T2], p3 Param[T3], p4 Param[T4], p5 Param[T5], p6 Param[T6], p7 Param[T7], p8 Param[T8], df func())

func Send2

func Send2[T0, T1 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1)

func Send2Default

func Send2Default[T0, T1 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, df func())

func Send3

func Send3[T0, T1, T2 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2)

func Send3Default

func Send3Default[T0, T1, T2 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, df func())

func Send4

func Send4[T0, T1, T2, T3 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3)

func Send4Default

func Send4Default[T0, T1, T2, T3 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, df func())

func Send5

func Send5[T0, T1, T2, T3, T4 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4)

func Send5Default

func Send5Default[T0, T1, T2, T3, T4 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, df func())

func Send6

func Send6[T0, T1, T2, T3, T4, T5 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, c5 chan<- T5, v5 T5)

func Send6Default

func Send6Default[T0, T1, T2, T3, T4, T5 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, c5 chan<- T5, v5 T5, df func())

func Send7

func Send7[T0, T1, T2, T3, T4, T5, T6 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, c5 chan<- T5, v5 T5, c6 chan<- T6, v6 T6)

func Send7Default

func Send7Default[T0, T1, T2, T3, T4, T5, T6 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, c5 chan<- T5, v5 T5, c6 chan<- T6, v6 T6, df func())

func Send8

func Send8[T0, T1, T2, T3, T4, T5, T6, T7 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, c5 chan<- T5, v5 T5, c6 chan<- T6, v6 T6, c7 chan<- T7, v7 T7)

func Send8Default

func Send8Default[T0, T1, T2, T3, T4, T5, T6, T7 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, c5 chan<- T5, v5 T5, c6 chan<- T6, v6 T6, c7 chan<- T7, v7 T7, df func())

func Send9

func Send9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, c5 chan<- T5, v5 T5, c6 chan<- T6, v6 T6, c7 chan<- T7, v7 T7, c8 chan<- T8, v8 T8)

func Send9Default

func Send9Default[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](c0 chan<- T0, v0 T0, c1 chan<- T1, v1 T1, c2 chan<- T2, v2 T2, c3 chan<- T3, v3 T3, c4 chan<- T4, v4 T4, c5 chan<- T5, v5 T5, c6 chan<- T6, v6 T6, c7 chan<- T7, v7 T7, c8 chan<- T8, v8 T8, df func())

Types

type Param

type Param[T any] struct {
	RecvChan  <-chan T
	RecvFunc  func(T, bool)
	SendChan  chan<- T
	SendValue T
}

Param is an argument for the Select* functions.

func Recv

func Recv[T any](c <-chan T, f func(T)) Param[T]

Recv is a helper for registering a callback for receiving on a channel

func RecvOK

func RecvOK[T any](c <-chan T, f func(T, bool)) Param[T]

RecvOK is a helper for registering a callback for receiving on a channel

func Send

func Send[T any](c chan<- T, v T) Param[T]

Send is a helper for generating a Param for sending on a channel

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL