1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package event provides an infinitely buffered double-ended queue of events.
6package event // import "golang.org/x/exp/shiny/driver/internal/event"
7
8import (
9	"sync"
10)
11
12// Deque is an infinitely buffered double-ended queue of events. The zero value
13// is usable, but a Deque value must not be copied.
14type Deque struct {
15	mu    sync.Mutex
16	cond  sync.Cond     // cond.L is lazily initialized to &Deque.mu.
17	back  []interface{} // FIFO.
18	front []interface{} // LIFO.
19}
20
21func (q *Deque) lockAndInit() {
22	q.mu.Lock()
23	if q.cond.L == nil {
24		q.cond.L = &q.mu
25	}
26}
27
28// NextEvent implements the screen.EventDeque interface.
29func (q *Deque) NextEvent() interface{} {
30	q.lockAndInit()
31	defer q.mu.Unlock()
32
33	for {
34		if n := len(q.front); n > 0 {
35			e := q.front[n-1]
36			q.front[n-1] = nil
37			q.front = q.front[:n-1]
38			return e
39		}
40
41		if n := len(q.back); n > 0 {
42			e := q.back[0]
43			q.back[0] = nil
44			q.back = q.back[1:]
45			return e
46		}
47
48		q.cond.Wait()
49	}
50}
51
52// Send implements the screen.EventDeque interface.
53func (q *Deque) Send(event interface{}) {
54	q.lockAndInit()
55	defer q.mu.Unlock()
56
57	q.back = append(q.back, event)
58	q.cond.Signal()
59}
60
61// SendFirst implements the screen.EventDeque interface.
62func (q *Deque) SendFirst(event interface{}) {
63	q.lockAndInit()
64	defer q.mu.Unlock()
65
66	q.front = append(q.front, event)
67	q.cond.Signal()
68}
69