Merge "Report tests using Draw*BaseVertex as NotSupported" am: f96636fdfa
[platform/upstream/VK-GL-CTS.git] / framework / delibs / decpp / deThreadSafeRingBuffer.hpp
1 #ifndef _DETHREADSAFERINGBUFFER_HPP
2 #define _DETHREADSAFERINGBUFFER_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements C++ Base Library
5  * -----------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Thread-safe ring buffer template.
24  *//*--------------------------------------------------------------------*/
25
26 #include "deDefs.hpp"
27 #include "deMutex.hpp"
28 #include "deSemaphore.hpp"
29
30 #include <vector>
31
32 namespace de
33 {
34
35 void ThreadSafeRingBuffer_selfTest (void);
36
37 /** Thread-safe ring buffer template. */
38 template <typename T>
39 class ThreadSafeRingBuffer
40 {
41 public:
42                                         ThreadSafeRingBuffer    (size_t size);
43                                         ~ThreadSafeRingBuffer   (void) {}
44
45         void                    pushFront                               (const T& elem);
46         bool                    tryPushFront                    (const T& elem);
47         T                               popBack                                 (void);
48         bool                    tryPopBack                              (T& dst);
49
50 protected:
51         void                    pushFrontInternal               (const T& elem);
52         T                               popBackInternal                 (void);
53
54         const size_t    m_size;
55         std::vector<T>  m_elements;
56
57         size_t                  m_front;
58         size_t                  m_back;
59
60         Mutex                   m_writeMutex;
61         Mutex                   m_readMutex;
62
63         Semaphore               m_fill;
64         Semaphore               m_empty;
65 };
66
67 // ThreadSafeRingBuffer implementation.
68
69 template <typename T>
70 ThreadSafeRingBuffer<T>::ThreadSafeRingBuffer (size_t size)
71         : m_size                (size+1)
72         , m_elements    (m_size)
73         , m_front               (0)
74         , m_back                (0)
75         , m_fill                (0)
76         , m_empty               ((int)size)
77 {
78         // Semaphores currently only support INT_MAX
79         DE_ASSERT(size > 0 && size < 0x7fffffff);
80 }
81
82 template <typename T>
83 inline void ThreadSafeRingBuffer<T>::pushFrontInternal (const T& elem)
84 {
85         m_elements[m_front] = elem;
86         m_front = (m_front + 1) % m_size;
87 }
88
89 template <typename T>
90 inline T ThreadSafeRingBuffer<T>::popBackInternal ()
91 {
92         const size_t ndx = m_back;
93         m_back = (m_back + 1) % m_size;
94         return m_elements[ndx];
95 }
96
97 template <typename T>
98 void ThreadSafeRingBuffer<T>::pushFront (const T& elem)
99 {
100         m_writeMutex.lock();
101         m_empty.decrement();
102         pushFrontInternal(elem);
103         m_fill.increment();
104         m_writeMutex.unlock();
105 }
106
107 template <typename T>
108 bool ThreadSafeRingBuffer<T>::tryPushFront (const T& elem)
109 {
110         if (!m_writeMutex.tryLock())
111                 return false;
112
113         const bool success = m_empty.tryDecrement();
114
115         if (success)
116         {
117                 pushFrontInternal(elem);
118                 m_fill.increment();
119         }
120
121         m_writeMutex.unlock();
122         return success;
123 }
124
125 template <typename T>
126 T ThreadSafeRingBuffer<T>::popBack ()
127 {
128         m_readMutex.lock();
129         m_fill.decrement();
130         T elem = popBackInternal();
131         m_empty.increment();
132         m_readMutex.unlock();
133         return elem;
134 }
135
136 template <typename T>
137 bool ThreadSafeRingBuffer<T>::tryPopBack (T& dst)
138 {
139         if (!m_readMutex.tryLock())
140                 return false;
141
142         bool success = m_fill.tryDecrement();
143
144         if (success)
145         {
146                 dst = popBackInternal();
147                 m_empty.increment();
148         }
149
150         m_readMutex.unlock();
151
152         return success;
153 }
154
155 } // de
156
157 #endif // _DETHREADSAFERINGBUFFER_HPP