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