NvBlastTkEventQueue.h
Go to the documentation of this file.
1 // This code contains NVIDIA Confidential Information and is disclosed to you
2 // under a form of NVIDIA software license agreement provided separately to you.
3 //
4 // Notice
5 // NVIDIA Corporation and its licensors retain all intellectual property and
6 // proprietary rights in and to this software and related documentation and
7 // any modifications thereto. Any use, reproduction, disclosure, or
8 // distribution of this software and related documentation without an express
9 // license agreement from NVIDIA Corporation is strictly prohibited.
10 //
11 // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
12 // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
13 // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
14 // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
15 //
16 // Information and code furnished is believed to be accurate and reliable.
17 // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
18 // information or for any infringement of patents or other rights of third parties that may
19 // result from its use. No license is granted by implication or otherwise under any patent
20 // or patent rights of NVIDIA Corporation. Details are subject to change without notice.
21 // This code supersedes and replaces all information previously supplied.
22 // NVIDIA Corporation products are not authorized for use as critical
23 // components in life support devices or systems without express written approval of
24 // NVIDIA Corporation.
25 //
26 // Copyright (c) 2016-2020 NVIDIA Corporation. All rights reserved.
27 
28 
29 #ifndef NVBLASTTKEVENTQUEUE_H
30 #define NVBLASTTKEVENTQUEUE_H
31 
32 #include <algorithm>
33 #include <vector>
34 
35 #include <mutex>
36 #include <atomic>
37 
38 #include "NvBlastTkFrameworkImpl.h"
39 #include "NvBlastAssert.h"
40 
41 
42 namespace Nv {
43 namespace Blast {
44 
62 {
63 public:
64  TkEventQueue() : m_currentEvent(0), m_poolCapacity(0), m_pool(nullptr), m_allowAllocs(true) {}
65 
70  operator const Array<TkEvent>::type&()
71  {
72  NVBLAST_ASSERT(m_allowAllocs);
73  NVBLAST_ASSERT(m_currentEvent == m_events.size());
74  return m_events;
75  }
76 
84  void protect(bool enable)
85  {
86  // During parallel use, m_events.size() and m_currentEvent are allowed to diverge.
87  // This is fine because resizeUninitialized does not alter the stored data.
88  NVBLAST_ASSERT(m_currentEvent <= m_events.capacity());
89  m_events.resizeUninitialized(m_currentEvent);
90  m_allowAllocs = !enable;
91  }
92 
97  void reset()
98  {
99  m_events.clear();
100  m_currentEvent = 0;
101  for (void* mem : m_memory)
102  {
103  NVBLAST_FREE(mem);
104  }
105  m_memory.clear();
106  m_currentData = 0;
107  m_allowAllocs = true;
108  m_poolCapacity = 0;
109  m_pool = nullptr;
110  }
111 
115  template<class T>
116  void addEvent(T* payload)
117  {
118  uint32_t index = m_currentEvent.fetch_add(1);
119 
120  // Should not allocate in protected state.
121  NVBLAST_ASSERT(m_allowAllocs || m_currentEvent <= m_events.capacity());
122 
123  m_events.resizeUninitialized(m_currentEvent);
124 
125  // During parallel use, m_events.size() and m_currentEvent are allowed to diverge.
126  // Consistency is restored in protect().
127  NVBLAST_ASSERT(!m_allowAllocs || m_currentEvent == m_events.size());
128 
129  TkEvent& evt = m_events[index];
130  evt.type = TkEvent::Type(T::EVENT_TYPE);
131  evt.payload = payload;
132  }
133 
137  template<typename T>
139  {
140  uint32_t index = m_currentData.fetch_add(sizeof(T));
141  if (m_currentData <= m_poolCapacity)
142  {
143  return reinterpret_cast<T*>(&m_pool[index]);
144  }
145  else
146  {
147  // Could do larger block allocation here.
148  reserveData(sizeof(T));
149  // Account for the requested size.
150  m_currentData = sizeof(T);
151  return reinterpret_cast<T*>(&m_pool[0]);
152  }
153  }
154 
160  void reserveData(size_t size)
161  {
162  NVBLAST_ASSERT(m_allowAllocs);
163  m_pool = reinterpret_cast<uint8_t*>(allocDataBySize(size));
164  m_poolCapacity = size;
165  m_currentData = 0;
166  }
167 
171  void reserveEvents(uint32_t n)
172  {
173  NVBLAST_ASSERT(m_allowAllocs);
174  m_events.reserve(m_events.size() + n);
175  }
176 
181  {
182  m_listeners.pushBack(&l);
183  }
184 
189  {
190  m_listeners.findAndReplaceWithLast(&l);
191  }
192 
197  void dispatch()
198  {
199  dispatch(*this);
200  reset();
201  }
202 
206  void dispatch(const Array<TkEvent>::type& events) const
207  {
208  if (events.size())
209  {
210  for (TkEventListener* l : m_listeners)
211  {
212  BLAST_PROFILE_SCOPE_M("TkEventQueue::dispatch");
213  l->receive(events.begin(), events.size());
214  }
215  }
216  }
217 
218 private:
222  void* allocDataBySize(size_t size)
223  {
224  void* memory = nullptr;
225  if (size > 0)
226  {
227  memory = NVBLAST_ALLOC_NAMED(size, "TkEventQueue Data");
228  m_memory.pushBack(memory);
229  }
230  return memory;
231  }
232 
233 
234  Array<TkEvent>::type m_events;
235  Array<void*>::type m_memory;
236  std::atomic<uint32_t> m_currentEvent;
237  std::atomic<uint32_t> m_currentData;
238  size_t m_poolCapacity;
239  uint8_t* m_pool;
240  bool m_allowAllocs;
242 };
243 
244 } // namespace Blast
245 } // namespace Nv
246 
247 
248 #endif // ifndef NVBLASTTKEVENTQUEUE_H
void addListener(TkEventListener &l)
Definition: NvBlastTkEventQueue.h:180
physx::shdfnd::InlineArray< T, N, Allocator > type
Definition: NvBlastArray.h:60
void reserveData(size_t size)
Definition: NvBlastTkEventQueue.h:160
Definition: NvBlastTkEvent.h:65
physx::shdfnd::Array< T, Allocator > type
Definition: NvBlastArray.h:48
void dispatch(const Array< TkEvent >::type &events) const
Definition: NvBlastTkEventQueue.h:206
#define BLAST_PROFILE_SCOPE_M(name)
Definition: NvBlastProfilerInternal.h:86
#define NVBLAST_ASSERT(exp)
Definition: NvBlastAssert.h:37
Type
Definition: NvBlastTkEvent.h:68
void protect(bool enable)
Definition: NvBlastTkEventQueue.h:84
Definition: NvBlastTkEvent.h:168
void addEvent(T *payload)
Definition: NvBlastTkEventQueue.h:116
Definition: NvBlastTkEventQueue.h:61
#define NVBLAST_FREE(_mem)
Definition: NvBlastGlobals.h:222
TkEventQueue()
Definition: NvBlastTkEventQueue.h:64
#define NVBLAST_ALLOC_NAMED(_size, _name)
Definition: NvBlastGlobals.h:221
T * allocData()
Definition: NvBlastTkEventQueue.h:138
Definition: NvBlastArray.h:37
void reserveEvents(uint32_t n)
Definition: NvBlastTkEventQueue.h:171
void dispatch()
Definition: NvBlastTkEventQueue.h:197
void removeListener(TkEventListener &l)
Definition: NvBlastTkEventQueue.h:188
void reset()
Definition: NvBlastTkEventQueue.h:97