TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / graphics / buffer_queue.cpp
1 // Copyright (C) 2016 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "anbox/graphics/buffer_queue.h"
16
17 namespace anbox {
18 namespace graphics {
19 BufferQueue::BufferQueue(size_t capacity)
20     : capacity_(capacity), buffers_(new Buffer[capacity]) {}
21
22 int BufferQueue::try_push_locked(Buffer &&buffer) {
23   if (closed_)
24     return -EIO;
25
26   if (count_ >= capacity_)
27     return -EAGAIN;
28
29   size_t pos = pos_ + count_;
30   if (pos >= capacity_)
31     pos -= capacity_;
32
33   buffers_[pos] = std::move(buffer);
34   if (count_++ == 0)
35     can_pop_.notify_one();
36
37   return 0;
38 }
39
40 int BufferQueue::push_locked(
41     Buffer &&buffer, std::unique_lock<std::mutex> &lock) {
42   while (count_ == capacity_) {
43     if (closed_)
44       return -EIO;
45     can_push_.wait(lock);
46   }
47   return try_push_locked(std::move(buffer));
48 }
49
50 int BufferQueue::wait_until_not_empty_locked(std::unique_lock<std::mutex> &lock) {
51   while (count_ == 0) {
52     if (closed_)
53       // Closed queue is empty.
54       return -EIO;
55     can_pop_.wait(lock);
56   }
57
58   return 0;
59 }
60
61 int BufferQueue::try_pop_locked(Buffer *buffer) {
62   if (count_ == 0)
63     return closed_ ? -EIO : -EAGAIN;
64
65   *buffer = std::move(buffers_[pos_]);
66   size_t pos = pos_ + 1;
67   if (pos >= capacity_)
68     pos -= capacity_;
69
70   pos_ = pos;
71   if (count_-- == capacity_)
72     can_push_.notify_one();
73
74   return 0;
75 }
76
77 int BufferQueue::pop_locked(
78     Buffer *buffer, std::unique_lock<std::mutex> &lock) {
79   while (count_ == 0) {
80     if (closed_)
81       // Closed queue is empty.
82       return -EIO;
83     can_pop_.wait(lock);
84   }
85   return try_pop_locked(buffer);
86 }
87
88 // Close the queue, it is no longer possible to push new items
89 // to it (i.e. push() will always return Result::Error), or to
90 // read from an empty queue (i.e. pop() will always return
91 // Result::Error once the queue becomes empty).
92 void BufferQueue::close_locked() {
93   closed_ = true;
94
95   // Wake any potential waiters.
96   if (count_ == capacity_) {
97     can_push_.notify_all();
98   }
99   if (count_ == 0) {
100     can_pop_.notify_all();
101   }
102 }
103 }  // namespace graphics
104 }  // namespace anbox