• Stars
    star
    133
  • Rank 272,600 (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

go-nfqueue

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

xast

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

pia-socks-proxy

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

git-go-vendor

Simple go vendoring using git submodules.
Go
12
star
11

cch

cch: closable safe go channels
Go
7
star
12

radix

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

generics.pw

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

genh

genh: generics helpers
Go
4
star
15

dynamic-routes

Dynamic routes for Express.JS
JavaScript
4
star
16

cgoVSsyso

Go
3
star
17

seahash

A SeaHash Implentation in Go
Go
2
star
18

bctx

context helpers
Go
2
star
19

vscode-save-runner

Save Runner for Visual Studio Code
TypeScript
2
star
20

wjsu

syscall/js wasm helper
Go
2
star
21

dvcs-helper

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

Secure-Browser-Chat

1
star
23

closer

Go
1
star
24

otk

Go
1
star
25

stc

Go
1
star
26

rlog

Go
1
star
27

slowbolt

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

jdb

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

limiter

Go
1
star
30

skiplist

a simple skiplist
Go
1
star
31

msgpack

Go
1
star
32

mgo.ejson

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

webview

Go
1
star
34

oerrs

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

td

TD Ameritrade unofficial Go API Client
Go
1
star
36

segmentedSlice

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

etc-fish

My Fish Shell configuration
Shell
1
star