Rename various things for more inclusive language
[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*                                getUnusedData           (size_t size);  //!< Return data pointer that contains at least size bytes. Valid until next call
178
179         ThreadStatus                    getStatus                       (void) const { de::ScopedLock lock(m_statusLock); return m_status; }
180         void                            setStatus                       (ThreadStatus status) { de::ScopedLock lock(m_statusLock); m_status = status; }
181
182         MessageBuilder                  newMessage                      (void) { return MessageBuilder(*this); }
183         de::Random&                             getRandom                       (void) { return m_random; }
184
185         // Used to by test case to read log messages
186         int                                             getMessageCount         (void) const;
187         Message                                 getMessage                      (int index) const;
188
189         // Used by message builder
190         void                                    pushMessage                     (const std::string& str);
191
192 private:
193         virtual void                    run                                     (void);
194
195         std::vector<Operation*> m_operations;
196         de::Random                              m_random;
197
198         mutable de::Mutex               m_messageLock;
199         std::vector<Message>    m_messages;
200         mutable de::Mutex               m_statusLock;
201         ThreadStatus                    m_status;
202         std::vector<deUint8>    m_unusedData;
203
204         // Disabled
205                                                         Thread                          (const Thread&);
206         Thread                                  operator=                       (const Thread&);
207 };
208
209 class DataBlock : public Object
210 {
211 public:
212                                         DataBlock       (de::SharedPtr<Event> event);
213
214         void                    setData         (size_t size, const void* data);
215         const deUint8*  getData         (void) const { return &(m_data[0]); }
216         size_t                  getSize         (void) const { return m_data.size(); }
217
218 private:
219         std::vector<deUint8> m_data;
220 };
221
222
223 class CompareData : public Operation
224 {
225 public:
226                         CompareData     (de::SharedPtr<DataBlock> a, de::SharedPtr<DataBlock> b);
227         void    exec            (Thread& thread);
228
229 private:
230         de::SharedPtr<DataBlock>        m_a;
231         de::SharedPtr<DataBlock>        m_b;
232 };
233
234 } // ThreadUtil
235 } // tcu
236
237 #endif // _TCUTHREADUTIL_HPP