func HostPoolHostPolicy(hp hostpool.HostPool) HostSelectionPolicy {
	return &hostPoolHostPolicy{hostMap: map[string]*HostInfo{}, hp: hp}
}
HostPoolHostPolicy is a host policy which uses the bitly/go-hostpool library
to distribute queries between hosts and prevent sending queries to
unresponsive hosts. When creating the host pool that is passed to the policy
use an empty slice of hosts as the hostpool will be populated later by gocql.
See below for examples of usage:

// Create host selection policy using a simple host pool
cluster.PoolConfig.HostSelectionPolicy = HostPoolHostPolicy(hostpool.New(nil))

// Create host selection policy using an epsilon greddy pool
cluster.PoolConfig.HostSelectionPolicy = HostPoolHostPolicy(
hostpool.NewEpsilonGreedy(nil, 0, &hostpool.LinearEpsilonValueCalculator{}),
)
package gocql
import (
	"fmt"
	"log"
	"sync"
	"sync/atomic"
	"github.com/hailocab/go-hostpool"
)
type cowHostList struct {
	list atomic.Value
	mu   sync.Mutex
}
func (c *cowHostList) String() string {
	return fmt.Sprintf("%+v", c.get())
}
func (c *cowHostList) get() []*HostInfo {
	l, ok := c.list.Load().(*[]*HostInfo)
	if !ok {
		return nil
	}
	return *l
}
func (c *cowHostList) set(list []*HostInfo) {
	c.mu.Lock()
	c.list.Store(&list)
	c.mu.Unlock()
}
func (c *cowHostList) add(host *HostInfo) bool {
	c.mu.Lock()
	l := c.get()
	if n := len(l); n == 0 {
		l = []*HostInfo{host}
	} else {
		newL := make([]*HostInfo, n+1)
		for i := 0; i < n; i++ {
			if host.Equal(l[i]) {
				c.mu.Unlock()
				return false
			}
			newL[i] = l[i]
		}
		newL[n] = host
		l = newL
	}
	c.list.Store(&l)
	c.mu.Unlock()
	return true
}
func (c *cowHostList) update(host *HostInfo) {
	c.mu.Lock()
	l := c.get()
	if len(l) == 0 {
		c.mu.Unlock()
		return
	}
	found := false
	newL := make([]*HostInfo, len(l))
	for i := range l {
		if host.Equal(l[i]) {
			newL[i] = host
			found = true
		} else {
			newL[i] = l[i]
		}
	}
	if found {
		c.list.Store(&newL)
	}
	c.mu.Unlock()
}
func (c *cowHostList) remove(addr string) bool {
	c.mu.Lock()
	l := c.get()
	size := len(l)
	if size == 0 {
		c.mu.Unlock()
		return false
	}
	found := false
	newL := make([]*HostInfo, 0, size)
	for i := 0; i < len(l); i++ {
		if l[i].Peer() != addr {
			newL = append(newL, l[i])
		} else {
			found = true
		}
	}
	if !found {
		c.mu.Unlock()
		return false
	}
	newL = newL[:size-1 : size-1]
	c.list.Store(&newL)
	c.mu.Unlock()
	return true
}
type RetryableQuery interface {
	Attempts() int
	GetConsistency() Consistency
}
type RetryPolicy interface {
	Attempt(RetryableQuery) bool
}
type SimpleRetryPolicy struct {
	NumRetries int  
}
func (s *SimpleRetryPolicy) Attempt(q RetryableQuery) bool {
	return q.Attempts() <= s.NumRetries
}
type HostStateNotifier interface {
	AddHost(host *HostInfo)
	RemoveHost(addr string)
	HostUp(host *HostInfo)
	HostDown(addr string)
}
type HostSelectionPolicy interface {
	HostStateNotifier
	SetPartitioner
	Pick(ExecutableQuery) NextHost
}
type SelectedHost interface {
	Info() *HostInfo
	Mark(error)
}
type selectedHost HostInfo
func (host *selectedHost) Info() *HostInfo {
	return (*HostInfo)(host)
}
func (host *selectedHost) Mark(err error) {}
type NextHost func() SelectedHost
func RoundRobinHostPolicy() HostSelectionPolicy {
	return &roundRobinHostPolicy{}
}
type roundRobinHostPolicy struct {
	hosts cowHostList
	pos   uint32
	mu    sync.RWMutex
}
func (r *roundRobinHostPolicy) SetPartitioner(partitioner string) {
}
func (r *roundRobinHostPolicy) Pick(qry ExecutableQuery) NextHost {
	var i int
	return func() SelectedHost {
		hosts := r.hosts.get()
		if len(hosts) == 0 {
			return nil
		}
		pos := atomic.AddUint32(&r.pos, 1) - 1
		if i >= len(hosts) {
			return nil
		}
		host := hosts[(pos)%uint32(len(hosts))]
		i++
		return (*selectedHost)(host)
	}
}
func (r *roundRobinHostPolicy) AddHost(host *HostInfo) {
	r.hosts.add(host)
}
func (r *roundRobinHostPolicy) RemoveHost(addr string) {
	r.hosts.remove(addr)
}
func (r *roundRobinHostPolicy) HostUp(host *HostInfo) {
	r.AddHost(host)
}
func (r *roundRobinHostPolicy) HostDown(addr string) {
	r.RemoveHost(addr)
}
func TokenAwareHostPolicy(fallback HostSelectionPolicy) HostSelectionPolicy {
	return &tokenAwareHostPolicy{fallback: fallback}
}
type tokenAwareHostPolicy struct {
	hosts       cowHostList
	mu          sync.RWMutex
	partitioner string
	tokenRing   *tokenRing
	fallback    HostSelectionPolicy
}
func (t *tokenAwareHostPolicy) SetPartitioner(partitioner string) {
	t.mu.Lock()
	defer t.mu.Unlock()
	if t.partitioner != partitioner {
		t.fallback.SetPartitioner(partitioner)
		t.partitioner = partitioner
		t.resetTokenRing()
	}
}
func (t *tokenAwareHostPolicy) AddHost(host *HostInfo) {
	t.hosts.add(host)
	t.fallback.AddHost(host)
	t.mu.Lock()
	t.resetTokenRing()
	t.mu.Unlock()
}
func (t *tokenAwareHostPolicy) RemoveHost(addr string) {
	t.hosts.remove(addr)
	t.fallback.RemoveHost(addr)
	t.mu.Lock()
	t.resetTokenRing()
	t.mu.Unlock()
}
func (t *tokenAwareHostPolicy) HostUp(host *HostInfo) {
	t.AddHost(host)
}
func (t *tokenAwareHostPolicy) HostDown(addr string) {
	t.RemoveHost(addr)
}
func (t *tokenAwareHostPolicy) resetTokenRing() {
	if t.partitioner == "" {
		return
	}
	hosts := t.hosts.get()
	tokenRing, err := newTokenRing(t.partitioner, hosts)
	if err != nil {
		log.Printf("Unable to update the token ring due to error: %s", err)
		return
	}
	t.tokenRing = tokenRing
}
func (t *tokenAwareHostPolicy) Pick(qry ExecutableQuery) NextHost {
	if qry == nil {
		return t.fallback.Pick(qry)
	}
	routingKey, err := qry.GetRoutingKey()
	if err != nil {
		return t.fallback.Pick(qry)
	}
	if routingKey == nil {
		return t.fallback.Pick(qry)
	}
	t.mu.RLock()
	host := t.tokenRing.GetHostForPartitionKey(routingKey)
	t.mu.RUnlock()
	if host == nil {
		return t.fallback.Pick(qry)
	}
	var (
		hostReturned bool
		fallbackIter NextHost
	)
	return func() SelectedHost {
		if !hostReturned {
			hostReturned = true
			return (*selectedHost)(host)
		}
		if fallbackIter == nil {
			fallbackIter = t.fallback.Pick(qry)
		}
		fallbackHost := fallbackIter()
		if fallbackHost != nil && fallbackHost.Info() == host {
			fallbackHost = fallbackIter()
		}
		return fallbackHost
	}
}