Peekable Queue in Golang

1.8k views Asked by At

I am trying to design a mechanism to allow cooperation of many processes – goroutines. There are two classes of processes – providers and users. Providers put “bids” for their services into a queue and users take waiting bids and start working with providers. However, a user may not like a bid and then two things should happen:

  • This bid should return to the queue. It should be placed at the beginning of the queue
  • The user should be given the next bid in the queue

Ideally, I would like to avoid a central process that coordinates the communication between providers and users. Another way of thinking about this problem is to imagine a “peekable” queue or channel. A concept similar to the way AWS Kinesis works. A reader can get an access to “peek” into the head of the queue. As this reader is peeking, no other readers can see the item. It the reader likes the item, then it removes it from the queue. If not the reader releases the lock on the item and another reader can peek.

Any ideas how to best implement this behavior in Go using channels and goroutines?

1

There are 1 answers

0
chowey On

As @DaveC states in his comment, the simplest and fastest way to do this is to use a mutex.

You could use the "container/list" package, which implements a double-linked list for you. This can be pushed/popped from both ends.

Here is a quick implementation that does what I think you are asking:

import (
    "container/list"
    "sync"
)

type Queue struct {
    q list.List
    l sync.Mutex
}

func (q *Queue) Push(data interface{}) {
    q.l.Lock()
    q.q.PushBack(data)
    q.l.Unlock()
}

func (q *Queue) Pop() interface{} {
    q.l.Lock()
    data := q.q.Remove(q.q.Front())
    q.l.Unlock()
    return data
}

func (q *Queue) TakeAnother(data interface{}) interface{} {
    q.l.Lock()
    e := q.q.Front()
    // swap the data with whatever is in the front of the list
    e.Value, data = data, e.Value
    q.l.Unlock()
    return data
}

Nowhere do I use channels or goroutines, since I don't think they are the correct tool for this job.