initial commit
This commit is contained in:
commit
c67729332c
26 changed files with 1612 additions and 0 deletions
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/pkg
|
||||
/bin
|
||||
29
Godeps/_workspace/src/github.com/creack/goselect/.gitignore
generated
vendored
Normal file
29
Godeps/_workspace/src/github.com/creack/goselect/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
go-select*
|
||||
goselect*
|
||||
example-*
|
||||
example/example
|
||||
5
Godeps/_workspace/src/github.com/creack/goselect/Dockerfile
generated
vendored
Normal file
5
Godeps/_workspace/src/github.com/creack/goselect/Dockerfile
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
FROM google/golang:stable
|
||||
MAINTAINER Guillaume J. Charmes <guillaume@charmes.net>
|
||||
CMD /tmp/a.out
|
||||
ADD . /src
|
||||
RUN cd /src && go build -o /tmp/a.out
|
||||
22
Godeps/_workspace/src/github.com/creack/goselect/LICENSE
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/creack/goselect/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Guillaume J. Charmes
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
30
Godeps/_workspace/src/github.com/creack/goselect/README.md
generated
vendored
Normal file
30
Godeps/_workspace/src/github.com/creack/goselect/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# go-select
|
||||
|
||||
select(2) implementation in Go
|
||||
|
||||
## Supported platforms
|
||||
|
||||
| | 386 | amd64 | arm |
|
||||
|---------------|-----|-------|-----|
|
||||
| **linux** | yes | yes | yes |
|
||||
| **darwin** | yes | yes | n/a |
|
||||
| **freebsd** | yes | yes | yes |
|
||||
| **openbsd** | yes | yes | yes |
|
||||
| **netbsd** | yes | yes | yes |
|
||||
| **dragonfly** | n/a | yes | n/a |
|
||||
| **solaris** | n/a | no | n/a |
|
||||
| **plan9** | no | no | n/a |
|
||||
| **windows** | yes | yes | n/a |
|
||||
| **android** | n/a | n/a | no |
|
||||
|
||||
*n/a: platform not supported by Go
|
||||
|
||||
Go on `plan9` and `solaris` do not implement `syscall.Select` not `syscall.SYS_SELECT`.
|
||||
|
||||
## Cross compile
|
||||
|
||||
Using davecheney's https://github.com/davecheney/golang-crosscompile
|
||||
|
||||
```
|
||||
export PLATFORMS="darwin/386 darwin/amd64 freebsd/386 freebsd/amd64 freebsd/arm linux/386 linux/amd64 linux/arm windows/386 windows/amd64 openbsd/386 openbsd/amd64 netbsd/386 netbsd/amd64 dragonfly/amd64 plan9/386 plan9/amd64 solaris/amd64"
|
||||
```
|
||||
369
Godeps/_workspace/src/github.com/creack/goselect/example/main.go
generated
vendored
Normal file
369
Godeps/_workspace/src/github.com/creack/goselect/example/main.go
generated
vendored
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/creack/goselect"
|
||||
)
|
||||
|
||||
type fder interface {
|
||||
Fd() uintptr
|
||||
}
|
||||
|
||||
// ErrNotFder .
|
||||
var ErrNotFder = fmt.Errorf("Not a fder")
|
||||
|
||||
type readFder interface {
|
||||
io.Reader
|
||||
fder
|
||||
}
|
||||
|
||||
type writeFder interface {
|
||||
io.Reader
|
||||
fder
|
||||
}
|
||||
|
||||
// SelectReader .
|
||||
type selectReader struct {
|
||||
readFder
|
||||
ready chan struct{}
|
||||
stop chan struct{}
|
||||
}
|
||||
|
||||
func (r *selectReader) Read(buf []byte) (int, error) {
|
||||
select {
|
||||
case <-r.stop:
|
||||
return 0, io.EOF
|
||||
case <-r.ready:
|
||||
return r.readFder.Read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
// Select .
|
||||
type Select struct {
|
||||
readers []*selectReader
|
||||
writers []writeFder
|
||||
controlPipeR *os.File
|
||||
controlPipeW *os.File
|
||||
}
|
||||
|
||||
// NewSelect .
|
||||
func NewSelect() (*Select, error) {
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &Select{
|
||||
readers: []*selectReader{},
|
||||
writers: []writeFder{},
|
||||
controlPipeR: r,
|
||||
controlPipeW: w,
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Select) run() {
|
||||
rFDSet := &goselect.FDSet{}
|
||||
var max uintptr
|
||||
var fd uintptr
|
||||
for {
|
||||
// TODO: this can be cached and changed only upon controlePipe event.
|
||||
rFDSet.Zero()
|
||||
fd = s.controlPipeR.Fd()
|
||||
max = fd
|
||||
rFDSet.Set(fd)
|
||||
for _, r := range s.readers {
|
||||
fd = r.Fd()
|
||||
if max < fd {
|
||||
max = fd
|
||||
}
|
||||
rFDSet.Set(fd)
|
||||
}
|
||||
println("-------> preselect")
|
||||
if err := goselect.Select(int(max)+1, rFDSet, nil, nil, -1); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for i := uintptr(0); i < goselect.FD_SETSIZE; i++ {
|
||||
if rFDSet.IsSet(i) {
|
||||
println(i, "is ready")
|
||||
}
|
||||
}
|
||||
println("<-------- postselect")
|
||||
for _, r := range s.readers {
|
||||
if rFDSet.IsSet(r.Fd()) {
|
||||
func(r *selectReader) { r.ready <- struct{}{} }(r)
|
||||
}
|
||||
}
|
||||
if rFDSet.IsSet(s.controlPipeR.Fd()) {
|
||||
buf := make([]byte, 1024)
|
||||
n, err := s.controlPipeR.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("----> control: %s\n", buf[:n])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewReader .
|
||||
func (s *Select) NewReader(r io.Reader) (io.Reader, error) {
|
||||
rr, ok := r.(readFder)
|
||||
if !ok {
|
||||
return nil, ErrNotFder
|
||||
}
|
||||
ret := &selectReader{
|
||||
readFder: rr,
|
||||
ready: make(chan struct{}),
|
||||
stop: make(chan struct{}),
|
||||
}
|
||||
s.readers = append(s.readers, ret)
|
||||
if _, err := s.controlPipeW.Write([]byte("newreader")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func test6() error {
|
||||
s, err := NewSelect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = s
|
||||
|
||||
fmt.Printf("%d\n", os.Getpid())
|
||||
const MAX = 4
|
||||
rs := []io.Reader{}
|
||||
ws := []io.Writer{}
|
||||
for i := 0; i < MAX; i++ {
|
||||
r, w, _ := os.Pipe()
|
||||
println(i, "--->", r.Fd(), w.Fd())
|
||||
rs = append(rs, r)
|
||||
ws = append(ws, w)
|
||||
}
|
||||
|
||||
c := make(chan struct{})
|
||||
wg := sync.WaitGroup{}
|
||||
for i := 0; i < MAX; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
time.Sleep(2 * time.Second)
|
||||
<-c
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
time.Sleep(4 * time.Second)
|
||||
close(c)
|
||||
wg.Wait()
|
||||
for i := 0; i < MAX; i++ {
|
||||
time.Sleep(5 * time.Second)
|
||||
wg.Add(1)
|
||||
go func(r io.Reader, i int) {
|
||||
rr, _ := s.NewReader(r)
|
||||
r = rr
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
log.Printf("[%d] error read: %s\n", i, err)
|
||||
break
|
||||
}
|
||||
_ = n
|
||||
fmt.Printf("[%d] %s\n", i, buf[:n])
|
||||
}
|
||||
wg.Done()
|
||||
}(rs[i], i)
|
||||
}
|
||||
for i := 0; i < 1; i++ {
|
||||
for i := 0; i < MAX; i++ {
|
||||
fmt.Fprintf(ws[i], "{%d} hello", i)
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func test4() error {
|
||||
rFDSet := &goselect.FDSet{}
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
// TODO: this can be cached and changed only upon controlePipe event.
|
||||
rFDSet.Zero()
|
||||
rFDSet.Set(os.Stdin.Fd())
|
||||
if err := goselect.Select(int(os.Stdin.Fd())+1, rFDSet, nil, nil, -1); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := uintptr(0); i < goselect.FD_SETSIZE; i++ {
|
||||
if rFDSet.IsSet(i) {
|
||||
println(i, "is ready")
|
||||
}
|
||||
}
|
||||
if rFDSet.IsSet(os.Stdin.Fd()) {
|
||||
n, err := os.Stdin.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
fmt.Printf("---->: %s\n", buf[:n])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
f *os.File
|
||||
queue [][]byte
|
||||
}
|
||||
|
||||
func (c *Client) Push(msg []byte) {
|
||||
c.queue = append(c.queue, msg)
|
||||
println(len(c.queue))
|
||||
}
|
||||
|
||||
func (c *Client) Pop() []byte {
|
||||
if len(c.queue) == 0 {
|
||||
return nil
|
||||
}
|
||||
tmp := c.queue[0]
|
||||
c.queue = c.queue[1:]
|
||||
return tmp
|
||||
}
|
||||
|
||||
func testServer() error {
|
||||
l, err := net.Listen("tcp", "0.0.0.0:8080")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ll, ok := l.(*net.TCPListener)
|
||||
if !ok {
|
||||
return fmt.Errorf("wrong listener type")
|
||||
}
|
||||
|
||||
llf, err := ll.File()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rFDSet := &goselect.FDSet{}
|
||||
wFDSet := &goselect.FDSet{}
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
var max, fd uintptr
|
||||
|
||||
clients := []*Client{}
|
||||
|
||||
for {
|
||||
// TODO: this can be cached and changed only upon controlePipe event.
|
||||
rFDSet.Zero()
|
||||
wFDSet.Zero()
|
||||
fd = llf.Fd()
|
||||
max = fd
|
||||
rFDSet.Set(fd)
|
||||
|
||||
for _, c := range clients {
|
||||
fd = c.f.Fd()
|
||||
rFDSet.Set(fd)
|
||||
if len(c.queue) > 0 {
|
||||
wFDSet.Set(fd)
|
||||
}
|
||||
if max < fd {
|
||||
max = fd
|
||||
}
|
||||
}
|
||||
|
||||
if err := goselect.Select(int(max)+1, rFDSet, wFDSet, nil, -1); err != nil {
|
||||
return err
|
||||
}
|
||||
println("-->")
|
||||
|
||||
// Watch for new clients
|
||||
if rFDSet.IsSet(llf.Fd()) {
|
||||
c, err := ll.AcceptTCP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := c.File()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fd = f.Fd()
|
||||
println("New client:", fd)
|
||||
clients = append(clients, &Client{f: f})
|
||||
}
|
||||
|
||||
// Watch for client activity
|
||||
for _, c := range clients {
|
||||
fd = c.f.Fd()
|
||||
if rFDSet.IsSet(fd) {
|
||||
n, err := c.f.Read(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%s", buf[:n])
|
||||
for _, cc := range clients {
|
||||
if c != cc {
|
||||
cc.Push(buf[:n])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send message to clients
|
||||
for _, c := range clients {
|
||||
fd = c.f.Fd()
|
||||
if wFDSet.IsSet(fd) {
|
||||
msg := c.Pop()
|
||||
fmt.Printf("%d write ready: %v\n", fd, msg)
|
||||
if msg != nil {
|
||||
_, err := c.f.Write(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := testServer(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func test5() error {
|
||||
wg := sync.WaitGroup{}
|
||||
fmt.Printf("%d\n", os.Getpid())
|
||||
for i := 0; i < 200; i++ {
|
||||
r, w, _ := os.Pipe()
|
||||
go func(w io.Writer) {
|
||||
for {
|
||||
w.Write([]byte("hello"))
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}(w)
|
||||
wg.Add(1)
|
||||
go func(r io.Reader) {
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
_, err := r.Read(buf)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}(r)
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
33
Godeps/_workspace/src/github.com/creack/goselect/fdset.go
generated
vendored
Normal file
33
Godeps/_workspace/src/github.com/creack/goselect/fdset.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// +build !freebsd,!windows,!plan9
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
const FD_SETSIZE = syscall.FD_SETSIZE
|
||||
|
||||
// FDSet wraps syscall.FdSet with convenience methods
|
||||
type FDSet syscall.FdSet
|
||||
|
||||
// Set adds the fd to the set
|
||||
func (fds *FDSet) Set(fd uintptr) {
|
||||
fds.Bits[fd/NFDBITS] |= (1 << (fd % NFDBITS))
|
||||
}
|
||||
|
||||
// Clear remove the fd from the set
|
||||
func (fds *FDSet) Clear(fd uintptr) {
|
||||
fds.Bits[fd/NFDBITS] &^= (1 << (fd % NFDBITS))
|
||||
}
|
||||
|
||||
// IsSet check if the given fd is set
|
||||
func (fds *FDSet) IsSet(fd uintptr) bool {
|
||||
return fds.Bits[fd/NFDBITS]&(1<<(fd%NFDBITS)) != 0
|
||||
}
|
||||
|
||||
// Keep a null set to avoid reinstatiation
|
||||
var nullFdSet = &FDSet{}
|
||||
|
||||
// Zero empties the Set
|
||||
func (fds *FDSet) Zero() {
|
||||
copy(fds.Bits[:], (nullFdSet).Bits[:])
|
||||
}
|
||||
10
Godeps/_workspace/src/github.com/creack/goselect/fdset_32.go
generated
vendored
Normal file
10
Godeps/_workspace/src/github.com/creack/goselect/fdset_32.go
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// +build darwin openbsd netbsd 386 arm
|
||||
|
||||
package goselect
|
||||
|
||||
// darwin, netbsd and openbsd uses uint32 on both amd64 and 386
|
||||
|
||||
const (
|
||||
// NFDBITS is the amount of bits per mask
|
||||
NFDBITS = 4 * 8
|
||||
)
|
||||
10
Godeps/_workspace/src/github.com/creack/goselect/fdset_64.go
generated
vendored
Normal file
10
Godeps/_workspace/src/github.com/creack/goselect/fdset_64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// +build amd64,!darwin,!netbsd,!openbsd
|
||||
|
||||
package goselect
|
||||
|
||||
// darwin, netbsd and openbsd uses uint32 on both amd64 and 386
|
||||
|
||||
const (
|
||||
// NFDBITS is the amount of bits per mask
|
||||
NFDBITS = 8 * 8
|
||||
)
|
||||
93
Godeps/_workspace/src/github.com/creack/goselect/fdset_doc.go
generated
vendored
Normal file
93
Godeps/_workspace/src/github.com/creack/goselect/fdset_doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package goselect
|
||||
|
||||
/**
|
||||
From: XCode's MacOSX10.10.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/sys/select.h
|
||||
--
|
||||
// darwin/amd64 / 386
|
||||
sizeof(__int32_t) == 4
|
||||
--
|
||||
|
||||
typedef __int32_t __fd_mask;
|
||||
|
||||
#define FD_SETSIZE 1024
|
||||
#define __NFDBITS (sizeof(__fd_mask) * 8)
|
||||
#define __howmany(x, y) ((((x) % (y)) == 0) ? ((x) / (y)) : (((x) / (y)) + 1))
|
||||
|
||||
typedef struct fd_set {
|
||||
__fd_mask fds_bits[__howmany(__FD_SETSIZE, __NFDBITS)];
|
||||
} fd_set;
|
||||
|
||||
#define __FD_MASK(n) ((__fd_mask)1 << ((n) % __NFDBITS))
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/__NFDBITS] |= __FD_MASK(n))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/__NFDBITS] &= ~__FD_MASK(n))
|
||||
#define FD_ISSET(n, p) (((p)->fds_bits[(n)/__NFDBITS] & __FD_MASK(n)) != 0)
|
||||
*/
|
||||
|
||||
/**
|
||||
From: /usr/include/i386-linux-gnu/sys/select.h
|
||||
--
|
||||
// linux/i686
|
||||
sizeof(long int) == 4
|
||||
--
|
||||
|
||||
typedef long int __fd_mask;
|
||||
|
||||
#define FD_SETSIZE 1024
|
||||
#define __NFDBITS (sizeof(__fd_mask) * 8)
|
||||
|
||||
|
||||
typedef struct fd_set {
|
||||
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
|
||||
} fd_set;
|
||||
|
||||
#define __FD_MASK(n) ((__fd_mask)1 << ((n) % __NFDBITS))
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/__NFDBITS] |= __FD_MASK(n))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/__NFDBITS] &= ~__FD_MASK(n))
|
||||
#define FD_ISSET(n, p) (((p)->fds_bits[(n)/__NFDBITS] & __FD_MASK(n)) != 0)
|
||||
*/
|
||||
|
||||
/**
|
||||
From: /usr/include/x86_64-linux-gnu/sys/select.h
|
||||
--
|
||||
// linux/amd64
|
||||
sizeof(long int) == 8
|
||||
--
|
||||
|
||||
typedef long int __fd_mask;
|
||||
|
||||
#define FD_SETSIZE 1024
|
||||
#define __NFDBITS (sizeof(__fd_mask) * 8)
|
||||
|
||||
|
||||
typedef struct fd_set {
|
||||
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
|
||||
} fd_set;
|
||||
|
||||
#define __FD_MASK(n) ((__fd_mask)1 << ((n) % __NFDBITS))
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/__NFDBITS] |= __FD_MASK(n))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/__NFDBITS] &= ~__FD_MASK(n))
|
||||
#define FD_ISSET(n, p) (((p)->fds_bits[(n)/__NFDBITS] & __FD_MASK(n)) != 0)
|
||||
*/
|
||||
|
||||
/**
|
||||
From: /usr/include/sys/select.h
|
||||
--
|
||||
// freebsd/amd64
|
||||
sizeof(unsigned long) == 8
|
||||
--
|
||||
|
||||
typedef unsigned long __fd_mask;
|
||||
|
||||
#define FD_SETSIZE 1024U
|
||||
#define __NFDBITS (sizeof(__fd_mask) * 8)
|
||||
#define _howmany(x, y) (((x) + ((y) - 1)) / (y))
|
||||
|
||||
typedef struct fd_set {
|
||||
__fd_mask fds_bits[_howmany(FD_SETSIZE, __NFDBITS)];
|
||||
} fd_set;
|
||||
|
||||
#define __FD_MASK(n) ((__fd_mask)1 << ((n) % __NFDBITS))
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/__NFDBITS] |= __FD_MASK(n))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/__NFDBITS] &= ~__FD_MASK(n))
|
||||
#define FD_ISSET(n, p) (((p)->fds_bits[(n)/__NFDBITS] & __FD_MASK(n)) != 0)
|
||||
*/
|
||||
33
Godeps/_workspace/src/github.com/creack/goselect/fdset_freebsd.go
generated
vendored
Normal file
33
Godeps/_workspace/src/github.com/creack/goselect/fdset_freebsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// +build freebsd
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
const FD_SETSIZE = syscall.FD_SETSIZE
|
||||
|
||||
// FDSet wraps syscall.FdSet with convenience methods
|
||||
type FDSet syscall.FdSet
|
||||
|
||||
// Set adds the fd to the set
|
||||
func (fds *FDSet) Set(fd uintptr) {
|
||||
fds.X__fds_bits[fd/NFDBITS] |= (1 << (fd % NFDBITS))
|
||||
}
|
||||
|
||||
// Clear remove the fd from the set
|
||||
func (fds *FDSet) Clear(fd uintptr) {
|
||||
fds.X__fds_bits[fd/NFDBITS] &^= (1 << (fd % NFDBITS))
|
||||
}
|
||||
|
||||
// IsSet check if the given fd is set
|
||||
func (fds *FDSet) IsSet(fd uintptr) bool {
|
||||
return fds.X__fds_bits[fd/NFDBITS]&(1<<(fd%NFDBITS)) != 0
|
||||
}
|
||||
|
||||
// Keep a null set to avoid reinstatiation
|
||||
var nullFdSet = &FDSet{}
|
||||
|
||||
// Zero empties the Set
|
||||
func (fds *FDSet) Zero() {
|
||||
copy(fds.X__fds_bits[:], (nullFdSet).X__fds_bits[:])
|
||||
}
|
||||
20
Godeps/_workspace/src/github.com/creack/goselect/fdset_unsupported.go
generated
vendored
Normal file
20
Godeps/_workspace/src/github.com/creack/goselect/fdset_unsupported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// +build plan9
|
||||
|
||||
package goselect
|
||||
|
||||
const FD_SETSIZE = 0
|
||||
|
||||
// FDSet wraps syscall.FdSet with convenience methods
|
||||
type FDSet struct{}
|
||||
|
||||
// Set adds the fd to the set
|
||||
func (fds *FDSet) Set(fd uintptr) {}
|
||||
|
||||
// Clear remove the fd from the set
|
||||
func (fds *FDSet) Clear(fd uintptr) {}
|
||||
|
||||
// IsSet check if the given fd is set
|
||||
func (fds *FDSet) IsSet(fd uintptr) bool { return false }
|
||||
|
||||
// Zero empties the Set
|
||||
func (fds *FDSet) Zero() {}
|
||||
57
Godeps/_workspace/src/github.com/creack/goselect/fdset_windows.go
generated
vendored
Normal file
57
Godeps/_workspace/src/github.com/creack/goselect/fdset_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// +build windows
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
const FD_SETSIZE = 64
|
||||
|
||||
// FDSet extracted from mingw libs source code
|
||||
type FDSet struct {
|
||||
fd_count uint
|
||||
fd_array [FD_SETSIZE]uintptr
|
||||
}
|
||||
|
||||
// Set adds the fd to the set
|
||||
func (fds *FDSet) Set(fd uintptr) {
|
||||
var i uint
|
||||
for i = 0; i < fds.fd_count; i++ {
|
||||
if fds.fd_array[i] == fd {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == fds.fd_count {
|
||||
if fds.fd_count < FD_SETSIZE {
|
||||
fds.fd_array[i] = fd
|
||||
fds.fd_count++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear remove the fd from the set
|
||||
func (fds *FDSet) Clear(fd uintptr) {
|
||||
var i uint
|
||||
for i = 0; i < fds.fd_count; i++ {
|
||||
if fds.fd_array[i] == fd {
|
||||
for i < fds.fd_count-1 {
|
||||
fds.fd_array[i] = fds.fd_array[i+1]
|
||||
i++
|
||||
}
|
||||
fds.fd_count--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsSet check if the given fd is set
|
||||
func (fds *FDSet) IsSet(fd uintptr) bool {
|
||||
if isset, err := __WSAFDIsSet(syscall.Handle(fd), fds); err == nil && isset != 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Zero empties the Set
|
||||
func (fds *FDSet) Zero() {
|
||||
fds.fd_count = 0
|
||||
}
|
||||
28
Godeps/_workspace/src/github.com/creack/goselect/select.go
generated
vendored
Normal file
28
Godeps/_workspace/src/github.com/creack/goselect/select.go
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package goselect
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Select wraps syscall.Select with Go types
|
||||
func Select(n int, r, w, e *FDSet, timeout time.Duration) error {
|
||||
var timeval *syscall.Timeval
|
||||
if timeout >= 0 {
|
||||
t := syscall.NsecToTimeval(timeout.Nanoseconds())
|
||||
timeval = &t
|
||||
}
|
||||
|
||||
return sysSelect(n, r, w, e, timeval)
|
||||
}
|
||||
|
||||
// RetrySelect wraps syscall.Select with Go types, and retries a number of times, with a given retryDelay.
|
||||
func RetrySelect(n int, r, w, e *FDSet, timeout time.Duration, retries int, retryDelay time.Duration) (err error) {
|
||||
for i := 0; i < retries; i++ {
|
||||
if err = Select(n, r, w, e, timeout); err != syscall.EINTR {
|
||||
return err
|
||||
}
|
||||
time.Sleep(retryDelay)
|
||||
}
|
||||
return err
|
||||
}
|
||||
10
Godeps/_workspace/src/github.com/creack/goselect/select_linux.go
generated
vendored
Normal file
10
Godeps/_workspace/src/github.com/creack/goselect/select_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// +build linux
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
|
||||
_, err := syscall.Select(n, (*syscall.FdSet)(r), (*syscall.FdSet)(w), (*syscall.FdSet)(e), timeout)
|
||||
return err
|
||||
}
|
||||
9
Godeps/_workspace/src/github.com/creack/goselect/select_other.go
generated
vendored
Normal file
9
Godeps/_workspace/src/github.com/creack/goselect/select_other.go
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// +build !linux,!windows,!plan9,!solaris
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
|
||||
return syscall.Select(n, (*syscall.FdSet)(r), (*syscall.FdSet)(w), (*syscall.FdSet)(e), timeout)
|
||||
}
|
||||
16
Godeps/_workspace/src/github.com/creack/goselect/select_unsupported.go
generated
vendored
Normal file
16
Godeps/_workspace/src/github.com/creack/goselect/select_unsupported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// +build plan9 solaris
|
||||
|
||||
package goselect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ErrUnsupported .
|
||||
var ErrUnsupported = fmt.Errorf("Platofrm %s/%s unsupported", runtime.GOOS, runtime.GOARCH)
|
||||
|
||||
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
|
||||
return ErrUnsupported
|
||||
}
|
||||
13
Godeps/_workspace/src/github.com/creack/goselect/select_windows.go
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/creack/goselect/select_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// +build windows
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
//sys _select(nfds int, readfds *FDSet, writefds *FDSet, exceptfds *FDSet, timeout *syscall.Timeval) (total int, err error) = ws2_32.select
|
||||
//sys __WSAFDIsSet(handle syscall.Handle, fdset *FDSet) (isset int, err error) = ws2_32.__WSAFDIsSet
|
||||
|
||||
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
|
||||
_, err := _select(n, r, w, e, timeout)
|
||||
return err
|
||||
}
|
||||
41
Godeps/_workspace/src/github.com/creack/goselect/zselect_windows.go
generated
vendored
Normal file
41
Godeps/_workspace/src/github.com/creack/goselect/zselect_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
||||
|
||||
package goselect
|
||||
|
||||
import "unsafe"
|
||||
import "syscall"
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
var (
|
||||
modws2_32 = syscall.NewLazyDLL("ws2_32.dll")
|
||||
|
||||
procselect = modws2_32.NewProc("select")
|
||||
proc__WSAFDIsSet = modws2_32.NewProc("__WSAFDIsSet")
|
||||
)
|
||||
|
||||
func _select(nfds int, readfds *FDSet, writefds *FDSet, exceptfds *FDSet, timeout *syscall.Timeval) (total int, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procselect.Addr(), 5, uintptr(nfds), uintptr(unsafe.Pointer(readfds)), uintptr(unsafe.Pointer(writefds)), uintptr(unsafe.Pointer(exceptfds)), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
total = int(r0)
|
||||
if total == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func __WSAFDIsSet(handle syscall.Handle, fdset *FDSet) (isset int, err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc__WSAFDIsSet.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(fdset)), 0)
|
||||
isset = int(r0)
|
||||
if isset == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue