Merge "Fix extension support checks in negative api tests" into nougat-cts-dev am...
[platform/upstream/VK-GL-CTS.git] / framework / common / tcuThreadUtil.hpp
1 #ifndef _TCUTHREADUTIL_HPP
2 #define _TCUTHREADUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements Quality Program Tester Core
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 test utilities
24  *//*--------------------------------------------------------------------*/
25
26 #include "tcuDefs.hpp"
27 #include "deSharedPtr.hpp"
28 #include "deMutex.hpp"
29 #include "deSemaphore.hpp"
30 #include "deThread.hpp"
31 #include "deRandom.hpp"
32
33 #include <vector>
34 #include <sstream>
35
36 namespace tcu
37 {
38 namespace ThreadUtil
39 {
40 // Event object for synchronizing threads
41 class Event
42 {
43 public:
44         enum Result
45         {
46                 RESULT_NOT_READY = 0,
47                 RESULT_OK,
48                 RESULT_FAILED
49         };
50
51                                         Event           (void);
52                                         ~Event          (void);
53         void                    setResult       (Result result);
54         Result                  waitReady       (void);
55         Result                  getResult       (void) const { return m_result; }
56
57 private:
58         volatile Result m_result;
59         volatile int    m_waiterCount;
60         de::Semaphore   m_waiters;
61         de::Mutex               m_lock;
62
63         // Disabled
64                                         Event           (const Event&);
65         Event&                  operator=       (const Event&);
66 };
67
68 // Base class for objects which modifications should be tracked between threads
69 class Object
70 {
71 public:
72                                                                                 Object          (const char* type, de::SharedPtr<Event> createEvent);
73         virtual                                                         ~Object         (void);
74         const char*                                                     getType         (void) const { return m_type; }
75
76         // Used by class Operation only
77         void                                                            read            (de::SharedPtr<Event> event, std::vector<de::SharedPtr<Event> >& deps);
78         void                                                            modify          (de::SharedPtr<Event> event, std::vector<de::SharedPtr<Event> >& deps);
79
80 private:
81         const char*                                                     m_type;
82         de::SharedPtr<Event>                            m_modify;
83         std::vector<de::SharedPtr<Event> >      m_reads;
84
85         // Disabled
86                                                                                 Object          (const Object&);
87         Object&                                                         operator=       (const Object&);
88 };
89
90 class Thread;
91
92 class MessageBuilder
93 {
94 public:
95                                                 MessageBuilder          (Thread& thread) : m_thread(thread) {}
96                                                 MessageBuilder          (const MessageBuilder& other) : m_thread(other.m_thread), m_stream(other.m_stream.str()) {}
97         template<class T>
98         MessageBuilder&         operator<<                      (const T& t) { m_stream << t; return *this; }
99
100         class EndToken
101         {
102         public:
103                                                 EndToken                        (void) {}
104         };
105
106         void                            operator<<                      (const EndToken&);
107
108 private:
109         Thread&                         m_thread;
110         std::stringstream       m_stream;
111 };
112
113 class Message
114 {
115 public:
116                                                 Message         (deUint64 time, const char* message) : m_time(time), m_message(message) {}
117
118         deUint64                        getTime         (void) const { return m_time; }
119         const std::string&      getMessage      (void) const { return m_message; }
120
121         static const MessageBuilder::EndToken End;
122
123 private:
124         deUint64                        m_time;
125         std::string                     m_message;
126 };
127
128 // Base class for operations executed by threads
129 class Operation
130 {
131 public:
132                                                                                         Operation               (const char* name);
133         virtual                                                                 ~Operation              (void);
134
135         const char*                                                             getName                 (void) const { return m_name; }
136         de::SharedPtr<Event>                                    getEvent                (void) { return m_event; }
137
138         void                                                                    readObject              (de::SharedPtr<Object> object) { object->read(m_event, m_deps); }
139         void                                                                    modifyObject    (de::SharedPtr<Object> object) { object->modify(m_event, m_deps); }
140
141         virtual void                                                    exec                    (Thread& thread) = 0;   //!< Overwritten by inherited class to perform actual operation
142         virtual void                                                    execute                 (Thread& thread);               //!< May Be overwritten by inherited class to change how syncronization is done
143
144 protected:
145         const char*                                                             m_name;
146         std::vector<de::SharedPtr<Event> >              m_deps;
147         de::SharedPtr<Event>                                    m_event;
148
149                                                                                         Operation               (const Operation&);
150         Operation&                                                              operator=               (const Operation&);
151 };
152
153 class Thread : public de::Thread
154 {
155 public:
156         enum ThreadStatus
157         {
158                 THREADSTATUS_NOT_STARTED = 0,
159                 THREADSTATUS_INIT_FAILED,
160                 THREADSTATUS_RUNNING,
161                 THREADSTATUS_READY,
162                 THREADSTATUS_FAILED,
163                 THREADSTATUS_NOT_SUPPORTED
164         };
165                                                         Thread                          (deUint32 seed);
166                                                         ~Thread                         (void);
167
168         virtual void                    init                            (void) {}       //!< Called first before any Operation
169
170         // \todo [mika] Should the result of execution be passed to deinit?
171         virtual void                    deinit                          (void) {}       //!< Called after after operation
172
173         void                                    addOperation            (Operation* operation);
174
175         void                                    exec                            (void);
176
177         deUint8*                                getDummyData            (size_t size);  //!< Return data pointer that contains at least size bytes. Valid until next call
178
179         ThreadStatus                    getStatus                       (void) const { return m_status; }
180
181         MessageBuilder                  newMessage                      (void) { return MessageBuilder(*this); }
182         de::Random&                             getRandom                       (void) { return m_random; }
183
184         // Used to by test case to read log messages
185         int                                             getMessageCount         (void) const;
186         Message                                 getMessage                      (int index) const;
187
188         // Used by message builder
189         void                                    pushMessage                     (const std::string& str);
190
191 private:
192         virtual void                    run                                     (void);
193
194         std::vector<Operation*> m_operations;
195         de::Random                              m_random;
196
197         mutable de::Mutex               m_messageLock;
198         std::vector<Message>    m_messages;
199         ThreadStatus                    m_status;
200         std::vector<deUint8>    m_dummyData;
201
202         // Disabled
203                                                         Thread                          (const Thread&);
204         Thread                                  operator=                       (const Thread&);
205 };
206
207 class DataBlock : public Object
208 {
209 public:
210                                         DataBlock       (de::SharedPtr<Event> event);
211
212         void                    setData         (size_t size, const void* data);
213         const deUint8*  getData         (void) const { return &(m_data[0]); }
214         size_t                  getSize         (void) const { return m_data.size(); }
215
216 private:
217         std::vector<deUint8> m_data;
218 };
219
220
221 class CompareData : public Operation
222 {
223 public:
224                         CompareData     (de::SharedPtr<DataBlock> a, de::SharedPtr<DataBlock> b);
225         void    exec            (Thread& thread);
226
227 private:
228         de::SharedPtr<DataBlock>        m_a;
229         de::SharedPtr<DataBlock>        m_b;
230 };
231
232 } // ThreadUtil
233 } // tcu
234
235 #endif // _TCUTHREADUTIL_HPP