...

Source file src/internal/poll/fd_plan9.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package poll
     6	
     7	import (
     8		"errors"
     9		"io"
    10		"sync/atomic"
    11		"time"
    12	)
    13	
    14	type atomicBool int32
    15	
    16	func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
    17	func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
    18	func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
    19	
    20	type FD struct {
    21		// Lock sysfd and serialize access to Read and Write methods.
    22		fdmu fdMutex
    23	
    24		Destroy func()
    25	
    26		// deadlines
    27		raio      *asyncIO
    28		waio      *asyncIO
    29		rtimer    *time.Timer
    30		wtimer    *time.Timer
    31		rtimedout atomicBool // set true when read deadline has been reached
    32		wtimedout atomicBool // set true when write deadline has been reached
    33	
    34		// Whether this is a normal file.
    35		// On Plan 9 we do not use this package for ordinary files,
    36		// so this is always false, but the field is present because
    37		// shared code in fd_mutex.go checks it.
    38		isFile bool
    39	}
    40	
    41	// We need this to close out a file descriptor when it is unlocked,
    42	// but the real implementation has to live in the net package because
    43	// it uses os.File's.
    44	func (fd *FD) destroy() error {
    45		if fd.Destroy != nil {
    46			fd.Destroy()
    47		}
    48		return nil
    49	}
    50	
    51	// Close handles the locking for closing an FD. The real operation
    52	// is in the net package.
    53	func (fd *FD) Close() error {
    54		if !fd.fdmu.increfAndClose() {
    55			return errClosing(fd.isFile)
    56		}
    57		return nil
    58	}
    59	
    60	// Read implements io.Reader.
    61	func (fd *FD) Read(fn func([]byte) (int, error), b []byte) (int, error) {
    62		if fd.rtimedout.isSet() {
    63			return 0, ErrTimeout
    64		}
    65		if err := fd.readLock(); err != nil {
    66			return 0, err
    67		}
    68		defer fd.readUnlock()
    69		if len(b) == 0 {
    70			return 0, nil
    71		}
    72		fd.raio = newAsyncIO(fn, b)
    73		n, err := fd.raio.Wait()
    74		fd.raio = nil
    75		if isHangup(err) {
    76			err = io.EOF
    77		}
    78		if isInterrupted(err) {
    79			err = ErrTimeout
    80		}
    81		return n, err
    82	}
    83	
    84	// Write implements io.Writer.
    85	func (fd *FD) Write(fn func([]byte) (int, error), b []byte) (int, error) {
    86		if fd.wtimedout.isSet() {
    87			return 0, ErrTimeout
    88		}
    89		if err := fd.writeLock(); err != nil {
    90			return 0, err
    91		}
    92		defer fd.writeUnlock()
    93		fd.waio = newAsyncIO(fn, b)
    94		n, err := fd.waio.Wait()
    95		fd.waio = nil
    96		if isInterrupted(err) {
    97			err = ErrTimeout
    98		}
    99		return n, err
   100	}
   101	
   102	// SetDeadline sets the read and write deadlines associated with fd.
   103	func (fd *FD) SetDeadline(t time.Time) error {
   104		return setDeadlineImpl(fd, t, 'r'+'w')
   105	}
   106	
   107	// SetReadDeadline sets the read deadline associated with fd.
   108	func (fd *FD) SetReadDeadline(t time.Time) error {
   109		return setDeadlineImpl(fd, t, 'r')
   110	}
   111	
   112	// SetWriteDeadline sets the write deadline associated with fd.
   113	func (fd *FD) SetWriteDeadline(t time.Time) error {
   114		return setDeadlineImpl(fd, t, 'w')
   115	}
   116	
   117	func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
   118		d := t.Sub(time.Now())
   119		if mode == 'r' || mode == 'r'+'w' {
   120			fd.rtimedout.setFalse()
   121		}
   122		if mode == 'w' || mode == 'r'+'w' {
   123			fd.wtimedout.setFalse()
   124		}
   125		if t.IsZero() || d < 0 {
   126			// Stop timer
   127			if mode == 'r' || mode == 'r'+'w' {
   128				if fd.rtimer != nil {
   129					fd.rtimer.Stop()
   130				}
   131				fd.rtimer = nil
   132			}
   133			if mode == 'w' || mode == 'r'+'w' {
   134				if fd.wtimer != nil {
   135					fd.wtimer.Stop()
   136				}
   137				fd.wtimer = nil
   138			}
   139		} else {
   140			// Interrupt I/O operation once timer has expired
   141			if mode == 'r' || mode == 'r'+'w' {
   142				fd.rtimer = time.AfterFunc(d, func() {
   143					fd.rtimedout.setTrue()
   144					if fd.raio != nil {
   145						fd.raio.Cancel()
   146					}
   147				})
   148			}
   149			if mode == 'w' || mode == 'r'+'w' {
   150				fd.wtimer = time.AfterFunc(d, func() {
   151					fd.wtimedout.setTrue()
   152					if fd.waio != nil {
   153						fd.waio.Cancel()
   154					}
   155				})
   156			}
   157		}
   158		if !t.IsZero() && d < 0 {
   159			// Interrupt current I/O operation
   160			if mode == 'r' || mode == 'r'+'w' {
   161				fd.rtimedout.setTrue()
   162				if fd.raio != nil {
   163					fd.raio.Cancel()
   164				}
   165			}
   166			if mode == 'w' || mode == 'r'+'w' {
   167				fd.wtimedout.setTrue()
   168				if fd.waio != nil {
   169					fd.waio.Cancel()
   170				}
   171			}
   172		}
   173		return nil
   174	}
   175	
   176	// On Plan 9 only, expose the locking for the net code.
   177	
   178	// ReadLock wraps FD.readLock.
   179	func (fd *FD) ReadLock() error {
   180		return fd.readLock()
   181	}
   182	
   183	// ReadUnlock wraps FD.readUnlock.
   184	func (fd *FD) ReadUnlock() {
   185		fd.readUnlock()
   186	}
   187	
   188	func isHangup(err error) bool {
   189		return err != nil && stringsHasSuffix(err.Error(), "Hangup")
   190	}
   191	
   192	func isInterrupted(err error) bool {
   193		return err != nil && stringsHasSuffix(err.Error(), "interrupted")
   194	}
   195	
   196	// IsPollDescriptor reports whether fd is the descriptor being used by the poller.
   197	// This is only used for testing.
   198	func IsPollDescriptor(fd uintptr) bool {
   199		return false
   200	}
   201	
   202	// RawControl invokes the user-defined function f for a non-IO
   203	// operation.
   204	func (fd *FD) RawControl(f func(uintptr)) error {
   205		return errors.New("not implemented")
   206	}
   207	
   208	// RawRead invokes the user-defined function f for a read operation.
   209	func (fd *FD) RawRead(f func(uintptr) bool) error {
   210		return errors.New("not implemented")
   211	}
   212	
   213	// RawWrite invokes the user-defined function f for a write operation.
   214	func (fd *FD) RawWrite(f func(uintptr) bool) error {
   215		return errors.New("not implemented")
   216	}
   217	

View as plain text