Main Page   Class List   Class Members  

  • Main Page
  • User's Guide
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

sdk/toolkit/source/NvBlastTkEventQueue.h

Go to the documentation of this file.
00001 // This code contains NVIDIA Confidential Information and is disclosed to you
00002 // under a form of NVIDIA software license agreement provided separately to you.
00003 //
00004 // Notice
00005 // NVIDIA Corporation and its licensors retain all intellectual property and
00006 // proprietary rights in and to this software and related documentation and
00007 // any modifications thereto. Any use, reproduction, disclosure, or
00008 // distribution of this software and related documentation without an express
00009 // license agreement from NVIDIA Corporation is strictly prohibited.
00010 //
00011 // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
00012 // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
00013 // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
00014 // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
00015 //
00016 // Information and code furnished is believed to be accurate and reliable.
00017 // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
00018 // information or for any infringement of patents or other rights of third parties that may
00019 // result from its use. No license is granted by implication or otherwise under any patent
00020 // or patent rights of NVIDIA Corporation. Details are subject to change without notice.
00021 // This code supersedes and replaces all information previously supplied.
00022 // NVIDIA Corporation products are not authorized for use as critical
00023 // components in life support devices or systems without express written approval of
00024 // NVIDIA Corporation.
00025 //
00026 // Copyright (c) 2016-2020 NVIDIA Corporation. All rights reserved.
00027 
00028 
00029 #ifndef NVBLASTTKEVENTQUEUE_H
00030 #define NVBLASTTKEVENTQUEUE_H
00031 
00032 #include <algorithm>
00033 #include <vector>
00034 
00035 #include <mutex>
00036 #include <atomic>
00037 
00038 #include "NvBlastTkFrameworkImpl.h"
00039 #include "NvBlastAssert.h"
00040 
00041 
00042 namespace Nv {
00043 namespace Blast {
00044 
00061 class TkEventQueue
00062 {
00063 public:
00064     TkEventQueue() : m_currentEvent(0), m_poolCapacity(0), m_pool(nullptr), m_allowAllocs(true) {}
00065 
00070     operator const Array<TkEvent>::type&() 
00071     {
00072         NVBLAST_ASSERT(m_allowAllocs);
00073         NVBLAST_ASSERT(m_currentEvent == m_events.size());
00074         return m_events; 
00075     }
00076 
00084     void protect(bool enable)
00085     {
00086         // During parallel use, m_events.size() and m_currentEvent are allowed to diverge.
00087         // This is fine because resizeUninitialized does not alter the stored data.
00088         NVBLAST_ASSERT(m_currentEvent <= m_events.capacity());
00089         m_events.resizeUninitialized(m_currentEvent);
00090         m_allowAllocs = !enable;
00091     }
00092 
00097     void reset()
00098     {
00099         m_events.clear();
00100         m_currentEvent = 0;
00101         for (void* mem : m_memory)
00102         {
00103             NVBLAST_FREE(mem);
00104         }
00105         m_memory.clear();
00106         m_currentData = 0;
00107         m_allowAllocs = true;
00108         m_poolCapacity = 0;
00109         m_pool = nullptr;
00110     }
00111 
00115     template<class T>
00116     void addEvent(T* payload)
00117     {
00118         uint32_t index = m_currentEvent.fetch_add(1);
00119 
00120         // Should not allocate in protected state.
00121         NVBLAST_ASSERT(m_allowAllocs || m_currentEvent <= m_events.capacity());
00122 
00123         m_events.resizeUninitialized(m_currentEvent);
00124 
00125         // During parallel use, m_events.size() and m_currentEvent are allowed to diverge.
00126         // Consistency is restored in protect().
00127         NVBLAST_ASSERT(!m_allowAllocs || m_currentEvent == m_events.size());
00128 
00129         TkEvent& evt = m_events[index];
00130         evt.type = TkEvent::Type(T::EVENT_TYPE);
00131         evt.payload = payload;
00132     }
00133 
00137     template<typename T>
00138     T* allocData()
00139     {
00140         uint32_t index = m_currentData.fetch_add(sizeof(T));
00141         if (m_currentData <= m_poolCapacity)
00142         {
00143             return reinterpret_cast<T*>(&m_pool[index]);
00144         }
00145         else
00146         {
00147             // Could do larger block allocation here.
00148             reserveData(sizeof(T));
00149             // Account for the requested size.
00150             m_currentData = sizeof(T);
00151             return reinterpret_cast<T*>(&m_pool[0]);
00152         }
00153     }
00154 
00160     void reserveData(size_t size)
00161     {
00162         NVBLAST_ASSERT(m_allowAllocs);
00163         m_pool = reinterpret_cast<uint8_t*>(allocDataBySize(size));
00164         m_poolCapacity = size;
00165         m_currentData = 0;
00166     }
00167 
00171     void reserveEvents(uint32_t n)
00172     {
00173         NVBLAST_ASSERT(m_allowAllocs);
00174         m_events.reserve(m_events.size() + n);
00175     }
00176 
00180     void addListener(TkEventListener& l)
00181     {
00182         m_listeners.pushBack(&l);
00183     }
00184 
00188     void removeListener(TkEventListener& l)
00189     {
00190         m_listeners.findAndReplaceWithLast(&l);
00191     }
00192 
00197     void dispatch()
00198     {
00199         dispatch(*this);
00200         reset();
00201     }
00202 
00206     void dispatch(const Array<TkEvent>::type& events) const
00207     {
00208         if (events.size())
00209         {
00210             for (TkEventListener* l : m_listeners)
00211             {
00212                 BLAST_PROFILE_SCOPE_M("TkEventQueue::dispatch");
00213                 l->receive(events.begin(), events.size());
00214             }
00215         }
00216     }
00217 
00218 private:
00222     void* allocDataBySize(size_t size)
00223     {
00224         void* memory = nullptr;
00225         if (size > 0)
00226         {
00227             memory = NVBLAST_ALLOC_NAMED(size, "TkEventQueue Data");
00228             m_memory.pushBack(memory);
00229         }
00230         return memory;
00231     }
00232 
00233 
00234     Array<TkEvent>::type                    m_events;       
00235     Array<void*>::type                      m_memory;       
00236     std::atomic<uint32_t>                   m_currentEvent; 
00237     std::atomic<uint32_t>                   m_currentData;  
00238     size_t                                  m_poolCapacity; 
00239     uint8_t*                                m_pool;         
00240     bool                                    m_allowAllocs;  
00241     InlineArray<TkEventListener*,4>::type   m_listeners;    
00242 };
00243 
00244 }   // namespace Blast
00245 }   // namespace Nv
00246 
00247 
00248 #endif  // ifndef NVBLASTTKEVENTQUEUE_H
Copyright © 2015-2017 NVIDIA Corporation, 2701 San Tomas Expressway, Santa Clara, CA 95050 U.S.A. All rights reserved. www.nvidia.com