github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/internal/netpoll/kqueue.go (about)

     1  // +build darwin netbsd freebsd openbsd dragonfly
     2  
     3  package netpoll
     4  
     5  import (
     6  	"log"
     7  
     8  	"github.com/angenalZZZ/gofunc/net/internal"
     9  	"golang.org/x/sys/unix"
    10  )
    11  
    12  // Poller represents a poller which is in charge of monitoring file-descriptors.
    13  type Poller struct {
    14  	fd            int
    15  	asyncJobQueue internal.AsyncJobQueue
    16  }
    17  
    18  // OpenPoller instantiates a poller.
    19  func OpenPoller() (poller *Poller, err error) {
    20  	poller = new(Poller)
    21  	if poller.fd, err = unix.Kqueue(); err != nil {
    22  		poller = nil
    23  		return
    24  	}
    25  	if _, err = unix.Kevent(poller.fd, []unix.Kevent_t{{
    26  		Ident:  0,
    27  		Filter: unix.EVFILT_USER,
    28  		Flags:  unix.EV_ADD | unix.EV_CLEAR,
    29  	}}, nil, nil); err != nil {
    30  		_ = poller.Close()
    31  		poller = nil
    32  		return
    33  	}
    34  	poller.asyncJobQueue = internal.NewAsyncJobQueue()
    35  	return
    36  }
    37  
    38  // Close closes the poller.
    39  func (p *Poller) Close() error {
    40  	return unix.Close(p.fd)
    41  }
    42  
    43  var wakeChanges = []unix.Kevent_t{{
    44  	Ident:  0,
    45  	Filter: unix.EVFILT_USER,
    46  	Fflags: unix.NOTE_TRIGGER,
    47  }}
    48  
    49  // Trigger wakes up the poller blocked in waiting for network-events and runs jobs in asyncJobQueue.
    50  func (p *Poller) Trigger(job internal.Job) error {
    51  	if p.asyncJobQueue.Push(job) == 1 {
    52  		_, err := unix.Kevent(p.fd, wakeChanges, nil, nil)
    53  		return err
    54  	}
    55  	return nil
    56  }
    57  
    58  // Polling blocks the current goroutine, waiting for network-events.
    59  func (p *Poller) Polling(callback func(fd int, filter int16) error) (err error) {
    60  	el := newEventList(InitEvents)
    61  	var wakenUp bool
    62  	for {
    63  		n, err0 := unix.Kevent(p.fd, nil, el.events, nil)
    64  		if err0 != nil && err0 != unix.EINTR {
    65  			log.Println(err0)
    66  			continue
    67  		}
    68  		var evFilter int16
    69  		for i := 0; i < n; i++ {
    70  			if fd := int(el.events[i].Ident); fd != 0 {
    71  				evFilter = el.events[i].Filter
    72  				if (el.events[i].Flags&unix.EV_EOF != 0) || (el.events[i].Flags&unix.EV_ERROR != 0) {
    73  					evFilter = EVFilterSock
    74  				}
    75  				if err = callback(fd, evFilter); err != nil {
    76  					return
    77  				}
    78  			} else {
    79  				wakenUp = true
    80  			}
    81  		}
    82  		if wakenUp {
    83  			wakenUp = false
    84  			if err = p.asyncJobQueue.ForEach(); err != nil {
    85  				return
    86  			}
    87  		}
    88  		if n == el.size {
    89  			el.increase()
    90  		}
    91  	}
    92  }
    93  
    94  // AddReadWrite registers the given file-descriptor with readable and writable events to the poller.
    95  func (p *Poller) AddReadWrite(fd int) error {
    96  	if _, err := unix.Kevent(p.fd, []unix.Kevent_t{
    97  		{Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_READ},
    98  		{Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_WRITE},
    99  	}, nil, nil); err != nil {
   100  		return err
   101  	}
   102  	return nil
   103  }
   104  
   105  // AddRead registers the given file-descriptor with readable event to the poller.
   106  func (p *Poller) AddRead(fd int) error {
   107  	if _, err := unix.Kevent(p.fd, []unix.Kevent_t{
   108  		{Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_READ}}, nil, nil); err != nil {
   109  		return err
   110  	}
   111  	return nil
   112  }
   113  
   114  // AddWrite registers the given file-descriptor with writable event to the poller.
   115  func (p *Poller) AddWrite(fd int) error {
   116  	if _, err := unix.Kevent(p.fd, []unix.Kevent_t{
   117  		{Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_WRITE}}, nil, nil); err != nil {
   118  		return err
   119  	}
   120  	return nil
   121  }
   122  
   123  // ModRead renews the given file-descriptor with readable event in the poller.
   124  func (p *Poller) ModRead(fd int) error {
   125  	if _, err := unix.Kevent(p.fd, []unix.Kevent_t{
   126  		{Ident: uint64(fd), Flags: unix.EV_DELETE, Filter: unix.EVFILT_WRITE}}, nil, nil); err != nil {
   127  		return err
   128  	}
   129  	return nil
   130  }
   131  
   132  // ModReadWrite renews the given file-descriptor with readable and writable events in the poller.
   133  func (p *Poller) ModReadWrite(fd int) error {
   134  	if _, err := unix.Kevent(p.fd, []unix.Kevent_t{
   135  		{Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_WRITE}}, nil, nil); err != nil {
   136  		return err
   137  	}
   138  	return nil
   139  }
   140  
   141  // Delete removes the given file-descriptor from the poller.
   142  func (p *Poller) Delete(fd int) error {
   143  	return nil
   144  }