func (c *throttledConn) SetDeadline(t time.Time) error {
	return c.originalConn.SetDeadline(t)
}
Implements the net.Conn SetDeadline method
package iothrottler
import (
	"errors"
	"io"
	"log"
	"math"
	"net"
	"time"
)
type Bandwidth int64
const (
	BytesPerSecond Bandwidth = 1
	Kbps = BytesPerSecond * (1024 / 8)
	Mbps = Kbps * 1024
	Gbps = Mbps * 1024
	Unlimited = math.MaxInt64
)
type IOThrottlerPool struct {
	bandwidthSettingChan chan Bandwidth
	bandwidthAllocatorChan chan Bandwidth
	bandwidthFreeChan chan Bandwidth
	clientCountChan chan int64
	releasePoolChan chan bool
}
func NewIOThrottlerPool(bandwidth Bandwidth) *IOThrottlerPool {
	pool := &IOThrottlerPool{make(chan Bandwidth), make(chan Bandwidth), make(chan Bandwidth), make(chan int64), make(chan bool)}
	go throttlerPoolDriver(pool)
	pool.bandwidthSettingChan <- bandwidth
	return pool
}
func throttlerPoolDriver(pool *IOThrottlerPool) {
	clientCount := int64(0)
	currentBandwidth := Bandwidth(0)
	totalbandwidth := Bandwidth(0)
	allocationSize := Bandwidth(0)
	timeout := time.NewTicker(time.Second)
	var thisBandwidthAllocatorChan chan Bandwidth = nil
	timeout.Stop()
	recalculateAllocationSize := func() {
		if currentBandwidth == Unlimited {
			totalbandwidth = Unlimited
		}
		if totalbandwidth == Unlimited {
			allocationSize = Unlimited
		} else {
			if clientCount == 0 {
				allocationSize = totalbandwidth / 2
			} else {
				allocationSize = totalbandwidth / Bandwidth(clientCount*2)
			}
			if allocationSize < 0 {
				allocationSize = 0
			}
			if allocationSize == 0 && totalbandwidth > 0 {
				allocationSize = 1
			}
		}
		if allocationSize > 0 {
			thisBandwidthAllocatorChan = pool.bandwidthAllocatorChan
		} else {
			thisBandwidthAllocatorChan = nil
		}
	}
	for {
		select {
		case release := <-pool.releasePoolChan:
			if release {
				close(pool.bandwidthAllocatorChan)
				close(pool.bandwidthFreeChan)
				pool.releasePoolChan <- true
				close(pool.releasePoolChan)
				close(pool.clientCountChan)
				return
			}
		case increment := <-pool.clientCountChan:
			if clientCount == 0 {
				timeout.Reset(time.Second)
			}
			clientCount += increment
			if clientCount == 0 {
				timeout.Stop()
			}
			recalculateAllocationSize()
		case newBandwidth := <-pool.bandwidthSettingChan:
			totalbandwidth = newBandwidth
			currentBandwidth = newBandwidth
			recalculateAllocationSize()
		case thisBandwidthAllocatorChan <- allocationSize:
			if Unlimited != totalbandwidth {
				totalbandwidth -= allocationSize
				recalculateAllocationSize()
			}
		case returnSize := <-pool.bandwidthFreeChan:
			if Unlimited != totalbandwidth {
				totalbandwidth += returnSize
			}
			recalculateAllocationSize()
		case <-timeout.C:
			if clientCount > 0 {
				if Unlimited != totalbandwidth {
					totalbandwidth += currentBandwidth
					recalculateAllocationSize()
				}
			}
		}
	}
}
func (pool *IOThrottlerPool) ReleasePool() {
	defer func() {
		recover()
	}()
	pool.releasePoolChan <- true
	<-pool.releasePoolChan
}
func (pool *IOThrottlerPool) SetBandwidth(bandwith Bandwidth) {
	pool.bandwidthSettingChan <- bandwith
}
func orErrors(er0, er1 error) error {
	if er0 != nil {
		return er0
	}
	return er1
}
func twiddleClientCount(p *IOThrottlerPool, change int64) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = errors.New("Pool has been released")
		}
	}()
	p.clientCountChan <- change
	return nil
}
type throttledReadCloser struct {
	origReadCloser io.ReadCloser
	pool           *IOThrottlerPool
}
type throttledWriteCloser struct {
	origWriteCloser io.WriteCloser
	pool            *IOThrottlerPool
}
type throttledReadWriteCloser struct {
	throttledReadCloser
	throttledWriteCloser
}
func (t *throttledReadCloser) Read(b []byte) (int, error) {
	allocation, ok := <-t.pool.bandwidthAllocatorChan
	if !ok {
		return 0, errors.New("Pool has been released")
	}
	toRead := Bandwidth(len(b))
	if allocation < Bandwidth(len(b)) {
		toRead = allocation
	}
	n, err := t.origReadCloser.Read(b[:toRead])
	if Bandwidth(n) < allocation && allocation != Unlimited {
		t.pool.bandwidthFreeChan <- allocation - Bandwidth(n)
	}
	return n, err
}
func (t *throttledWriteCloser) Write(data []byte) (int, error) {
	allocation := Bandwidth(0)
	for allocation < Bandwidth(len(data)) {
		thisAllocation, ok := <-t.pool.bandwidthAllocatorChan
		if !ok {
			return 0, errors.New("Pool has been released")
		}
		allocation += thisAllocation
	}
	n, err := t.origWriteCloser.Write(data)
	if Bandwidth(n) < allocation && allocation != Unlimited {
		t.pool.bandwidthFreeChan <- allocation - Bandwidth(n)
	}
	return n, err
}
func (t *throttledReadCloser) Close() error {
	err := twiddleClientCount(t.pool, -1)
	return orErrors(err, t.origReadCloser.Close())
}
func (t *throttledWriteCloser) Close() error {
	err := twiddleClientCount(t.pool, -1)
	return orErrors(err, t.origWriteCloser.Close())
}
func (t *throttledReadWriteCloser) Close() error {
	err := twiddleClientCount(t.throttledReadCloser.pool, -1)
	return orErrors(err, t.throttledReadCloser.origReadCloser.Close())
}
func (p *IOThrottlerPool) AddReader(reader io.ReadCloser) (io.ReadCloser, error) {
	err := twiddleClientCount(p, 1)
	if err != nil {
		return nil, err
	}
	return &throttledReadCloser{reader, p}, nil
}
func (p *IOThrottlerPool) AddWriter(writer io.WriteCloser) (io.WriteCloser, error) {
	err := twiddleClientCount(p, 1)
	if err != nil {
		return nil, err
	}
	return &throttledWriteCloser{writer, p}, nil
}
func (p *IOThrottlerPool) AddReadWriter(readWriter io.ReadWriteCloser) (io.ReadWriteCloser, error) {
	err := twiddleClientCount(p, 1)
	if err != nil {
		return nil, err
	}
	return &throttledReadWriteCloser{throttledReadCloser{readWriter, p},
		throttledWriteCloser{readWriter, p}}, err
}
type throttledConn struct {
	throttledReadWriteCloser
	originalConn net.Conn
}
func (c *throttledConn) LocalAddr() net.Addr {
	return c.originalConn.LocalAddr()
}
func (c *throttledConn) RemoteAddr() net.Addr {
	return c.originalConn.RemoteAddr()
}