github.com/grailbio/base@v0.0.11/syncqueue/lifo.go (about)

     1  // Copyright 2018 GRAIL, Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache-2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  package syncqueue
     6  
     7  import (
     8  	"sync"
     9  )
    10  
    11  // LIFO implements a last-in, first-out producer-consumer queue. Thread safe.
    12  type LIFO struct {
    13  	mu     sync.Mutex
    14  	cond   *sync.Cond
    15  	queue  []interface{}
    16  	closed bool
    17  }
    18  
    19  // NewFIFO creates an empty FIFO queue.
    20  func NewLIFO() *LIFO {
    21  	q := &LIFO{}
    22  	q.cond = sync.NewCond(&q.mu)
    23  	return q
    24  }
    25  
    26  // Put adds the object in the queue.
    27  func (q *LIFO) Put(v interface{}) {
    28  	q.mu.Lock()
    29  	q.queue = append(q.queue, v)
    30  	q.cond.Signal()
    31  	q.mu.Unlock()
    32  }
    33  
    34  // Close informs the queue that no more objects will be added via Put().
    35  func (q *LIFO) Close() {
    36  	q.closed = true
    37  	q.cond.Broadcast()
    38  }
    39  
    40  // Get removes the newest object added to the queue.  It blocks the caller if
    41  // the queue is empty.
    42  func (q *LIFO) Get() (interface{}, bool) {
    43  	q.mu.Lock()
    44  	for !q.closed && len(q.queue) == 0 {
    45  		q.cond.Wait()
    46  	}
    47  	var v interface{}
    48  	var ok bool
    49  	if n := len(q.queue); n > 0 {
    50  		v = q.queue[n-1]
    51  		q.queue = q.queue[:n-1]
    52  		ok = true
    53  	}
    54  	q.mu.Unlock()
    55  	return v, ok
    56  }