• Stars
    star
    133
  • Rank 271,826 (Top 6 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 8 years ago
  • Updated over 8 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A scalable lock-free channel.

lfchan GoDoc Build Status Go Report Card

--

A scalable lock-free channel.

  • Supports graceful closing.
  • Supports blocking and non-blocking operations.
  • Supports select.
  • Scales with the number of cores.

Install

go get github.com/OneOfOne/lfchan

Usage

import (
	"fmt"

	"github.com/OneOfOne/lfchan"
)

func main() {
	ch := lfchan.New() // or
	// ch := lfchan.NewSize(10) // buffered channel
	go ch.Send("hello", true)
	fmt.Printf("%s world", ch.Recv(true).(string))
}

Generate a typed channel

Generate the package:

go run "$GOPATH/src/github.com/OneOfOne/lfchan/gen.go" type [pkgName or . to embed the chan in the current package]

# primitve type
go run "$GOPATH/src/github.com/OneOfOne/lfchan/gen.go" string internal/stringChan

# or for using a non-native type
go run "$GOPATH/src/github.com/OneOfOne/lfchan/gen.go" github.com/OneOfOne/cmap.CMap internal/cmapChan

go run "$GOPATH/src/github.com/OneOfOne/lfchan/gen.go" github.com/OneOfOne/cmap.CMap

Use it in your code:

typed sub package

package main

// go run "$GOPATH/src/github.com/OneOfOne/lfchan/gen.go" string internal/stringChan

import (
	"fmt"

	"github.com/YOU/internal/stringChan"
)

func main() {
	ch := stringChan.New() // or
	// ch := stringChan.NewSize(10) // buffered channel
	go func() {
		go ch.Send("lfchan", true)
		ch.Send("hello", true)
	}()
	for s, ok := ch.Recv(true); ok; s, ok = ch.Recv(true) {
		fmt.Print(s, " ")
	}
	fmt.Println()
}

embed the type directly

package main

// go run "$GOPATH/src/github.com/OneOfOne/lfchan/gen.go" "[]*node" .

import (
	"fmt"
)

type node struct {
	v int
}

func main() {
	// notice how for embeded types the new func is called "new[Size]{TypeName}Chan()
	ch := newNodeChan() // or
	// ch := newSizeNodeChan(10) // buffered channel
	go func() {
		for i := 0; i < 10; i++ {
			ch.Send([]*Node{{i}, {i*i}}, true)
		}
	}()
	for ns, ok := ch.Recv(true); ok; ns, ok = ch.Recv(true) {
		for i, n := range ns {
			fmt.Println(i, n.v)
		}
	}
}

Known issues

  • Doesn't scale correctly on true SMP systems (issue #3).

  • Under high concurrency, ch.Len() can return -1 (issue #2) Fixed by commit bdddd90.

  • typed channels can't handle zero value primitve types correctly, for example it can't handle sending 0 on an int channel Fixed.

  • gen.go can't handle maps to non-native types.

Benchmark

# Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
# Linux 4.4.5 x86_64

➜ go test -bench=. -benchmem -cpu 1,4,8 -benchtime 10s
BenchmarkLFChan         100000000              157 ns/op               8 B/op          1 allocs/op
BenchmarkLFChan-4       100000000              187 ns/op               8 B/op          1 allocs/op
BenchmarkLFChan-8       100000000              168 ns/op               8 B/op          1 allocs/op

BenchmarkChan           200000000             96.2 ns/op               8 B/op          1 allocs/op
BenchmarkChan-4         50000000               244 ns/op               8 B/op          1 allocs/op
BenchmarkChan-8         50000000               323 ns/op               8 B/op          1 allocs/op

PASS
ok      github.com/OneOfOne/lfchan      124.067s

check issue #3 for more benchmarks and updates.

FAQ

Why are you using runtime.Gosched?

  • Sadly, it is the only clean way to release the scheduler in a tight loop, Go doesn't provide any other way to yield, time.Sleep causes random allocations at times. sync/atomic.Value has access to internal funcs which can control the scheduler, however user code can't do that.

Isn't using a spinlock bad for the CPU?

  • Yes and no, using the spinlock and few sleeps in the code makes it very efficient even under idle conditions.

License

This project is released under the Apache v2. licence. See LICENCE for more details.

More Repositories

1

xxhash

A native implementation of the excellent XXHash hashing algorithm.
Go
411
star
2

struct2ts

Generate Typescript classes/interfaces out of Go structs
Go
138
star
3

netchan

Go channels over a network.
Go
83
star
4

go-utils

Random Go Language utilities that don't warrant their own repos.
Go
50
star
5

cmap

A sharded map implementation to support fast concurrent access and swap/update operations.
Go
46
star
6

genx

GenX: Generics For Go, Yet Again.
Go
37
star
7

ta

Go
37
star
8

go-nfqueue

Go Wrapper For Creating IPTables NFQueue clients in Go
Go
29
star
9

xast

xast: ast rewriter with built-in clean up.
Go
26
star
10

pia-socks-proxy

An Alpine Linux container running a socks5 proxy (using dante) via Private Internet Access (OpenVPN).
Dockerfile
16
star
11

git-go-vendor

Simple go vendoring using git submodules.
Go
12
star
12

cch

cch: closable safe go channels
Go
7
star
13

radix

radix: a go radix tree with nearest matching
Go
6
star
14

generics.pw

source code for https://generics.pw
Go
4
star
15

genh

genh: generics helpers
Go
4
star
16

dynamic-routes

Dynamic routes for Express.JS
JavaScript
4
star
17

cgoVSsyso

Go
3
star
18

seahash

A SeaHash Implentation in Go
Go
2
star
19

bctx

context helpers
Go
2
star
20

vscode-save-runner

Save Runner for Visual Studio Code
TypeScript
2
star
21

wjsu

syscall/js wasm helper
Go
2
star
22

dvcs-helper

A helper to (dumb)-sync DVCS repos over php/ftp.
Python
2
star
23

Secure-Browser-Chat

1
star
24

closer

Go
1
star
25

otk

Go
1
star
26

stc

Go
1
star
27

rlog

Go
1
star
28

slowbolt

slowbolt: log slow update/view bolt calls
Go
1
star
29

jdb

A file-backed ACID in-memory k/v data store.
Go
1
star
30

limiter

Go
1
star
31

skiplist

a simple skiplist
Go
1
star
32

msgpack

Go
1
star
33

mgo.ejson

A simple package to Marshal/Unmarshal MongoDB's EJson in Go.
Go
1
star
34

webview

Go
1
star
35

oerrs

Yet another go package with an error list
Go
1
star
36

td

TD Ameritrade unofficial Go API Client
Go
1
star
37

segmentedSlice

A fast, index-able, sort-able, grow-only Slice.
Go
1
star
38

etc-fish

My Fish Shell configuration
Shell
1
star