github.com/decred/dcrlnd@v0.7.6/pool/read.go (about)

     1  package pool
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/decred/dcrlnd/buffer"
     7  )
     8  
     9  // Read is a worker pool specifically designed for sharing access to buffer.Read
    10  // objects amongst a set of worker goroutines. This enables an application to
    11  // limit the total number of buffer.Read objects allocated at any given time.
    12  type Read struct {
    13  	workerPool *Worker
    14  	bufferPool *ReadBuffer
    15  }
    16  
    17  // NewRead creates a new Read pool, using an underlying ReadBuffer pool to
    18  // recycle buffer.Read objects across the lifetime of the Read pool's workers.
    19  func NewRead(readBufferPool *ReadBuffer, numWorkers int,
    20  	workerTimeout time.Duration) *Read {
    21  
    22  	r := &Read{
    23  		bufferPool: readBufferPool,
    24  	}
    25  	r.workerPool = NewWorker(&WorkerConfig{
    26  		NewWorkerState: r.newWorkerState,
    27  		NumWorkers:     numWorkers,
    28  		WorkerTimeout:  workerTimeout,
    29  	})
    30  
    31  	return r
    32  }
    33  
    34  // Start safely spins up the Read pool.
    35  func (r *Read) Start() error {
    36  	return r.workerPool.Start()
    37  }
    38  
    39  // Stop safely shuts down the Read pool.
    40  func (r *Read) Stop() error {
    41  	return r.workerPool.Stop()
    42  }
    43  
    44  // Submit accepts a function closure that provides access to the fresh
    45  // buffer.Read object. The function's execution will be allocated to one of the
    46  // underlying Worker pool's goroutines.
    47  func (r *Read) Submit(inner func(*buffer.Read) error) error {
    48  	return r.workerPool.Submit(func(s WorkerState) error {
    49  		state := s.(*readWorkerState)
    50  		return inner(state.readBuf)
    51  	})
    52  }
    53  
    54  // readWorkerState is the per-goroutine state maintained by a Read pool's
    55  // goroutines.
    56  type readWorkerState struct {
    57  	// bufferPool is the pool to which the readBuf will be returned when the
    58  	// goroutine exits.
    59  	bufferPool *ReadBuffer
    60  
    61  	// readBuf is a buffer taken from the bufferPool on initialization,
    62  	// which will be cleaned and provided to any tasks that the goroutine
    63  	// processes before exiting.
    64  	readBuf *buffer.Read
    65  }
    66  
    67  // newWorkerState initializes a new readWorkerState, which will be called
    68  // whenever a new goroutine is allocated to begin processing read tasks.
    69  func (r *Read) newWorkerState() WorkerState {
    70  	return &readWorkerState{
    71  		bufferPool: r.bufferPool,
    72  		readBuf:    r.bufferPool.Take(),
    73  	}
    74  }
    75  
    76  // Cleanup returns the readBuf to the underlying buffer pool, and removes the
    77  // goroutine's reference to the readBuf.
    78  func (r *readWorkerState) Cleanup() {
    79  	r.bufferPool.Return(r.readBuf)
    80  	r.readBuf = nil
    81  }
    82  
    83  // Reset recycles the readBuf to make it ready for any subsequent tasks the
    84  // goroutine may process.
    85  func (r *readWorkerState) Reset() {
    86  	r.readBuf.Recycle()
    87  }