Home

Awesome

<p align="center"> <img src="logo.png" width="350" height="175" border="0" alt="event"> <br><br> <a title="Build Status" target="_blank" href="https://github.com/cheng-zhongliang/event/actions?query=workflow"><img src="https://img.shields.io/github/actions/workflow/status/cheng-zhongliang/event/go.yml?logo=github-actions" /></a> <a title="Codecov" target="_blank" href="https://codecov.io/gh/cheng-zhongliang/event"><img src="https://img.shields.io/codecov/c/github/cheng-zhongliang/event?logo=codecov" /></a> <a title="Supported Platforms" target="_blank" href="https://github.com/cheng-zhongliang/event"><img src="https://img.shields.io/badge/platform-Linux%20%7C%20FreeBSD%20%7C%20DragonFly%20%7C%20NetBSD%20%7C%20OpenBSD%20%7C%20Darwin-549688?logo=launchpad" /></a> <a title="Go Report Card" target="_blank" href="https://goreportcard.com/report/github.com/cheng-zhongliang/event"><img src="https://goreportcard.com/badge/github.com/cheng-zhongliang/event" /></a> <a title="Doc for event" target="_blank" href="https://pkg.go.dev/github.com/cheng-zhongliang/event"><img src="https://img.shields.io/badge/go.dev-doc-007d9c?logo=read-the-docs" /></a> <a title="License" target="_blank" href="https://github.com/cheng-zhongliang/event/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-BSD--3--Clause-brightgreen"></a> <a title="Release" target="_blank" href="https://github.com/cheng-zhongliang/event/releases"><img src="https://img.shields.io/github/v/release/cheng-zhongliang/event.svg?color=161823&logo=smartthings" /></a> <a title="Tag" target="_blank" href="https://github.com/cheng-zhongliang/event/tags"><img src="https://img.shields.io/github/v/tag/cheng-zhongliang/event?color=%23ff8936&logo=fitbit" /></a> <a title="Require Go Version" target="_blank" href="https://github.com/cheng-zhongliang/event"><img src="https://img.shields.io/badge/go-%3E%3D1.13-30dff3?logo=go" /></a> <a title="Mentioned in Awesome Go" target="_blank" href="https://github.com/avelino/awesome-go#networking"><img src="https://awesome.re/mentioned-badge.svg" /></a> <a title="Stars" target="_blank" href="https://starchart.cc/cheng-zhongliang/event"><img alt="Stars" src="https://img.shields.io/github/stars/cheng-zhongliang/event.svg?style=social"></a> </p>

event is a network I/O event notification library for Go. It uses epoll and kqueue to poll I/O events that is fast and low memory usage. It works in a similar manner as libevent.

The goal of event is to provide a BASIC tool for building high performance network applications.

Note: All development is done on a Raspberry Pi 4B.

Features

Getting Started

Installing

To start using event, just run go get:

$ go get -u github.com/cheng-zhongliang/event

Event

When the event is triggered, the callback function will be called.

Read/Write/Timeout

These events can be used in combination.

base := event.NewBase()
ev := event.New(base, fd, event.EvRead|event.Timeout, callback, arg)
ev.Attach(time.Second)

When the fd is readable or timeout expires, this event will be triggered.

Option

The event is one-shot by default. If you want to persist, you can set the EvPersist option.

ev := event.New(base, fd, event.EvRead|event.EvPersist, callback, arg)

Timer

The timer is a one-shot event that will be triggered after the timeout expires.

base := event.NewBase()
ev := event.NewTimer(base, callback, arg)
ev.Attach(time.Second)

Ticker

The ticker is a repeating event that will be triggered every time the timeout expires.

base := event.NewBase()
ev := event.NewTicker(base, callback, arg)
ev.Attach(time.Second)

Priority

When events are triggered together, high priority events will be dispatched first.

ev := event.New(base, fd, event.EvRead, callback, arg)
ev.SetPriority(event.HP)

Usage

Example echo server that binds to port 1246:

package main

import (
	"syscall"

	"github.com/cheng-zhongliang/event"
)

func main() {
	base, err := event.NewBase()
	if err != nil {
		panic(err)
	}
	fd := socket()
	ev := event.New(base, fd, event.EvRead|event.EvPersist, accept, base)
	if err := ev.Attach(0); err != nil {
		panic(err)
	}
	if err := base.Dispatch(); err != nil && err != syscall.EBADF {
		panic(err)
	}
	syscall.Close(fd)
}

func socket() int {
	addr := syscall.SockaddrInet4{Port: 1246, Addr: [4]byte{0, 0, 0, 0}}
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
	if err != nil {
		panic(err)
	}
	if err := syscall.Bind(fd, &addr); err != nil {
		panic(err)
	}
	err = syscall.Listen(fd, syscall.SOMAXCONN)
	if err != nil {
		panic(err)
	}
	return fd
}

func accept(fd int, events uint32, arg interface{}) {
	base := arg.(*event.EventBase)
	clientFd, _, err := syscall.Accept(fd)
	if err != nil {
		panic(err)
	}
	ev := event.New(base, clientFd, event.EvRead|event.EvPersist, echo, nil)
	if err := ev.Attach(0); err != nil {
		panic(err)
	}
}

func echo(fd int, events uint32, arg interface{}) {
	buf := make([]byte, 0xFFF)
	n, err := syscall.Read(fd, buf)
	if err != nil {
		panic(err)
	}
	if _, err := syscall.Write(fd, buf[:n]); err != nil {
		panic(err)
	}
}

Connect to the echo server:

$ telnet localhost 1246