Skip to content

Commit

Permalink
remove ET support and clean code
Browse files Browse the repository at this point in the history
  • Loading branch information
pilot committed Dec 26, 2023
1 parent 3e4c360 commit ed3aabd
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 116 deletions.
9 changes: 1 addition & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ The goal of `event` is to provide a `BASIC` tool for building high performance n
- Supports Read/Write/Timeout events
- Flexible timer event and ticker event
- Supports event priority
- Edge-triggered option
- Simple API
- Low memory usage

Expand Down Expand Up @@ -56,12 +55,6 @@ The event is one-shot by default. If you want to persist, you can set the `EvPer
ev := event.New(base, fd, event.EvRead|event.EvPersist, callback, arg)
```

The event is level-triggered by default. If you want to use edge-triggered, you can set the `EvET` option.

```go
ev := event.New(base, fd, event.EvRead|event.EvET, callback, arg)
```

### Read/Write/Timeout

These events can be used in combination.
Expand Down Expand Up @@ -100,7 +93,7 @@ When events are triggered together, high priority events will be dispatched firs

```go
ev := event.New(base, fd, event.EvRead|event.EvET, callback, arg)
ev.SetPriority(event.HPri)
ev.SetPriority(event.HP)
```

### Usage
Expand Down
30 changes: 2 additions & 28 deletions epoll.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
const (
initialNEvent = 0x20
maxNEvent = 0x1000
maxUint32 = 0xFFFFFFFF
)

var evPool = sync.Pool{
Expand All @@ -29,7 +28,6 @@ var evPool = sync.Pool{
type fdEvent struct {
r *Event
w *Event
et uint8
evs uint32
}

Expand Down Expand Up @@ -60,7 +58,6 @@ func (ep *poll) add(ev *Event) error {
es = evPool.Get().(*fdEvent)
ep.fdEvents[ev.fd] = es
}

if ev.events&EvRead != 0 {
es.r = ev
es.evs |= syscall.EPOLLIN
Expand All @@ -69,21 +66,13 @@ func (ep *poll) add(ev *Event) error {
es.w = ev
es.evs |= syscall.EPOLLOUT
}
if ev.events&EvET != 0 {
es.et++
es.evs |= syscall.EPOLLET & maxUint32
}

epEv := syscall.EpollEvent{Events: es.evs}

*(**fdEvent)(unsafe.Pointer(&epEv.Fd)) = es

return syscall.EpollCtl(ep.fd, op, ev.fd, &epEv)
}

func (ep *poll) del(ev *Event) error {
es := ep.fdEvents[ev.fd]

if ev.events&EvRead != 0 {
es.r = nil
es.evs &^= syscall.EPOLLIN
Expand All @@ -92,24 +81,15 @@ func (ep *poll) del(ev *Event) error {
es.w = nil
es.evs &^= syscall.EPOLLOUT
}
if ev.events&EvET != 0 {
if es.et--; es.et == 0 {
es.evs &^= syscall.EPOLLET & maxUint32
}
}

op := syscall.EPOLL_CTL_DEL
if es.evs&(syscall.EPOLLIN|syscall.EPOLLOUT) == 0 {
delete(ep.fdEvents, ev.fd)
evPool.Put(es)
} else {
op = syscall.EPOLL_CTL_MOD
}

epEv := syscall.EpollEvent{Events: es.evs}

*(**fdEvent)(unsafe.Pointer(&epEv.Fd)) = es

return syscall.EpollCtl(ep.fd, op, ev.fd, &epEv)
}

Expand All @@ -118,35 +98,29 @@ func (ep *poll) wait(cb func(ev *Event, res uint32), timeout time.Duration) erro
if err != nil && !temporaryErr(err) {
return err
}

for i := 0; i < n; i++ {
var evRead, evWrite *Event
what := ep.events[i].Events
es := *(**fdEvent)(unsafe.Pointer(&ep.events[i].Fd))

if what&(syscall.EPOLLERR|syscall.EPOLLHUP) != 0 {
what |= syscall.EPOLLIN | syscall.EPOLLOUT
}

if what&syscall.EPOLLIN != 0 {
evRead = es.r
}
if what&syscall.EPOLLOUT != 0 {
evWrite = es.w
}

if evRead != nil {
cb(evRead, evRead.events&(EvRead|EvET))
cb(evRead, evRead.events&EvRead)
}
if evWrite != nil {
cb(evWrite, evWrite.events&(EvWrite|EvET))
cb(evWrite, evWrite.events&EvWrite)
}
}

if n == len(ep.events) && n < maxNEvent {
ep.events = make([]syscall.EpollEvent, n<<1)
}

return nil
}

Expand Down
18 changes: 8 additions & 10 deletions event.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,18 @@ const (

// EvPersist is persistent behavior option.
EvPersist = 1 << iota
// EvET is edge-triggered behavior option.
EvET = 1 << iota

// EvLoopOnce is the flag to control event base loop just once.
EvLoopOnce = 001
// EvLoopNoblock is the flag to control event base loop not block.
EvLoopNoblock = 002

// HPri is the high priority.
HPri eventPriority = 0b00
// MPri is the middle priority.
MPri eventPriority = 0b01
// LPri is the low priority.
LPri eventPriority = 0b10
// HP is the high priority.
HP eventPriority = 0b00
// MP is the middle priority.
MP eventPriority = 0b01
// LP is the low priority.
LP eventPriority = 0b10

// evListInserted is the flag to indicate the event is in the event list.
evListInserted = 0x01
Expand Down Expand Up @@ -74,10 +72,10 @@ type Event struct {
priority eventPriority
}

// New creates a new event with default priority MPri.
// New creates a new event with default priority MP.
func New(base *EventBase, fd int, events uint32, callback func(fd int, events uint32, arg interface{}), arg interface{}) *Event {
ev := new(Event)
ev.Assign(base, fd, events, callback, arg, MPri)
ev.Assign(base, fd, events, callback, arg, MP)
return ev
}

Expand Down
50 changes: 1 addition & 49 deletions event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ func TestPriority(t *testing.T) {
syscall.Read(fds1[0], make([]byte, 8))
triggerTime1 = int(time.Now().UnixMicro())
}, "hello")
ev1.SetPriority(HPri)
ev1.SetPriority(HP)

err = ev0.Attach(0)
if err != nil {
Expand All @@ -329,54 +329,6 @@ func TestPriority(t *testing.T) {
syscall.Close(fds1[1])
}

func TestEdgeTrigger(t *testing.T) {
base, err := NewBase()
if err != nil {
t.Fatal(err)
}

fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
if err != nil {
t.Fatal(err)
}

_, err = syscall.Write(fds[1], []byte{0, 0, 0, 0, 0, 0, 0, 1})
if err != nil {
t.Fatal(err)
}

n := 0
ev := New(base, fds[0], EvRead|EvTimeout|EvPersist|EvET, func(fd int, events uint32, arg interface{}) {
if events&EvTimeout != 0 {
if err := base.Shutdown(); err != nil {
t.Fatal(err)
}
return
}
if events&EvET == 0 {
t.FailNow()
}
n++
}, "hello")

err = ev.Attach(10 * time.Millisecond)
if err != nil {
t.Fatal(err)
}

err = base.Dispatch()
if err != nil && err != syscall.EBADF {
t.Fatal(err)
}

if n != 1 {
t.FailNow()
}

syscall.Close(fds[0])
syscall.Close(fds[1])
}

func BenchmarkEventAdd(b *testing.B) {
receivers := make([]int, b.N)
base, err := NewBase()
Expand Down
26 changes: 5 additions & 21 deletions kqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,19 @@ func openPoll() (*poll, error) {
}

func (kq *poll) add(ev *Event) error {
ET := uint16(0)
if ev.events&EvET != 0 {
ET = syscall.EV_CLEAR
}
if ev.events&EvRead != 0 {
kq.changes = append(kq.changes, syscall.Kevent_t{
Ident: uint64(ev.fd),
Filter: syscall.EVFILT_READ,
Flags: syscall.EV_ADD | ET,
Flags: syscall.EV_ADD,
Udata: (*byte)(unsafe.Pointer(ev)),
})
}
if ev.events&EvWrite != 0 {
kq.changes = append(kq.changes, syscall.Kevent_t{
Ident: uint64(ev.fd),
Filter: syscall.EVFILT_WRITE,
Flags: syscall.EV_ADD | ET,
Flags: syscall.EV_ADD,
Udata: (*byte)(unsafe.Pointer(ev)),
})
}
Expand All @@ -79,19 +75,12 @@ func (kq *poll) del(ev *Event) error {
}

func (kq *poll) wait(cb func(ev *Event, res uint32), timeout time.Duration) error {
var timespec *syscall.Timespec = nil
if timeout >= 0 {
ts := syscall.NsecToTimespec(timeout.Nanoseconds())
timespec = &ts
}

n, err := syscall.Kevent(kq.fd, kq.changes, kq.events, timespec)
ts := syscall.NsecToTimespec(timeout.Nanoseconds())
n, err := syscall.Kevent(kq.fd, kq.changes, kq.events, &ts)
if err != nil && !temporaryErr(err) {
return err
}

kq.changes = kq.changes[:0]

for i := 0; i < n; i++ {
flags := kq.events[i].Flags
if flags&syscall.EV_ERROR != 0 {
Expand All @@ -101,24 +90,19 @@ func (kq *poll) wait(cb func(ev *Event, res uint32), timeout time.Duration) erro
}
return errno
}

which := uint32(0)
what := kq.events[i].Filter
ev := (*Event)(unsafe.Pointer(kq.events[i].Udata))

if what&syscall.EVFILT_READ != 0 {
which |= EvRead
} else if what&syscall.EVFILT_WRITE != 0 {
which |= EvWrite
}

cb(ev, ev.events&(which|EvET))
cb(ev, ev.events&which)
}

if n == len(kq.events) && n < maxNEvent {
kq.events = make([]syscall.Kevent_t, n<<1)
}

return nil
}

Expand Down

0 comments on commit ed3aabd

Please sign in to comment.