...
Run Format

Source file src/internal/poll/fd_poll_runtime.go

Documentation: internal/poll

  // Copyright 2013 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
  
  package poll
  
  import (
  	"errors"
  	"sync"
  	"syscall"
  	"time"
  )
  
  // runtimeNano returns the current value of the runtime clock in nanoseconds.
  func runtimeNano() int64
  
  func runtime_pollServerInit()
  func runtime_pollServerDescriptor() uintptr
  func runtime_pollOpen(fd uintptr) (uintptr, int)
  func runtime_pollClose(ctx uintptr)
  func runtime_pollWait(ctx uintptr, mode int) int
  func runtime_pollWaitCanceled(ctx uintptr, mode int) int
  func runtime_pollReset(ctx uintptr, mode int) int
  func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
  func runtime_pollUnblock(ctx uintptr)
  
  type pollDesc struct {
  	runtimeCtx uintptr
  }
  
  var serverInit sync.Once
  
  func (pd *pollDesc) init(fd *FD) error {
  	serverInit.Do(runtime_pollServerInit)
  	ctx, errno := runtime_pollOpen(uintptr(fd.Sysfd))
  	if errno != 0 {
  		if ctx != 0 {
  			runtime_pollUnblock(ctx)
  			runtime_pollClose(ctx)
  		}
  		return syscall.Errno(errno)
  	}
  	pd.runtimeCtx = ctx
  	return nil
  }
  
  func (pd *pollDesc) close() {
  	if pd.runtimeCtx == 0 {
  		return
  	}
  	runtime_pollClose(pd.runtimeCtx)
  	pd.runtimeCtx = 0
  }
  
  // Evict evicts fd from the pending list, unblocking any I/O running on fd.
  func (pd *pollDesc) evict() {
  	if pd.runtimeCtx == 0 {
  		return
  	}
  	runtime_pollUnblock(pd.runtimeCtx)
  }
  
  func (pd *pollDesc) prepare(mode int, isFile bool) error {
  	if pd.runtimeCtx == 0 {
  		return nil
  	}
  	res := runtime_pollReset(pd.runtimeCtx, mode)
  	return convertErr(res, isFile)
  }
  
  func (pd *pollDesc) prepareRead(isFile bool) error {
  	return pd.prepare('r', isFile)
  }
  
  func (pd *pollDesc) prepareWrite(isFile bool) error {
  	return pd.prepare('w', isFile)
  }
  
  func (pd *pollDesc) wait(mode int, isFile bool) error {
  	if pd.runtimeCtx == 0 {
  		return errors.New("waiting for unsupported file type")
  	}
  	res := runtime_pollWait(pd.runtimeCtx, mode)
  	return convertErr(res, isFile)
  }
  
  func (pd *pollDesc) waitRead(isFile bool) error {
  	return pd.wait('r', isFile)
  }
  
  func (pd *pollDesc) waitWrite(isFile bool) error {
  	return pd.wait('w', isFile)
  }
  
  func (pd *pollDesc) waitCanceled(mode int) {
  	if pd.runtimeCtx == 0 {
  		return
  	}
  	runtime_pollWaitCanceled(pd.runtimeCtx, mode)
  }
  
  func (pd *pollDesc) pollable() bool {
  	return pd.runtimeCtx != 0
  }
  
  func convertErr(res int, isFile bool) error {
  	switch res {
  	case 0:
  		return nil
  	case 1:
  		return errClosing(isFile)
  	case 2:
  		return ErrTimeout
  	}
  	println("unreachable: ", res)
  	panic("unreachable")
  }
  
  // SetDeadline sets the read and write deadlines associated with fd.
  func (fd *FD) SetDeadline(t time.Time) error {
  	return setDeadlineImpl(fd, t, 'r'+'w')
  }
  
  // SetReadDeadline sets the read deadline associated with fd.
  func (fd *FD) SetReadDeadline(t time.Time) error {
  	return setDeadlineImpl(fd, t, 'r')
  }
  
  // SetWriteDeadline sets the write deadline associated with fd.
  func (fd *FD) SetWriteDeadline(t time.Time) error {
  	return setDeadlineImpl(fd, t, 'w')
  }
  
  func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
  	diff := int64(time.Until(t))
  	d := runtimeNano() + diff
  	if d <= 0 && diff > 0 {
  		// If the user has a deadline in the future, but the delay calculation
  		// overflows, then set the deadline to the maximum possible value.
  		d = 1<<63 - 1
  	}
  	if t.IsZero() {
  		d = 0
  	}
  	if err := fd.incref(); err != nil {
  		return err
  	}
  	if fd.pd.runtimeCtx == 0 {
  		return errors.New("file type does not support deadlines")
  	}
  	runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
  	fd.decref()
  	return nil
  }
  
  // PollDescriptor returns the descriptor being used by the poller,
  // or ^uintptr(0) if there isn't one. This is only used for testing.
  func PollDescriptor() uintptr {
  	return runtime_pollServerDescriptor()
  }
  

View as plain text