Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

connpool: remove fullCond & use free list & all set

We need, at all times, to have a set of every open connection a pool
has.  At the same time, we need to have a list of not-closed but
available connections.  Keeping these two concepts separate simplifies
things.
  • Loading branch information...
commit dac6ce16677b73bd4cf8f9e16134238046c9ee53 1 parent 72f50a8
Bobby Powers authored

Showing 1 changed file with 25 additions and 25 deletions. Show diff stats Hide diff stats

  1. +25 25 radix/connection_pool.go
50 radix/connection_pool.go
... ... @@ -1,6 +1,7 @@
1 1 package radix
2 2
3 3 import (
  4 + "container/list"
4 5 "sync"
5 6 )
6 7
@@ -8,9 +9,9 @@ import (
8 9 type connPool struct {
9 10 available int
10 11 capacity int
11   - pool []*connection
  12 + all map[*connection]struct{}
  13 + free list.List
12 14 lock sync.Mutex
13   - fullCond *sync.Cond
14 15 emptyCond *sync.Cond
15 16 config *Configuration
16 17 }
@@ -19,55 +20,55 @@ func newConnPool(config *Configuration) *connPool {
19 20 cp := &connPool{
20 21 available: config.PoolSize,
21 22 capacity: config.PoolSize,
22   - pool: make([]*connection, config.PoolSize),
  23 + all: map[*connection]struct{}{},
23 24 config: config,
24 25 }
25   - cp.fullCond = sync.NewCond(&cp.lock)
26 26 cp.emptyCond = sync.NewCond(&cp.lock)
27 27
28 28 return cp
29 29 }
30 30 func (cp *connPool) push(conn *connection) {
31   - if conn != nil && conn.closed {
32   - // Connection was closed likely due to an error.
33   - // Don't attempt to reuse closed connections.
34   - conn = nil
  31 + if conn == nil {
  32 + return
35 33 }
36 34
37 35 cp.lock.Lock()
38   - for cp.available == cp.capacity {
39   - cp.fullCond.Wait()
40   - }
  36 + defer cp.lock.Unlock()
41 37
42   - cp.pool[cp.available] = conn
  38 + if !conn.closed {
  39 + cp.free.PushBack(conn)
  40 + } else {
  41 + delete(cp.all, conn)
  42 + }
43 43 cp.available++
44 44
45 45 cp.emptyCond.Signal()
46   - cp.lock.Unlock()
47 46 }
48 47
49   -func (cp *connPool) pull() (*connection, *Error) {
50   - var err *Error
  48 +func (cp *connPool) pull() (conn *connection, err *Error) {
51 49
52 50 cp.lock.Lock()
  51 + defer cp.lock.Unlock()
  52 +
53 53 for cp.available == 0 {
54 54 cp.emptyCond.Wait()
55 55 }
56 56
57   - conn := cp.pool[cp.available-1]
58   - if conn == nil {
  57 + if cp.free.Len() > 0 {
  58 + conn, _ = cp.free.Remove(cp.free.Back()).(*connection)
  59 + } else {
59 60 // Lazy init of a connection
60 61 conn, err = newConnection(cp.config)
61 62
62 63 if err != nil {
63   - cp.lock.Unlock()
64 64 return nil, err
65 65 }
  66 + // make sure to keep track of it, so that we can close
  67 + // it later.
  68 + cp.all[conn] = struct{}{}
66 69 }
67 70
68 71 cp.available--
69   - cp.fullCond.Signal()
70   - cp.lock.Unlock()
71 72
72 73 return conn, nil
73 74 }
@@ -76,10 +77,9 @@ func (cp *connPool) close() {
76 77 cp.lock.Lock()
77 78 defer cp.lock.Unlock()
78 79
79   - for i, conn := range cp.pool {
80   - if conn != nil {
81   - conn.close()
82   - cp.pool[i] = nil
83   - }
  80 + for conn, _ := range cp.all {
  81 + conn.close()
84 82 }
  83 +
  84 + cp.all = nil
85 85 }

0 comments on commit dac6ce1

Please sign in to comment.
Something went wrong with that request. Please try again.