From 1d5c424487c476831d9f98b1ca78b4fda6d18066 Mon Sep 17 00:00:00 2001 From: Johan Lorensson Date: Fri, 10 Mar 2023 09:23:08 +0100 Subject: [PATCH] Implement native container types used by shared EventPipe code. (#78852) * Implement native container types used by shared EventPipe code. Use eglib's list, slist, array, ptr_array, queue, hash table as a starting point creating a new set of native container types shared between native runtime components like EventPipe. EventPipe shim container API used a STL like API, new container types follows STL style container API and match STL type names: vector forward list list queue unordered map Native container types are still included in runtime build artifacts (through EventPipe cmake files), this can be changed/done differently depending on how each runtime would like to build/use the source files. In order to make that intent more clear, container and EventPipe cmake files have been renamed to not use CMakeList.txt, but .cmake. A number of new native tests for added container types have been added into EventPipe native test runner. --- src/coreclr/nativeaot/Runtime/EmptyContainers.h | 321 ----- src/coreclr/nativeaot/Runtime/EmptyContainers2.h | 548 --------- .../nativeaot/Runtime/eventpipe/CMakeLists.txt | 13 +- .../nativeaot/Runtime/eventpipe/ds-rt-aot.h | 44 - .../nativeaot/Runtime/eventpipe/ds-rt-types-aot.h | 29 - .../nativeaot/Runtime/eventpipe/ep-rt-aot.h | 1242 +------------------ .../nativeaot/Runtime/eventpipe/ep-rt-types-aot.h | 243 +--- src/coreclr/vm/eventing/eventpipe/CMakeLists.txt | 13 +- src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h | 44 - .../vm/eventing/eventpipe/ds-rt-types-coreclr.h | 29 - src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h | 1237 +------------------ .../vm/eventing/eventpipe/ep-rt-types-coreclr.h | 241 ---- src/mono/mono/component/CMakeLists.txt | 4 +- src/mono/mono/eglib/test/test.c | 9 +- src/mono/mono/eventpipe/ds-rt-mono.h | 44 - src/mono/mono/eventpipe/ds-rt-types-mono.h | 29 - src/mono/mono/eventpipe/ep-rt-config-mono.h | 1 - src/mono/mono/eventpipe/ep-rt-mono.c | 21 +- src/mono/mono/eventpipe/ep-rt-mono.h | 487 +------- src/mono/mono/eventpipe/ep-rt-types-mono.h | 186 --- .../eventpipe/{CMakeLists.txt => eventpipe.cmake} | 13 +- src/mono/mono/eventpipe/test/CMakeLists.txt | 8 +- src/mono/mono/eventpipe/test/dn-fwd-list-tests.c | 925 +++++++++++++++ src/mono/mono/eventpipe/test/dn-list-tests.c | 1106 +++++++++++++++++ src/mono/mono/eventpipe/test/dn-queue-tests.c | 337 ++++++ src/mono/mono/eventpipe/test/dn-umap-tests.c | 941 +++++++++++++++ src/mono/mono/eventpipe/test/dn-vector-ptr-tests.c | 965 +++++++++++++++ src/mono/mono/eventpipe/test/dn-vector-tests.c | 1245 ++++++++++++++++++++ .../mono/eventpipe/test/ep-buffer-manager-tests.c | 12 +- src/mono/mono/eventpipe/test/ep-tests.c | 10 +- src/mono/mono/eventpipe/test/ep-tests.h | 15 + src/native/containers/containers.cmake | 27 + src/native/containers/dn-allocator.c | 324 +++++ src/native/containers/dn-allocator.h | 107 ++ src/native/containers/dn-fwd-list.c | 406 +++++++ src/native/containers/dn-fwd-list.h | 324 +++++ src/native/containers/dn-list.c | 447 +++++++ src/native/containers/dn-list.h | 374 ++++++ src/native/containers/dn-queue.c | 76 ++ src/native/containers/dn-queue.h | 147 +++ src/native/containers/dn-sort-frag.inc | 201 ++++ src/native/containers/dn-umap-t.h | 76 ++ src/native/containers/dn-umap.c | 620 ++++++++++ src/native/containers/dn-umap.h | 277 +++++ src/native/containers/dn-utils.h | 79 ++ src/native/containers/dn-vector-priv.h | 94 ++ src/native/containers/dn-vector-ptr.h | 27 + src/native/containers/dn-vector-t.h | 288 +++++ src/native/containers/dn-vector-types.h | 53 + src/native/containers/dn-vector.c | 397 +++++++ src/native/containers/dn-vector.h | 331 ++++++ src/native/eventpipe/ds-eventpipe-protocol.c | 41 +- src/native/eventpipe/ds-eventpipe-protocol.h | 4 +- src/native/eventpipe/ds-ipc.c | 149 +-- src/native/eventpipe/ds-process-protocol.c | 45 +- src/native/eventpipe/ds-process-protocol.h | 2 +- src/native/eventpipe/ds-rt-types.h | 18 - src/native/eventpipe/ds-rt.h | 44 - src/native/eventpipe/ep-block.c | 26 +- src/native/eventpipe/ep-buffer-manager.c | 234 ++-- src/native/eventpipe/ep-buffer-manager.h | 4 +- src/native/eventpipe/ep-config.c | 84 +- src/native/eventpipe/ep-config.h | 2 +- src/native/eventpipe/ep-event-instance.c | 16 +- src/native/eventpipe/ep-event-instance.h | 4 +- src/native/eventpipe/ep-file.c | 100 +- src/native/eventpipe/ep-file.h | 10 +- src/native/eventpipe/ep-provider.c | 26 +- src/native/eventpipe/ep-provider.h | 2 +- src/native/eventpipe/ep-rt-types.h | 96 -- src/native/eventpipe/ep-rt.h | 273 +---- src/native/eventpipe/ep-session-provider.c | 42 +- src/native/eventpipe/ep-session-provider.h | 9 +- src/native/eventpipe/ep-session.c | 39 +- src/native/eventpipe/ep-session.h | 2 +- src/native/eventpipe/ep-stream.h | 1 + src/native/eventpipe/ep-thread.c | 34 +- src/native/eventpipe/ep-thread.h | 2 +- src/native/eventpipe/ep-types-forward.h | 2 +- src/native/eventpipe/ep-types.h | 10 +- src/native/eventpipe/ep.c | 90 +- .../eventpipe/{CMakeLists.txt => eventpipe.cmake} | 0 82 files changed, 10800 insertions(+), 5648 deletions(-) delete mode 100644 src/coreclr/nativeaot/Runtime/EmptyContainers.h delete mode 100644 src/coreclr/nativeaot/Runtime/EmptyContainers2.h rename src/mono/mono/eventpipe/{CMakeLists.txt => eventpipe.cmake} (90%) create mode 100644 src/mono/mono/eventpipe/test/dn-fwd-list-tests.c create mode 100644 src/mono/mono/eventpipe/test/dn-list-tests.c create mode 100644 src/mono/mono/eventpipe/test/dn-queue-tests.c create mode 100644 src/mono/mono/eventpipe/test/dn-umap-tests.c create mode 100644 src/mono/mono/eventpipe/test/dn-vector-ptr-tests.c create mode 100644 src/mono/mono/eventpipe/test/dn-vector-tests.c create mode 100644 src/native/containers/containers.cmake create mode 100644 src/native/containers/dn-allocator.c create mode 100644 src/native/containers/dn-allocator.h create mode 100644 src/native/containers/dn-fwd-list.c create mode 100644 src/native/containers/dn-fwd-list.h create mode 100644 src/native/containers/dn-list.c create mode 100644 src/native/containers/dn-list.h create mode 100644 src/native/containers/dn-queue.c create mode 100644 src/native/containers/dn-queue.h create mode 100644 src/native/containers/dn-sort-frag.inc create mode 100644 src/native/containers/dn-umap-t.h create mode 100644 src/native/containers/dn-umap.c create mode 100644 src/native/containers/dn-umap.h create mode 100644 src/native/containers/dn-utils.h create mode 100644 src/native/containers/dn-vector-priv.h create mode 100644 src/native/containers/dn-vector-ptr.h create mode 100644 src/native/containers/dn-vector-t.h create mode 100644 src/native/containers/dn-vector-types.h create mode 100644 src/native/containers/dn-vector.c create mode 100644 src/native/containers/dn-vector.h rename src/native/eventpipe/{CMakeLists.txt => eventpipe.cmake} (100%) diff --git a/src/coreclr/nativeaot/Runtime/EmptyContainers.h b/src/coreclr/nativeaot/Runtime/EmptyContainers.h deleted file mode 100644 index f96af50..0000000 --- a/src/coreclr/nativeaot/Runtime/EmptyContainers.h +++ /dev/null @@ -1,321 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#ifndef __EmptyContainers_h__ -#define __EmptyContainers_h__ - -// This header file will contains minimal containers that are needed for EventPipe library implementation -// shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase -// @TODO - this will likely be replaced by the common container classes to be added to the EventPipe library -// Hence initially, the bare boned implementation focus is on unblocking HW/Simple Trace bring up - -#include "EmptyContainers2.h" -#include "rhassert.h" - -struct SLink_EP -{ - SLink_EP* m_pNext; - - SLink_EP() - { - m_pNext = NULL; - } - - // find pLink within the list starting at pHead - // if found remove the link from the list and return the link - // otherwise return NULL - static SLink_EP* FindAndRemove(SLink_EP *pHead, SLink_EP* pLink, SLink_EP ** ppPrior) - { - - _ASSERTE(pHead != NULL); - _ASSERTE(pLink != NULL); - - SLink_EP* pFreeLink = NULL; - *ppPrior = NULL; - - while (pHead->m_pNext != NULL) - { - if (pHead->m_pNext == pLink) - { - pFreeLink = pLink; - pHead->m_pNext = pLink->m_pNext; - *ppPrior = pHead; - break; - } - pHead = pHead->m_pNext; - } - - return pFreeLink; - } -}; - - -// template -// Assumes fHead to be false -template -class SList_EP -{ -protected: - // used as sentinel - SLink_EP m_link; - SLink_EP* m_pHead; - SLink_EP* m_pTail; - - // get the list node within the object - static SLink_EP* GetLink (T* pLink) - { - return &(pLink->m_Link); - } - - static T* GetObject (SLink_EP* pLink) - { - if (pLink == NULL) - return NULL; - return reinterpret_cast(reinterpret_cast(pLink) - offsetof(T, m_Link)); - } - -public: - - SList_EP() - { - m_pHead = &m_link; - // NOTE :: fHead variable is template argument - // the following code is a compiled in, only if the fHead flag - // is set to false, - m_pTail = &m_link; - // TODO: Likely not needed now since SLink_EP has a ctor - m_link.m_pNext = NULL; - } - - bool IsEmpty() - { - return m_pHead->m_pNext == NULL; - } - - void InsertTail(T *pObj) - { - _ASSERTE(pObj != NULL); - SLink_EP *pLink = GetLink(pObj); - - m_pTail->m_pNext = pLink; - m_pTail = pLink; - } - - T* RemoveHead() - { - SLink_EP* pLink = m_pHead->m_pNext; - if (pLink != NULL) - { - m_pHead->m_pNext = pLink->m_pNext; - } - - if(m_pTail == pLink) - { - m_pTail = m_pHead; - } - - return GetObject(pLink); - } - - T* GetHead() - { - return GetObject(m_pHead->m_pNext); - } - - static T *GetNext(T *pObj) - { - _ASSERTE(pObj != NULL); - return GetObject(GetLink(pObj)->m_pNext); - } - - - T* FindAndRemove(T *pObj) - { - _ASSERTE(pObj != NULL); - - SLink_EP *prior; - SLink_EP *ret = SLink_EP::FindAndRemove(m_pHead, GetLink(pObj), &prior); - - if (ret == m_pTail) - m_pTail = prior; - - return GetObject(ret); - } - - void InsertHead(T *pObj) - { - //PalDebugBreak(); - } - - - class Iterator - { - friend class SList_EP; - //T* _t; - - public: - Iterator & operator++() - { - _ASSERTE(m_cur != NULL); - m_cur = SList_EP::GetNext(m_cur); - return *this; - } - - Iterator operator++(int) - { - Iterator it(m_cur); - ++(*this); - return it; - } - - bool operator==(Iterator const & other) const - { - return m_cur == other.m_cur || - (m_cur != NULL && other.m_cur != NULL && *m_cur == *other.m_cur); - } - - T & operator*() - { - _ASSERTE(m_cur != NULL); - return *m_cur; - } - - T * operator->() const - { - //PalDebugBreak(); - return m_cur; - } - - private: - // Iterator(SList * pList) - // : m_cur(pList->GetHead()) - // { } - - Iterator(T* pObj) - : m_cur(pObj) - { } - - Iterator() - : m_cur(NULL) - { } - - T* m_cur; - - }; - - Iterator begin() - { - return Iterator(GetHead()); - } - - Iterator end() - { - return Iterator(); - } - -}; - -template -struct SListElem_EP -{ - SLink_EP m_Link; - ElemT m_Value; - - operator ElemT const &() const - { - return m_Value; - } - - operator ElemT &() - { - return m_Value; - } - - ElemT const & operator*() const - { - //PalDebugBreak(); - return m_Value; - } - - ElemT & operator*() - { - //PalDebugBreak(); - return m_Value; - } - - SListElem_EP() - : m_Link() - , m_Value() - { - } - - SListElem_EP(ElemT val) - : m_Link() - , m_Value(val) - { - } - - ElemT & GetValue() - { - return m_Value; - } - -}; - -// Bare boned implementation to unblock HW -template -class CQuickArrayList_EP -{ -private: - size_t m_curSize; - T *m_array; - size_t maxSize; -public: - CQuickArrayList_EP() - : m_curSize(0), maxSize(100) - { - m_array = new T[maxSize]; - } - - - T* AllocNoThrow(size_t iItems) - { - return new T[iItems]; - } - - bool PushNoThrow(const T & value) - { - // if(m_curSize >= maxSize) - // PalDebugBreak(); - m_array[m_curSize++] = value; - return true; - } - - size_t Size() const - { - return m_curSize; - } - - T Pop() - { - T t = m_array[m_curSize]; - m_curSize--; - return t; - } - - void Shrink() - { - } - - T& operator[] (size_t ix) - { - return m_array[ix]; - } - - T* Ptr() - { - return m_array; - } -}; - -#endif // __EmptyContainers_h__ diff --git a/src/coreclr/nativeaot/Runtime/EmptyContainers2.h b/src/coreclr/nativeaot/Runtime/EmptyContainers2.h deleted file mode 100644 index 44036c2..0000000 --- a/src/coreclr/nativeaot/Runtime/EmptyContainers2.h +++ /dev/null @@ -1,548 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#ifndef __EmptyContainers2_h__ -#define __EmptyContainers2_h__ - -// This header file will contains minimal containers that are needed for EventPipe library implementation -// shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase -// @TODO - this will likely be replaced by the common container classes to be added to the EventPipe library -// Hence initially, the bare boned implementation focus is on unblocking HW/Simple Trace bring up - -// TODO: Should shash.h FailureType be used instead? -enum FailureType_EP { ftAllocation_EP, ftOverflow_EP }; - -template < typename ELEMENT, typename COUNT_T = uint32_t > -class DefaultSHashTraits_EP -{ -public: - typedef COUNT_T count_t; - typedef ELEMENT element_t; - typedef element_t* PTR_element_t; - - static const count_t s_growth_factor_numerator = 3; - static const count_t s_growth_factor_denominator = 2; - - static const count_t s_density_factor_numerator = 3; - static const count_t s_density_factor_denominator = 4; - - static const count_t s_minimum_allocation = 7; - - static const bool s_NoThrow = true; - - static const ELEMENT Null() { return (const ELEMENT) 0; } - static const ELEMENT Deleted() { return (const ELEMENT) -1; } - static bool IsNull(const ELEMENT &e) { return e == (const ELEMENT) 0; } - static bool IsDeleted(const ELEMENT &e) - { - //PalDebugBreak(); - return false; - //return e == (const ELEMENT) -1; - } - - static void OnFailure(FailureType_EP /*ft*/) { } - -}; - -template -class SHash_EP : public TRAITS -{ - public: - class Index; - friend class Index; - class Iterator; - - typedef typename TRAITS::element_t element_t; - typedef typename TRAITS::PTR_element_t PTR_element_t; - typedef typename TRAITS::key_t key_t; - typedef typename TRAITS::count_t count_t; - - SHash_EP():m_table(nullptr), - m_tableSize(0), - m_tableCount(0), - m_tableOccupied(0), - m_tableMax(0) - { - } - - ~SHash_EP() - { - delete [] m_table; - } - - const element_t * Lookup(element_t* table, count_t tableSize, key_t key) const - { - if (tableSize == 0) - return NULL; - - count_t hash = TRAITS::Hash(key); - count_t index = hash % tableSize; - count_t increment = 0; // delay computation - - while (true) - { - element_t& current = table[index]; - - if (TRAITS::IsNull(current)) - return NULL; - - if (!TRAITS::IsDeleted(current) - && TRAITS::Equals(key, TRAITS::GetKey(current))) - { - return ¤t; - } - - if (increment == 0) - increment = (hash % (tableSize-1)) + 1; - - index += increment; - if (index >= tableSize) - index -= tableSize; - } - - } - - const element_t* LookupPtr(key_t key) const - { - return Lookup(m_table, m_tableSize, key); - } - - bool Add(const element_t &element) - { - if (!CheckGrowth()) - return false; - - if (Add(m_table, m_tableSize, element)) - m_tableOccupied++; - m_tableCount++; - - return true; - } - - bool CheckGrowth() - { - if (m_tableOccupied == m_tableMax) - { - return Grow(); - } - - return true; - } - - bool Reallocate(count_t newTableSize) - { - // ASSERT(newTableSize >= - // (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator)); - - // Allocation size must be a prime number. This is necessary so that hashes uniformly - // distribute to all indices, and so that chaining will visit all indices in the hash table. - newTableSize = NextPrime(newTableSize); - if (newTableSize == 0) - { - TRAITS::OnFailure(ftOverflow_EP); - return false; - } - - element_t *newTable = new (nothrow) element_t [newTableSize]; - if (newTable == NULL) - { - TRAITS::OnFailure(ftAllocation_EP); - return false; - } - - element_t *p = newTable, *pEnd = newTable + newTableSize; - while (p < pEnd) - { - *p = TRAITS::Null(); - p++; - } - - for (Iterator i = Begin(), end = End(); i != end; i++) - { - const element_t & cur = (*i); - if (!TRAITS::IsNull(cur) && !TRAITS::IsDeleted(cur)) - Add(newTable, newTableSize, cur); - } - - // @todo: - // We might want to try to delay this cleanup to allow asynchronous readers - - delete [] m_table; - - m_table = PTR_element_t(newTable); - m_tableSize = newTableSize; - m_tableMax = (count_t) (newTableSize * TRAITS::s_density_factor_numerator / TRAITS::s_density_factor_denominator); - m_tableOccupied = m_tableCount; - - return true; - } - - // - // Enumerator, provides a template to produce an iterator on an existing class - // with a single iteration variable. - // - - template - class Enumerator - { - private: - const SUBTYPE *This() const - { - return (const SUBTYPE *) this; - } - - SUBTYPE *This() - { - return (SUBTYPE *)this; - } - - public: - - Enumerator() - { - } - - const element_t &operator*() const - { - return This()->Get(); - } - const element_t *operator->() const - { - return &(This()->Get()); - } - SUBTYPE &operator++() - { - This()->Next(); - return *This(); - } - SUBTYPE operator++(int) - { - SUBTYPE i = *This(); - This()->Next(); - return i; - } - bool operator==(const SUBTYPE &i) const - { - return This()->Equal(i); - } - bool operator!=(const SUBTYPE &i) const - { - return !This()->Equal(i); - } - }; - - // - // Index for whole table iterator. This is also the base for the keyed iterator. - // - - class Index - { - friend class SHash_EP; - friend class Iterator; - friend class Enumerator; - - // The methods implementation has to be here for portability - // Some compilers won't compile the separate implementation in shash.inl - protected: - - PTR_element_t m_table; - count_t m_tableSize; - count_t m_index; - - Index(const SHash_EP *hash, bool begin) - : m_table(hash->m_table), - m_tableSize(hash->m_tableSize), - m_index(begin ? 0 : m_tableSize) - { - } - - const element_t &Get() const - { - return m_table[m_index]; - } - - void First() - { - if (m_index < m_tableSize) - if (TRAITS::IsNull(m_table[m_index]) || TRAITS::IsDeleted(m_table[m_index])) - Next(); - } - - void Next() - { - if (m_index >= m_tableSize) - return; - - for (;;) - { - m_index++; - if (m_index >= m_tableSize) - break; - if (!TRAITS::IsNull(m_table[m_index]) && !TRAITS::IsDeleted(m_table[m_index])) - break; - } - } - - bool Equal(const Index &i) const - { - return i.m_index == m_index; - } - }; - - - class Iterator : public Index, public Enumerator - { - friend class SHash_EP; - TRAITS* _t; - - public: - Iterator(const SHash_EP *hash, bool begin) - : Index(hash, begin) - { - } - }; - - Iterator Begin() const - { - Iterator i(this, true); - i.First(); - return i; - } - Iterator End() const - { - return Iterator(this, false); - } - - bool AddNoThrow(const element_t &element) - { - //PalDebugBreak(); - return false; - } - bool AddOrReplaceNoThrow(const element_t &element) - { - //PalDebugBreak(); - return false; - } - - count_t GetCount() const - { - return m_tableCount; - } - - void Remove(key_t key) - { - //PalDebugBreak(); - } - - // Remove the specific element. - void Remove(Iterator& i) - { - //PalDebugBreak(); - } - void RemoveAll() - { - delete [] m_table; - - m_table = NULL; - m_tableSize = 0; - m_tableCount = 0; - m_tableOccupied = 0; - m_tableMax = 0; - } - - // Instance members - private: - PTR_element_t m_table; // pointer to table - count_t m_tableSize; // allocated size of table - count_t m_tableCount; // number of elements in table - count_t m_tableOccupied; // number, includes deleted slots - count_t m_tableMax; // maximum occupied count before reallocating - - bool Grow() - { - count_t newSize = (count_t) (m_tableCount - * TRAITS::s_growth_factor_numerator / TRAITS::s_growth_factor_denominator - * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator); - if (newSize < TRAITS::s_minimum_allocation) - newSize = TRAITS::s_minimum_allocation; - - // handle potential overflow - if (newSize < m_tableCount) - { - TRAITS::OnFailure(ftOverflow_EP); - return false; - } - - return Reallocate(newSize); - } - - static bool IsPrime(count_t number) - { - // This is a very low-tech check for primality, which doesn't scale very well. - // There are more efficient tests if this proves to be burdensome for larger - // tables. - - if ((number&1) == 0) - return false; - - count_t factor = 3; - while (factor * factor <= number) - { - if ((number % factor) == 0) - return false; - factor += 2; - } - - return true; - } - - static constexpr uint32_t g_shash_primes[] = { - 11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919, - 1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10103,12143,14591, - 17519,21023,25229,30293,36353,43627,52361,62851,75431,90523, 108631, 130363, - 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, - 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, - 4999559, 5999471, 7199369 }; - - // Returns a prime larger than 'number' or 0, in case of overflow - static count_t NextPrime(count_t number) - { - for (int i = 0; i < (int) (sizeof(g_shash_primes) / sizeof(g_shash_primes[0])); i++) - { - if (g_shash_primes[i] >= number) - return (typename SHash_EP::count_t)(g_shash_primes[i]); - } - - if ((number&1) == 0) - number++; - - while (number != 1) - { - if (IsPrime(number)) - return number; - number += 2; - } - - return 0; - } - - static bool Add(element_t *table, count_t tableSize, const element_t &element) - { - key_t key = TRAITS::GetKey(element); - - count_t hash = TRAITS::Hash(key); - count_t index = hash % tableSize; - count_t increment = 0; // delay computation - - while (true) - { - element_t& current = table[index]; - - if (TRAITS::IsNull(current)) - { - table[index] = element; - return true; - } - - if (TRAITS::IsDeleted(current)) - { - table[index] = element; - return false; - } - - if (increment == 0) - increment = (hash % (tableSize-1)) + 1; - - index += increment; - if (index >= tableSize) - index -= tableSize; - } - } - -}; - -template -class KeyValuePair_EP{ - KEY key; - VALUE value; - -public: - KeyValuePair_EP() - { - } - - KeyValuePair_EP(const KEY& k, const VALUE& v) - : key(k), value(v) - { - } - - KEY const & Key() const - { - return key; - } - - VALUE const & Value() const - { - return value; - } -}; - -template -class NoRemoveSHashTraits_EP : public PARENT -{ -public: - typedef typename PARENT::element_t element_t; - typedef typename PARENT::count_t count_t; -}; - -template -class MapSHashTraits_EP : public DefaultSHashTraits_EP< KeyValuePair_EP > -{ -public: - typedef typename DefaultSHashTraits_EP< KeyValuePair_EP >::element_t element_t; - typedef typename DefaultSHashTraits_EP< KeyValuePair_EP >::count_t count_t; - - typedef KEY key_t; - typedef VALUE value_t; - - static key_t GetKey(element_t e) - { - return e.Key(); - } - static bool Equals(key_t k1, key_t k2) - { - return k1 == k2; - } - static count_t Hash(key_t k) - { - return (count_t)(size_t)k; - } - - static const element_t Null() - { - return element_t(KEY(),VALUE()); - } - static bool IsNull(const element_t &e) - { - return e.Key() == KEY(); - } - static bool IsDeleted(const element_t &e) - { - return e.Key() == KEY(-1); - } - - key_t const & Key() const - { - //PalDebugBreak(); - return *(new KEY()); - } - - value_t const & Value() const - { - //PalDebugBreak(); - return *(new VALUE()); - } -}; - - -#endif // __EmptyContainers2_h__ diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt index 39d658d..d91a084 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt @@ -7,13 +7,17 @@ include_directories(${EP_GENERATED_HEADER_PATH}) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(AOT_EVENTPIPE_SHIM_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +set (CONTAINER_SOURCES "") +set (CONTAINER_HEADERS "") set (EVENTPIPE_SOURCES "") set (EVENTPIPE_HEADERS "") set (CORECLR_EVENTPIPE_SHIM_SOURCES "") set (CORECLR_EVENTPIPE_SHIM_HEADERS "") +set (SHARED_CONTAINERS_SOURCE_PATH "${CLR_SRC_NATIVE_DIR}/containers") set (SHARED_EVENTPIPE_SOURCE_PATH "${CLR_SRC_NATIVE_DIR}/eventpipe") -include (${SHARED_EVENTPIPE_SOURCE_PATH}/CMakeLists.txt) +include (${SHARED_EVENTPIPE_SOURCE_PATH}/eventpipe.cmake) +include (${SHARED_CONTAINERS_SOURCE_PATH}/containers.cmake) list(APPEND SHARED_DIAGNOSTIC_SERVER_SOURCES ds-ipc-pal-namedpipe.c @@ -33,16 +37,21 @@ list(APPEND EVENTPIPE_HEADERS ${SHARED_DIAGNOSTIC_SERVER_HEADERS} ) +addprefix(CONTAINER_SOURCES ${SHARED_CONTAINERS_SOURCE_PATH} "${SHARED_CONTAINER_SOURCES}") +addprefix(CONTAINER_HEADERS ${SHARED_CONTAINERS_SOURCE_PATH} "${SHARED_CONTAINER_HEADERS}") + addprefix(EVENTPIPE_SOURCES ${SHARED_EVENTPIPE_SOURCE_PATH} "${EVENTPIPE_SOURCES}") addprefix(EVENTPIPE_HEADERS ${SHARED_EVENTPIPE_SOURCE_PATH} "${EVENTPIPE_HEADERS}") set_source_files_properties(${SHARED_EVENTPIPE_SOURCE_PATH}/ep-sources.c PROPERTIES COMPILE_DEFINITIONS EP_FORCE_INCLUDE_SOURCE_FILES) set_source_files_properties(${SHARED_EVENTPIPE_SOURCE_PATH}/ds-sources.c PROPERTIES COMPILE_DEFINITIONS DS_FORCE_INCLUDE_SOURCE_FILES) +set_source_files_properties(${CONTAINER_SOURCES} PROPERTIES LANGUAGE CXX) set_source_files_properties(${EVENTPIPE_SOURCES} PROPERTIES LANGUAGE CXX) if(CLR_CMAKE_HOST_UNIX) if (CMAKE_VERSION VERSION_GREATER 3.11 OR CMAKE_VERSION VERSION_EQUAL 3.11) + set_source_files_properties(${CONTAINER_SOURCES} PROPERTIES COMPILE_OPTIONS -xc++) set_source_files_properties(${EVENTPIPE_SOURCES} PROPERTIES COMPILE_OPTIONS -xc++) else(CMAKE_VERSION VERSION_GREATER 3.11 OR CMAKE_VERSION VERSION_EQUAL 3.11) add_compile_options(-xc++) @@ -77,6 +86,8 @@ list(APPEND EVENTPIPE_SOURCES ${AOT_EVENTPIPE_SHIM_HEADERS} ${AOT_EVENTPIPE_MANAGED_TO_NATIVE_SOURCES} ${SHARED_EVENTPIPE_CONFIG_HEADERS} + ${CONTAINER_SOURCES} + ${CONTAINER_HEADERS} ) list(APPEND AOT_EVENTPIPE_DISABLED_SOURCES diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h index de297ab..def48eb 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h @@ -64,22 +64,6 @@ #undef DS_EXIT_BLOCKING_PAL_SECTION #define DS_EXIT_BLOCKING_PAL_SECTION -#undef DS_RT_DEFINE_ARRAY -#define DS_RT_DEFINE_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_LOCAL_ARRAY -#define DS_RT_DEFINE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_ARRAY_ITERATOR -#define DS_RT_DEFINE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR -#define DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type) - /* * AutoTrace. */ @@ -215,34 +199,6 @@ ds_rt_transport_get_default_name ( } /* - * DiagnosticsIpcPollHandle. - */ - -DS_RT_DEFINE_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) -DS_RT_DEFINE_LOCAL_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) -DS_RT_DEFINE_ARRAY_ITERATOR (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) - -#undef DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY -#define DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ds_rt_ipc_poll_handle_array_t) - -/* - * DiagnosticsPort. - */ - -DS_RT_DEFINE_ARRAY (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *) -DS_RT_DEFINE_ARRAY_ITERATOR (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *) - -DS_RT_DEFINE_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_LOCAL_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_ARRAY_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_reverse_iterator_t, ep_char8_t *) - -#undef DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY -#define DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ds_rt_port_config_array_t) - -/* * DiagnosticsProfiler. */ #ifdef PROFILING_SUPPORTED diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-types-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-types-aot.h index b71afd05..7656799 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-types-aot.h +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-types-aot.h @@ -10,34 +10,5 @@ #ifdef ENABLE_PERFTRACING #include "ep-rt-types-aot.h" -/* - * DiagnosticsIpcPollHandle. - */ - -#undef ds_rt_ipc_poll_handle_array_t -typedef struct _rt_aot_array_internal_t ds_rt_ipc_poll_handle_array_t; - -#undef ds_rt_ipc_poll_handle_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ds_rt_ipc_poll_handle_array_iterator_t; - -/* - * DiagnosticsPort. - */ - -#undef ds_rt_port_array_t -typedef struct _rt_aot_array_internal_t ds_rt_port_array_t; - -#undef ds_rt_port_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ds_rt_port_array_iterator_t; - -#undef ds_rt_port_config_array_t -typedef struct _rt_aot_array_internal_t ds_rt_port_config_array_t; - -#undef ds_rt_port_config_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ds_rt_port_config_array_iterator_t; - -#undef ds_rt_port_config_array_reverse_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ds_rt_port_config_array_reverse_iterator_t; - #endif /* ENABLE_PERFTRACING */ #endif /* __DIAGNOSTICS_RT_TYPES_AOT_H__ */ diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h index 019c044..7424062 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h @@ -56,1078 +56,6 @@ static inline uint8_t* _rt_aot_align_up(uint8_t* val, uintptr_t alignment) return reinterpret_cast(result); } -#ifndef EP_RT_BUILD_TYPE_FUNC_NAME -#define EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, type_name, func_name) \ -prefix_name ## _rt_ ## type_name ## _ ## func_name -#endif - -template -static -inline -void -_rt_aot_list_alloc (LIST_TYPE *list) { - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL); - - list->list = new (nothrow) typename LIST_TYPE::list_type_t (); -} - -template -static -inline -void -_rt_aot_list_free ( - LIST_TYPE *list, - void (*callback)(void *)) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL); - - if (list->list) { - while (!list->list->IsEmpty ()) { - typename LIST_TYPE::element_type_t *current = list->list->RemoveHead (); - if (callback) - callback (reinterpret_cast(current->GetValue ())); - delete current; - } - delete list->list; - } - list->list = NULL; -} - -template -static -inline -void -_rt_aot_list_clear ( - LIST_TYPE *list, - void (*callback)(void *)) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - - while (!list->list->IsEmpty ()) { - typename LIST_TYPE::element_type_t *current = list->list->RemoveHead (); - if (callback) - callback (reinterpret_cast(current->GetValue ())); - delete current; - } -} - -template -static -inline -bool -_rt_aot_list_append ( - LIST_TYPE *list, - LIST_ITEM item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - - typename LIST_TYPE::element_type_t *node = new (nothrow) typename LIST_TYPE::element_type_t (item); - if (node) - list->list->InsertTail (node); - return (node != NULL); -} - -template -static -inline -void -_rt_aot_list_remove ( - LIST_TYPE *list, - CONST_LIST_ITEM item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - - typename LIST_TYPE::element_type_t *current = list->list->GetHead (); - while (current) { - if (current->GetValue () == item) { - if (list->list->FindAndRemove (current)) - delete current; - break; - } - current = list->list->GetNext (current); - } -} - -template -static -inline -bool -_rt_aot_list_find ( - CONST_LIST_TYPE *list, - CONST_LIST_ITEM item_to_find, - LIST_ITEM *found_item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - EP_ASSERT (found_item != NULL); - - bool found = false; - typename LIST_TYPE::element_type_t *current = list->list->GetHead (); - while (current) { - if (current->GetValue () == item_to_find) { - *found_item = current->GetValue (); - found = true; - break; - } - current = list->list->GetNext (current); - } - return found; -} - -template -static -inline -bool -_rt_aot_list_is_empty (CONST_LIST_TYPE *list) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL); - - return (list->list == NULL || list->list->IsEmpty ()); -} - -template -static -inline -bool -_rt_aot_list_is_valid (CONST_LIST_TYPE *list) -{ - STATIC_CONTRACT_NOTHROW; - return (list != NULL && list->list != NULL); -} - -template -static -inline -ITERATOR_TYPE -_rt_aot_list_iterator_begin (CONST_LIST_TYPE *list) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - - return list->list->begin (); -} - -template -static -inline -bool -_rt_aot_list_iterator_end ( - CONST_LIST_TYPE *list, - CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL && iterator != NULL); - - return (*iterator == list->list->end ()); -} - -template -static -inline -void -_rt_aot_list_iterator_next (ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL); - - (*iterator)++; -} - -template -static -inline -ITEM_TYPE -_rt_aot_list_iterator_value (CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL); - - return const_cast(iterator)->operator*(); -} - -template -static -inline -void -_rt_aot_queue_alloc (QUEUE_TYPE *queue) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL); - - queue->queue = new (nothrow) typename QUEUE_TYPE::queue_type_t (); -} - -template -static -inline -void -_rt_aot_queue_free (QUEUE_TYPE *queue) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL); - - if (queue->queue) - delete queue->queue; - queue->queue = NULL; -} - -template -static -inline -bool -_rt_aot_queue_pop_head ( - QUEUE_TYPE *queue, - ITEM_TYPE *item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL && queue->queue != NULL && item != NULL); - - bool found = true; - typename QUEUE_TYPE::element_type_t *node = queue->queue->RemoveHead (); - if (node) { - *item = node->m_Value; - delete node; - } else { - *item = NULL; - found = false; - } - return found; -} - -template -static -inline -bool -_rt_aot_queue_push_head ( - QUEUE_TYPE *queue, - ITEM_TYPE item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL && queue->queue != NULL); - - typename QUEUE_TYPE::element_type_t *node = new (nothrow) typename QUEUE_TYPE::element_type_t (item); - if (node) - queue->queue->InsertHead (node); - return (node != NULL); -} - -template -static -inline -bool -_rt_aot_queue_push_tail ( - QUEUE_TYPE *queue, - ITEM_TYPE item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL && queue->queue != NULL); - - typename QUEUE_TYPE::element_type_t *node = new (nothrow) typename QUEUE_TYPE::element_type_t (item); - if (node) - queue->queue->InsertTail (node); - return (node != NULL); -} - -template -static -inline -bool -_rt_aot_queue_is_empty (CONST_QUEUE_TYPE *queue) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL && queue->queue != NULL); - - return (queue->queue != NULL && queue->queue->IsEmpty ()); -} - -template -static -inline -bool -_rt_aot_queue_is_valid (CONST_QUEUE_TYPE *queue) -{ - STATIC_CONTRACT_NOTHROW; - return (queue != NULL && queue->queue != NULL); -} - -template -static -inline -void -_rt_aot_array_alloc (ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL); - - ep_array->array = new (nothrow) typename ARRAY_TYPE::array_type_t (); -} - -template -static -inline -void -_rt_aot_array_alloc_capacity ( - ARRAY_TYPE *ep_array, - size_t capacity) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL); - - ep_array->array = new (nothrow) typename ARRAY_TYPE::array_type_t (); - if (ep_array->array) - ep_array->array->AllocNoThrow (capacity); -} - -template -static -inline -void -_rt_aot_array_init_capacity ( - ARRAY_TYPE *ep_array, - size_t capacity) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL); - - if (ep_array->array) - ep_array->array->AllocNoThrow (capacity); -} - -template -static -inline -void -_rt_aot_array_free (ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL); - - if (ep_array->array) { - delete ep_array->array; - ep_array->array = NULL; - } -} - -template -static -inline -bool -_rt_aot_array_append ( - ARRAY_TYPE *ep_array, - ITEM_TYPE item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - return ep_array->array->PushNoThrow (item); -} - -template -static -inline -void -_rt_aot_array_clear (ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - while (ep_array->array->Size () > 0) - ITEM_TYPE item = ep_array->array->Pop (); - ep_array->array->Shrink (); -} - -template -static -inline -size_t -_rt_aot_array_size (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - return ep_array->array->Size (); -} - -template -static -inline -ITEM_TYPE * -_rt_aot_array_data (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - return ep_array->array->Ptr (); -} - -template -static -inline -bool -_rt_aot_array_is_valid (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - return (ep_array->array != NULL); -} - -template -static -inline -ITERATOR_TYPE -_rt_aot_array_iterator_begin (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - ITERATOR_TYPE temp; - temp.array = ep_array->array; - temp.index = 0; - return temp; -} - -template -static -inline -bool -_rt_aot_array_iterator_end ( - CONST_ARRAY_TYPE *ep_array, - CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && iterator != NULL && iterator->array != NULL); - - return (iterator->index >= static_cast(iterator->array->Size ())); -} - -template -static -inline -void -_rt_aot_array_iterator_next (ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL); - - iterator->index++; -} - -template -static -inline -ITEM_TYPE -_rt_aot_array_iterator_value (const CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL && iterator->array != NULL); - EP_ASSERT (iterator->index < static_cast(iterator->array->Size ())); - - return iterator->array->operator[] (iterator->index); -} - -template -static -inline -ITERATOR_TYPE -_rt_aot_array_reverse_iterator_begin (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - ITERATOR_TYPE temp; - temp.array = ep_array->array; - temp.index = static_cast(ep_array->array->Size ()); - return temp; -} - -template -static -inline -bool -_rt_aot_array_reverse_iterator_end ( - CONST_ARRAY_TYPE *ep_array, - CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && iterator != NULL && iterator->array != NULL); - - return (iterator->index == 0); -} - -template -static -inline -void -_rt_aot_array_reverse_iterator_next (ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL); - - iterator->index--; -} - -template -static -inline -ITEM_TYPE -_rt_aot_array_reverse_iterator_value (CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL && iterator->array != NULL); - EP_ASSERT (iterator->index > 0); - - return iterator->array->operator[] (iterator->index - 1); -} - -template -static -inline -void -_rt_aot_hash_map_alloc ( - HASH_MAP_TYPE *hash_map, - uint32_t (*hash_callback)(const void *), - bool (*eq_callback)(const void *, const void *), - void (*key_free_callback)(void *), - void (*value_free_callback)(void *)) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && key_free_callback == NULL); - - hash_map->table = new (nothrow) typename HASH_MAP_TYPE::table_type_t (); - hash_map->callbacks.key_free_func = key_free_callback; - hash_map->callbacks.value_free_func = value_free_callback; -} - -template -static -inline -void -_rt_aot_hash_map_free (HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL); - - if (hash_map->table) { - if (hash_map->callbacks.value_free_func) { - for (typename HASH_MAP_TYPE::table_type_t::Iterator iterator = hash_map->table->Begin (); iterator != hash_map->table->End (); ++iterator) - hash_map->callbacks.value_free_func (reinterpret_cast((ptrdiff_t)(iterator->Value ()))); - } - delete hash_map->table; - } -} - -template -static -inline -bool -_rt_aot_hash_map_add ( - HASH_MAP_TYPE *hash_map, - KEY_TYPE key, - VALUE_TYPE value) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - return hash_map->table->Add (typename HASH_MAP_TYPE::table_type_t::element_t (key, value)); -} - -template -static -inline -bool -_rt_aot_hash_map_add_or_replace ( - HASH_MAP_TYPE *hash_map, - KEY_TYPE key, - VALUE_TYPE value) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - return hash_map->table->AddOrReplaceNoThrow (typename HASH_MAP_TYPE::table_type_t::element_t (key, value)); -} - -template -static -inline -void -_rt_aot_hash_map_remove_all (HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - if (hash_map->callbacks.value_free_func) { - for (typename HASH_MAP_TYPE::table_type_t::Iterator iterator = hash_map->table->Begin (); iterator != hash_map->table->End (); ++iterator) - hash_map->callbacks.value_free_func (reinterpret_cast((ptrdiff_t)(iterator->Value ()))); - } - hash_map->table->RemoveAll (); -} - -template -static -inline -bool -_rt_aot_hash_map_lookup ( - CONST_HASH_MAP_TYPE *hash_map, - CONST_KEY_TYPE key, - VALUE_TYPE *value) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - const typename HASH_MAP_TYPE::table_type_t::element_t *ret = hash_map->table->LookupPtr ((KEY_TYPE)key); - if (ret == NULL) - return false; - *value = ret->Value (); - return true; -} - -template -static -inline -uint32_t -_rt_aot_hash_map_count (CONST_HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - return hash_map->table->GetCount (); -} - -template -static -inline -bool -_rt_aot_hash_map_is_valid (CONST_HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - - return (hash_map != NULL && hash_map->table != NULL); -} - -template -static -inline -void -_rt_aot_hash_map_remove ( - HASH_MAP_TYPE *hash_map, - CONST_KEY_TYPE key) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - const typename HASH_MAP_TYPE::table_type_t::element_t *ret = NULL; - if (hash_map->callbacks.value_free_func) - ret = hash_map->table->LookupPtr ((KEY_TYPE)key); - hash_map->table->Remove ((KEY_TYPE)key); - if (ret) - hash_map->callbacks.value_free_func (reinterpret_cast(static_cast(ret->Value ()))); -} - -template -static -inline -ITERATOR_TYPE -_rt_aot_hash_map_iterator_begin (CONST_HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - return hash_map->table->Begin (); -} - -template -static -inline -bool -_rt_aot_hash_map_iterator_end ( - CONST_HASH_MAP_TYPE *hash_map, - CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL && iterator != NULL); - - return (hash_map->table->End () == *iterator); -} - -template -static -inline -void -_rt_aot_hash_map_iterator_next (ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (iterator != NULL); - - (*iterator)++; -} - -template -static -inline -KEY_TYPE -_rt_aot_hash_map_iterator_key (CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (iterator != NULL); - - return (*iterator)->Key (); -} - -template -static -inline -VALUE_TYPE -_rt_aot_hash_map_iterator_value (CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (iterator != NULL); - - return (*iterator)->Value (); -} - -#define EP_RT_DEFINE_LIST_PREFIX(prefix_name, list_name, list_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, alloc) (list_type *list) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_list_alloc(list); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, free) (list_type *list, void (*callback)(void *)) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_list_free(list, callback); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, clear) (list_type *list, void (*callback)(void *)) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_list_clear(list, callback); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, append) (list_type *list, item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_list_append(list, item); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, remove) (list_type *list, const item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_list_remove(list, item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, find) (const list_type *list, const item_type item_to_find, item_type *found_item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_list_find(list, item_to_find, found_item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_empty) (const list_type *list) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_list_is_empty(list); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_valid) (const list_type *list) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_list_is_valid(list); \ - } - -#undef EP_RT_DEFINE_LIST -#define EP_RT_DEFINE_LIST(list_name, list_type, item_type) \ - EP_RT_DEFINE_LIST_PREFIX(ep, list_name, list_type, item_type) - -#define EP_RT_DEFINE_LIST_ITERATOR_PREFIX(prefix_name, list_name, list_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_begin) (const list_type *list) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_list_iterator_begin(list); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_end) (const list_type *list, const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_list_iterator_end(list, iterator); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_next) (iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_list_iterator_next(iterator); \ - } \ - static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_value) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_list_iterator_value(iterator); \ - } - -#undef EP_RT_DEFINE_LIST_ITERATOR -#define EP_RT_DEFINE_LIST_ITERATOR(list_name, list_type, iterator_type, item_type) \ - EP_RT_DEFINE_LIST_ITERATOR_PREFIX(ep, list_name, list_type, iterator_type, item_type) - -#define EP_RT_DEFINE_QUEUE_PREFIX(prefix_name, queue_name, queue_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, alloc) (queue_type *queue) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_queue_alloc(queue); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, free) (queue_type *queue) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_queue_free(queue); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, pop_head) (queue_type *queue, item_type *item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_queue_pop_head(queue, item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_head) (queue_type *queue, item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_queue_push_head(queue, item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_tail) (queue_type *queue, item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_queue_push_tail(queue, item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_empty) (const queue_type *queue) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_queue_is_empty(queue); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_valid) (const queue_type *queue) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_queue_is_valid(queue); \ - } - -#undef EP_RT_DEFINE_QUEUE -#define EP_RT_DEFINE_QUEUE(queue_name, queue_type, item_type) \ - EP_RT_DEFINE_QUEUE_PREFIX(ep, queue_name, queue_type, item_type) - -#define EP_RT_DEFINE_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc) (array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_array_alloc(ep_array); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc_capacity) (array_type *ep_array, size_t capacity) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_array_alloc_capacity(ep_array, capacity); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, free) (array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_array_free(ep_array); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, append) (array_type *ep_array, item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_append (ep_array, item); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, clear) (array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_array_clear (ep_array); \ - } \ - static inline size_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, size) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_size (ep_array); \ - } \ - static inline item_type * EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, data) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_data (ep_array); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, is_valid) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_is_valid (ep_array); \ - } - -#define EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init) (array_type *ep_array) { \ - STATIC_CONTRACT_NOTHROW; \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init_capacity) (array_type *ep_array, size_t capacity) { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_array_init_capacity(ep_array, capacity); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, fini) (array_type *ep_array) { \ - STATIC_CONTRACT_NOTHROW; \ - } - -#undef EP_RT_DEFINE_ARRAY -#define EP_RT_DEFINE_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#undef EP_RT_DEFINE_LOCAL_ARRAY -#define EP_RT_DEFINE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, var_type) \ - var_type::array_type_t _local_ ##var_name; \ - var_type var_name; \ - var_name.array = &_local_ ##var_name - -#define EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_begin) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_iterator_begin (ep_array); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_end) (const array_type *ep_array, const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_iterator_end (ep_array, iterator); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_next) (iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_array_iterator_next (iterator); \ - } \ - static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_value) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_iterator_value (iterator); \ - } - -#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_begin) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_reverse_iterator_begin (ep_array); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_end) (const array_type *ep_array, const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_reverse_iterator_end (ep_array, iterator); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_next) (iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_array_reverse_iterator_next (iterator); \ - } \ - static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_value) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_array_reverse_iterator_value (iterator); \ - } - -#undef EP_RT_DEFINE_ARRAY_ITERATOR -#define EP_RT_DEFINE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#undef EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR -#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, alloc) (hash_map_type *hash_map, uint32_t (*hash_callback)(const void *), bool (*eq_callback)(const void *, const void *), void (*key_free_callback)(void *), void (*value_free_callback)(void *)) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_hash_map_alloc(hash_map, hash_callback, eq_callback, key_free_callback, value_free_callback); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, free) (hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_hash_map_free(hash_map); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add) (hash_map_type *hash_map, key_type key, value_type value) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_add(hash_map, key, value); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove_all) (hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_hash_map_remove_all(hash_map); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, lookup) (const hash_map_type *hash_map, const key_type key, value_type *value) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_lookup(hash_map, key, value); \ - } \ - static inline uint32_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, count) (const hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_count(hash_map); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, is_valid) (const hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_is_valid(hash_map); \ - } - -#define EP_RT_DEFINE_HASH_MAP_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add_or_replace) (hash_map_type *hash_map, key_type key, value_type value) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_add_or_replace(hash_map, key, value); \ - } \ - -#define EP_RT_DEFINE_HASH_MAP_REMOVE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove) (hash_map_type *hash_map, const key_type key) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_hash_map_remove(hash_map, key); \ - } - -#undef EP_RT_DEFINE_HASH_MAP -#define EP_RT_DEFINE_HASH_MAP(hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type) - -#undef EP_RT_DEFINE_HASH_MAP_REMOVE -#define EP_RT_DEFINE_HASH_MAP_REMOVE(hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_REMOVE_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type) - -#define EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(prefix_name, hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_begin) (const hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_iterator_begin(hash_map); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_end) (const hash_map_type *hash_map, const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_iterator_end(hash_map, iterator); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_next) (iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_aot_hash_map_iterator_next(iterator); \ - } \ - static inline key_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_key) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_iterator_key(iterator); \ - } \ - static inline value_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_value) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_aot_hash_map_iterator_value(iterator); \ - } - -#undef EP_RT_DEFINE_HASH_MAP_ITERATOR -#define EP_RT_DEFINE_HASH_MAP_ITERATOR(hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(ep, hash_map_name, hash_map_type, iterator_type, key_type, value_type) - static inline ep_rt_lock_handle_t * @@ -1305,16 +233,6 @@ ep_rt_atomic_compare_exchange_utf8_string (ep_char8_t *volatile *target, ep_char return ep_rt_aot_atomic_compare_exchange_utf8_string (target, expected, value); } -/* - * EventPipe. - */ - -EP_RT_DEFINE_ARRAY (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID) -EP_RT_DEFINE_ARRAY_ITERATOR (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID) - -EP_RT_DEFINE_ARRAY (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *) -EP_RT_DEFINE_ARRAY_ITERATOR (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *) - static void ep_rt_init (void) @@ -1485,85 +403,6 @@ ep_rt_provider_invoke_callback ( callback_data); } -/* - * EventPipeBuffer. - */ - -EP_RT_DEFINE_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) -EP_RT_DEFINE_LOCAL_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) -EP_RT_DEFINE_ARRAY_ITERATOR (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) - -#undef EP_RT_DECLARE_LOCAL_BUFFER_ARRAY -#define EP_RT_DECLARE_LOCAL_BUFFER_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_buffer_array_t) - -/* - * EventPipeBufferList. - */ - -EP_RT_DEFINE_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) -EP_RT_DEFINE_LOCAL_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) -EP_RT_DEFINE_ARRAY_ITERATOR (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) - -#undef EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY -#define EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_buffer_list_array_t) - -/* - * EventPipeEvent. - */ - -EP_RT_DEFINE_LIST (event_list, ep_rt_event_list_t, EventPipeEvent *) -EP_RT_DEFINE_LIST_ITERATOR (event_list, ep_rt_event_list_t, ep_rt_event_list_iterator_t, EventPipeEvent *) - -/* - * EventPipeFile. - */ - -EP_RT_DEFINE_HASH_MAP_REMOVE(metadata_labels_hash, ep_rt_metadata_labels_hash_map_t, EventPipeEvent *, uint32_t) -EP_RT_DEFINE_HASH_MAP(stack_hash, ep_rt_stack_hash_map_t, StackHashKey *, StackHashEntry *) -EP_RT_DEFINE_HASH_MAP_ITERATOR(stack_hash, ep_rt_stack_hash_map_t, ep_rt_stack_hash_map_iterator_t, StackHashKey *, StackHashEntry *) - -/* - * EventPipeProvider. - */ - -EP_RT_DEFINE_LIST (provider_list, ep_rt_provider_list_t, EventPipeProvider *) -EP_RT_DEFINE_LIST_ITERATOR (provider_list, ep_rt_provider_list_t, ep_rt_provider_list_iterator_t, EventPipeProvider *) - -EP_RT_DEFINE_QUEUE (provider_callback_data_queue, ep_rt_provider_callback_data_queue_t, EventPipeProviderCallbackData *) - -static -EventPipeProvider * -ep_rt_provider_list_find_by_name ( - const ep_rt_provider_list_t *list, - const ep_char8_t *name) -{ - STATIC_CONTRACT_NOTHROW; - - // The provider list should be non-NULL, but can be NULL on shutdown. - if (list) { - SList_EP> *provider_list = list->list; - SListElem_EP *element = provider_list->GetHead (); - while (element) { - EventPipeProvider *provider = element->GetValue (); - if (ep_rt_utf8_string_compare (ep_provider_get_provider_name (element->GetValue ()), name) == 0) - return provider; - - element = provider_list->GetNext (element); - } - } - - return NULL; -} - -/* - * EventPipeProviderConfiguration. - */ - -EP_RT_DEFINE_ARRAY (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration) -EP_RT_DEFINE_ARRAY_ITERATOR (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration) - static inline bool @@ -1669,73 +508,6 @@ ep_rt_notify_profiler_provider_created (EventPipeProvider *provider) } /* - * EventPipeSessionProvider. - */ - -EP_RT_DEFINE_LIST (session_provider_list, ep_rt_session_provider_list_t, EventPipeSessionProvider *) -EP_RT_DEFINE_LIST_ITERATOR (session_provider_list, ep_rt_session_provider_list_t, ep_rt_session_provider_list_iterator_t, EventPipeSessionProvider *) - -static -EventPipeSessionProvider * -ep_rt_session_provider_list_find_by_name ( - const ep_rt_session_provider_list_t *list, - const ep_char8_t *name) -{ - STATIC_CONTRACT_NOTHROW; - - SList_EP> *provider_list = list->list; - EventPipeSessionProvider *session_provider = NULL; - SListElem_EP *element = provider_list->GetHead (); - while (element) { - EventPipeSessionProvider *candidate = element->GetValue (); - if (ep_rt_utf8_string_compare (ep_session_provider_get_provider_name (candidate), name) == 0) { - session_provider = candidate; - break; - } - element = provider_list->GetNext (element); - } - - return session_provider; -} - -/* - * EventPipeSequencePoint. - */ - -EP_RT_DEFINE_LIST (sequence_point_list, ep_rt_sequence_point_list_t, EventPipeSequencePoint *) -EP_RT_DEFINE_LIST_ITERATOR (sequence_point_list, ep_rt_sequence_point_list_t, ep_rt_sequence_point_list_iterator_t, EventPipeSequencePoint *) - -/* - * EventPipeThread. - */ - -EP_RT_DEFINE_LIST (thread_list, ep_rt_thread_list_t, EventPipeThread *) -EP_RT_DEFINE_LIST_ITERATOR (thread_list, ep_rt_thread_list_t, ep_rt_thread_list_iterator_t, EventPipeThread *) - -EP_RT_DEFINE_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) -EP_RT_DEFINE_LOCAL_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) -EP_RT_DEFINE_ARRAY_ITERATOR (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) - -#undef EP_RT_DECLARE_LOCAL_THREAD_ARRAY -#define EP_RT_DECLARE_LOCAL_THREAD_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_thread_array_t) - -/* - * EventPipeThreadSessionState. - */ - -EP_RT_DEFINE_LIST (thread_session_state_list, ep_rt_thread_session_state_list_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_LIST_ITERATOR (thread_session_state_list, ep_rt_thread_session_state_list_t, ep_rt_thread_session_state_list_iterator_t, EventPipeThreadSessionState *) - -EP_RT_DEFINE_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_LOCAL_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_ARRAY_ITERATOR (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) - -#undef EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY -#define EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_thread_session_state_array_t) - -/* * Arrays. */ @@ -1937,7 +709,7 @@ ep_rt_is_running (void) static inline void -ep_rt_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints) +ep_rt_execute_rundown (dn_vector_ptr_t *execution_checkpoints) { STATIC_CONTRACT_NOTHROW; @@ -2265,12 +1037,9 @@ ep_rt_temp_path_get ( return 0; } -EP_RT_DEFINE_ARRAY (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *) -EP_RT_DEFINE_ARRAY_ITERATOR (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *) - static void -ep_rt_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array) +ep_rt_os_environment_get_utf16 (dn_vector_ptr_t *env_array) { STATIC_CONTRACT_NOTHROW; EP_ASSERT (env_array != NULL); @@ -2911,13 +1680,6 @@ ep_rt_thread_set_activity_id ( #define EP_YIELD_WHILE(condition) {}//YIELD_WHILE(condition) /* - * ThreadSequenceNumberMap. - */ - -EP_RT_DEFINE_HASH_MAP_REMOVE(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, EventPipeThreadSessionState *, uint32_t) -EP_RT_DEFINE_HASH_MAP_ITERATOR(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, ep_rt_thread_sequence_number_hash_map_iterator_t, EventPipeThreadSessionState *, uint32_t) - -/* * Volatile. */ diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-types-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-types-aot.h index 647bb50..df06d26 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-types-aot.h +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-types-aot.h @@ -8,11 +8,10 @@ #include #include +#include "rhassert.h" #ifdef ENABLE_PERFTRACING -#include "EmptyContainers.h" - #ifdef TARGET_UNIX #define __stdcall #endif @@ -37,97 +36,6 @@ #undef EP_UNLIKELY #define EP_UNLIKELY(expr) expr -template -struct _rt_aot_list_internal_t { - typedef struct SListElem_EP element_type_t; - typedef class SList_EP list_type_t; - list_type_t *list; -}; - -template -struct _rt_aot_queue_internal_t { - typedef struct SListElem_EP element_type_t; - typedef class SList_EP queue_type_t; - queue_type_t *queue; -}; - -template -struct _rt_aot_array_internal_t { - typedef T element_type_t; - typedef class CQuickArrayList_EP array_type_t; - array_type_t *array; -}; - -template -struct _rt_aot_array_iterator_internal_t { - typedef typename _rt_aot_array_internal_t::array_type_t array_iterator_type; - array_iterator_type *array; - size_t index; -}; - -typedef struct _rt_aot_table_callbacks_t { - void (*key_free_func)(void *); - void (*value_free_func)(void *); -} rt_aot_table_callbacks_t; - -template -struct _rt_aot_table_default_internal_t { - typedef class SHash_EP > > table_type_t; - rt_aot_table_callbacks_t callbacks; - table_type_t *table; -}; - -template -struct _rt_aot_table_remove_internal_t { - typedef class SHash_EP< MapSHashTraits_EP > table_type_t; - rt_aot_table_callbacks_t callbacks; - table_type_t *table; -}; - -class EventPipeAotStackHashTraits : public NoRemoveSHashTraits_EP< MapSHashTraits_EP > -{ -public: - typedef typename MapSHashTraits_EP::element_t element_t; - typedef typename MapSHashTraits_EP::count_t count_t; - - typedef StackHashKey * key_t; - - static key_t GetKey (element_t e) - { - extern StackHashKey * ep_stack_hash_entry_get_key (StackHashEntry *); - return ep_stack_hash_entry_get_key (e.Value ()); - } - - static bool Equals (key_t k1, key_t k2) - { - extern bool ep_stack_hash_key_equal (const void *, const void *); - return ep_stack_hash_key_equal (k1, k2); - } - - static count_t Hash (key_t k) - { - extern uint32_t ep_stack_hash_key_hash (const void *); - return (count_t)ep_stack_hash_key_hash (k); - } - - static element_t Null () - { - return element_t (NULL, NULL); - } - - static bool IsNull (const element_t &e) - { - return (e.Key () == NULL|| e.Value () == NULL); - } -}; - -template -struct _rt_aot_table_custom_internal_t { - typedef class SHash_EP table_type_t; - rt_aot_table_callbacks_t callbacks; - table_type_t *table; -}; - class CLREventStatic; struct _rt_aot_event_internal_t { CLREventStatic *event; @@ -139,155 +47,16 @@ struct _rt_aot_lock_internal_t { }; /* - * EventPipeBuffer. - */ - -#undef ep_rt_buffer_array_t -typedef struct _rt_aot_array_internal_t ep_rt_buffer_array_t; - -#undef ep_rt_buffer_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ep_rt_buffer_array_iterator_t; - -/* - * EventPipeBufferList. - */ - -#undef ep_rt_buffer_list_array_t -typedef struct _rt_aot_array_internal_t ep_rt_buffer_list_array_t; - -#undef ep_rt_buffer_list_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ep_rt_buffer_list_array_iterator_t; - -/* - * EventPipeEvent. - */ - -#undef ep_rt_event_list_t -typedef struct _rt_aot_list_internal_t ep_rt_event_list_t; - -#undef ep_rt_event_list_iterator_t -typedef class _rt_aot_list_internal_t::list_type_t::Iterator ep_rt_event_list_iterator_t; - -/* - * EventPipeFile. - */ - -#undef ep_rt_metadata_labels_hash_map_t -typedef struct _rt_aot_table_remove_internal_t ep_rt_metadata_labels_hash_map_t; - -#undef ep_rt_metadata_labels_hash_map_iterator_t -typedef class _rt_aot_table_remove_internal_t::table_type_t::Iterator ep_rt_metadata_labels_hash_map_iterator_t; - -#undef ep_rt_stack_hash_map_t -typedef struct _rt_aot_table_custom_internal_t ep_rt_stack_hash_map_t; - -#undef ep_rt_stack_hash_map_iterator_t -typedef class _rt_aot_table_custom_internal_t::table_type_t::Iterator ep_rt_stack_hash_map_iterator_t; - -/* - * EventPipeProvider. - */ - -#undef ep_rt_provider_list_t -typedef struct _rt_aot_list_internal_t ep_rt_provider_list_t; - -#undef ep_rt_provider_list_iterator_t -typedef class _rt_aot_list_internal_t::list_type_t::Iterator ep_rt_provider_list_iterator_t; - -#undef ep_rt_provider_callback_data_queue_t -typedef struct _rt_aot_queue_internal_t ep_rt_provider_callback_data_queue_t; - -/* - * EventPipeProviderConfiguration. - */ - -#undef ep_rt_provider_config_array_t -typedef struct _rt_aot_array_internal_t ep_rt_provider_config_array_t; - -#undef ep_rt_provider_config_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ep_rt_provider_config_array_iterator_t; - -/* - * EventPipeSessionProvider. - */ - -#undef ep_rt_session_provider_list_t -typedef struct _rt_aot_list_internal_t ep_rt_session_provider_list_t; - -#undef ep_rt_session_provider_list_iterator_t -typedef class _rt_aot_list_internal_t::list_type_t::Iterator ep_rt_session_provider_list_iterator_t; - -/* - * EventPipeSequencePoint. - */ - -#undef ep_rt_sequence_point_list_t -typedef struct _rt_aot_list_internal_t ep_rt_sequence_point_list_t; - -#undef ep_rt_sequence_point_list_iterator_t -typedef class _rt_aot_list_internal_t::list_type_t::Iterator ep_rt_sequence_point_list_iterator_t; - -/* - * EventPipeThread. - */ - -#undef ep_rt_thread_list_t -typedef struct _rt_aot_list_internal_t ep_rt_thread_list_t; - -#undef ep_rt_thread_list_iterator_t -typedef class _rt_aot_list_internal_t::list_type_t::Iterator ep_rt_thread_list_iterator_t; - -#undef ep_rt_thread_array_t -typedef struct _rt_aot_array_internal_t ep_rt_thread_array_t; - -#undef ep_rt_thread_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ep_rt_thread_array_iterator_t; - -/* - * EventPipeThreadSessionState. - */ - -#undef ep_rt_thread_session_state_list_t -typedef struct _rt_aot_list_internal_t ep_rt_thread_session_state_list_t; - -#undef ep_rt_thread_session_state_list_iterator_t -typedef class _rt_aot_list_internal_t::list_type_t::Iterator ep_rt_thread_session_state_list_iterator_t; - -#undef ep_rt_thread_session_state_array_t -typedef struct _rt_aot_array_internal_t ep_rt_thread_session_state_array_t; - -#undef ep_rt_thread_session_state_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ep_rt_thread_session_state_array_iterator_t; - -/* * EventPipe. */ -#undef ep_rt_session_id_array_t -typedef struct _rt_aot_array_internal_t ep_rt_session_id_array_t; - -#undef ep_rt_session_id_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ep_rt_session_id_array_iterator_t; - #undef ep_rt_method_desc_t typedef class MethodDesc ep_rt_method_desc_t; -#undef ep_rt_execution_checkpoint_array_t -typedef struct _rt_aot_array_internal_t ep_rt_execution_checkpoint_array_t; - -#undef ep_rt_execution_checkpoint_array_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ep_rt_execution_checkpoint_array_iterator_t; - /* * PAL. */ -#undef ep_rt_env_array_utf16_t -typedef struct _rt_aot_array_internal_t ep_rt_env_array_utf16_t; - -#undef ep_rt_env_array_utf16_iterator_t -typedef struct _rt_aot_array_iterator_internal_t ep_rt_env_array_utf16_iterator_t; - #undef ep_rt_file_handle_t typedef class CFileStream * ep_rt_file_handle_t; @@ -332,15 +101,5 @@ typedef struct _rt_aot_thread_params_t { void *thread_params; } ep_rt_thread_params_t; -/* - * ThreadSequenceNumberMap. - */ - -#undef ep_rt_thread_sequence_number_hash_map_t -typedef struct _rt_aot_table_remove_internal_t ep_rt_thread_sequence_number_hash_map_t; - -#undef ep_rt_thread_sequence_number_hash_map_iterator_t -typedef class _rt_aot_table_remove_internal_t::table_type_t::Iterator ep_rt_thread_sequence_number_hash_map_iterator_t; - #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_RT_TYPES_AOT_H__ */ diff --git a/src/coreclr/vm/eventing/eventpipe/CMakeLists.txt b/src/coreclr/vm/eventing/eventpipe/CMakeLists.txt index de4169a..3619ffe 100644 --- a/src/coreclr/vm/eventing/eventpipe/CMakeLists.txt +++ b/src/coreclr/vm/eventing/eventpipe/CMakeLists.txt @@ -28,15 +28,19 @@ add_custom_command(OUTPUT ${GEN_EVENTPIPE_SOURCES} COMMAND ${GENERATE_COMMAND} DEPENDS ${GENERATE_SCRIPT} ${EVENT_MANIFEST} ${EVENT_EXCLUSIONS}) +set (CONTAINER_SOURCES "") +set (CONTAINER_HEADERS "") set (EVENTPIPE_SOURCES "") set (EVENTPIPE_HEADERS "") set (CORECLR_EVENTPIPE_SHIM_SOURCES "") set (CORECLR_EVENTPIPE_SHIM_HEADERS "") +set (SHARED_CONTAINERS_SOURCE_PATH "${CLR_SRC_NATIVE_DIR}/containers") set (SHARED_EVENTPIPE_SOURCE_PATH "${CLR_SRC_NATIVE_DIR}/eventpipe") set (CORECLR_EVENTPIPE_SHIM_SOURCE_PATH "${CORECLR_EVENTPIPE_SHIM_DIR}") -include (${SHARED_EVENTPIPE_SOURCE_PATH}/CMakeLists.txt) +include (${SHARED_CONTAINERS_SOURCE_PATH}/containers.cmake) +include (${SHARED_EVENTPIPE_SOURCE_PATH}/eventpipe.cmake) list(APPEND EVENTPIPE_SOURCES ${SHARED_EVENTPIPE_SOURCES} @@ -48,16 +52,21 @@ list(APPEND EVENTPIPE_HEADERS ${SHARED_DIAGNOSTIC_SERVER_HEADERS} ) +addprefix(CONTAINER_SOURCES ${SHARED_CONTAINERS_SOURCE_PATH} "${SHARED_CONTAINER_SOURCES}") +addprefix(CONTAINER_HEADERS ${SHARED_CONTAINERS_SOURCE_PATH} "${SHARED_CONTAINER_HEADERS}") + addprefix(EVENTPIPE_SOURCES ${SHARED_EVENTPIPE_SOURCE_PATH} "${EVENTPIPE_SOURCES}") addprefix(EVENTPIPE_HEADERS ${SHARED_EVENTPIPE_SOURCE_PATH} "${EVENTPIPE_HEADERS}") set_source_files_properties(${SHARED_EVENTPIPE_SOURCE_PATH}/ep-sources.c PROPERTIES COMPILE_DEFINITIONS EP_FORCE_INCLUDE_SOURCE_FILES) set_source_files_properties(${SHARED_EVENTPIPE_SOURCE_PATH}/ds-sources.c PROPERTIES COMPILE_DEFINITIONS DS_FORCE_INCLUDE_SOURCE_FILES) +set_source_files_properties(${CONTAINER_SOURCES} PROPERTIES LANGUAGE CXX) set_source_files_properties(${EVENTPIPE_SOURCES} PROPERTIES LANGUAGE CXX) if(CLR_CMAKE_HOST_UNIX) if (CMAKE_VERSION VERSION_GREATER 3.11 OR CMAKE_VERSION VERSION_EQUAL 3.11) + set_source_files_properties(${CONTAINER_SOURCES} PROPERTIES COMPILE_OPTIONS -xc++) set_source_files_properties(${EVENTPIPE_SOURCES} PROPERTIES COMPILE_OPTIONS -xc++) else(CMAKE_VERSION VERSION_GREATER 3.11 OR CMAKE_VERSION VERSION_EQUAL 3.11) add_compile_options(-xc++) @@ -85,6 +94,8 @@ list(APPEND EVENTPIPE_SOURCES ${CORECLR_EVENTPIPE_SHIM_HEADERS} ${EVENTPIPE_HEADERS} ${SHARED_EVENTPIPE_CONFIG_HEADERS} + ${CONTAINER_SOURCES} + ${CONTAINER_HEADERS} ) add_library_clr(eventpipe_gen_objs OBJECT ${GEN_EVENTPIPE_SOURCES}) diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h index cc445b8..aa5b8ca 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h @@ -65,22 +65,6 @@ #undef DS_EXIT_BLOCKING_PAL_SECTION #define DS_EXIT_BLOCKING_PAL_SECTION -#undef DS_RT_DEFINE_ARRAY -#define DS_RT_DEFINE_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_LOCAL_ARRAY -#define DS_RT_DEFINE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_ARRAY_ITERATOR -#define DS_RT_DEFINE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR -#define DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type) - /* * AutoTrace. */ @@ -245,34 +229,6 @@ ds_rt_transport_get_default_name ( } /* - * DiagnosticsIpcPollHandle. - */ - -DS_RT_DEFINE_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) -DS_RT_DEFINE_LOCAL_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) -DS_RT_DEFINE_ARRAY_ITERATOR (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) - -#undef DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY -#define DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ds_rt_ipc_poll_handle_array_t) - -/* - * DiagnosticsPort. - */ - -DS_RT_DEFINE_ARRAY (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *) -DS_RT_DEFINE_ARRAY_ITERATOR (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *) - -DS_RT_DEFINE_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_LOCAL_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_ARRAY_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_reverse_iterator_t, ep_char8_t *) - -#undef DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY -#define DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ds_rt_port_config_array_t) - -/* * DiagnosticsProfiler. */ #ifdef PROFILING_SUPPORTED diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-types-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-types-coreclr.h index 23da814..366dddf 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-types-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-types-coreclr.h @@ -10,34 +10,5 @@ #ifdef ENABLE_PERFTRACING #include "ep-rt-types-coreclr.h" -/* - * DiagnosticsIpcPollHandle. - */ - -#undef ds_rt_ipc_poll_handle_array_t -typedef struct _rt_coreclr_array_internal_t ds_rt_ipc_poll_handle_array_t; - -#undef ds_rt_ipc_poll_handle_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ds_rt_ipc_poll_handle_array_iterator_t; - -/* - * DiagnosticsPort. - */ - -#undef ds_rt_port_array_t -typedef struct _rt_coreclr_array_internal_t ds_rt_port_array_t; - -#undef ds_rt_port_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ds_rt_port_array_iterator_t; - -#undef ds_rt_port_config_array_t -typedef struct _rt_coreclr_array_internal_t ds_rt_port_config_array_t; - -#undef ds_rt_port_config_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ds_rt_port_config_array_iterator_t; - -#undef ds_rt_port_config_array_reverse_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ds_rt_port_config_array_reverse_iterator_t; - #endif /* ENABLE_PERFTRACING */ #endif /* __DIAGNOSTICS_RT_TYPES_CORECLR_H__ */ diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h index 0f679ab..c791563 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h @@ -35,1078 +35,6 @@ #undef EP_ALIGN_UP #define EP_ALIGN_UP(val,align) ALIGN_UP(val,align) -#ifndef EP_RT_BUILD_TYPE_FUNC_NAME -#define EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, type_name, func_name) \ -prefix_name ## _rt_ ## type_name ## _ ## func_name -#endif - -template -static -inline -void -_rt_coreclr_list_alloc (LIST_TYPE *list) { - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL); - - list->list = new (nothrow) typename LIST_TYPE::list_type_t (); -} - -template -static -inline -void -_rt_coreclr_list_free ( - LIST_TYPE *list, - void (*callback)(void *)) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL); - - if (list->list) { - while (!list->list->IsEmpty ()) { - typename LIST_TYPE::element_type_t *current = list->list->RemoveHead (); - if (callback) - callback (reinterpret_cast(current->GetValue ())); - delete current; - } - delete list->list; - } - list->list = NULL; -} - -template -static -inline -void -_rt_coreclr_list_clear ( - LIST_TYPE *list, - void (*callback)(void *)) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - - while (!list->list->IsEmpty ()) { - typename LIST_TYPE::element_type_t *current = list->list->RemoveHead (); - if (callback) - callback (reinterpret_cast(current->GetValue ())); - delete current; - } -} - -template -static -inline -bool -_rt_coreclr_list_append ( - LIST_TYPE *list, - LIST_ITEM item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - - typename LIST_TYPE::element_type_t *node = new (nothrow) typename LIST_TYPE::element_type_t (item); - if (node) - list->list->InsertTail (node); - return (node != NULL); -} - -template -static -inline -void -_rt_coreclr_list_remove ( - LIST_TYPE *list, - CONST_LIST_ITEM item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - - typename LIST_TYPE::element_type_t *current = list->list->GetHead (); - while (current) { - if (current->GetValue () == item) { - if (list->list->FindAndRemove (current)) - delete current; - break; - } - current = list->list->GetNext (current); - } -} - -template -static -inline -bool -_rt_coreclr_list_find ( - CONST_LIST_TYPE *list, - CONST_LIST_ITEM item_to_find, - LIST_ITEM *found_item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - EP_ASSERT (found_item != NULL); - - bool found = false; - typename LIST_TYPE::element_type_t *current = list->list->GetHead (); - while (current) { - if (current->GetValue () == item_to_find) { - *found_item = current->GetValue (); - found = true; - break; - } - current = list->list->GetNext (current); - } - return found; -} - -template -static -inline -bool -_rt_coreclr_list_is_empty (CONST_LIST_TYPE *list) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL); - - return (list->list == NULL || list->list->IsEmpty ()); -} - -template -static -inline -bool -_rt_coreclr_list_is_valid (CONST_LIST_TYPE *list) -{ - STATIC_CONTRACT_NOTHROW; - return (list != NULL && list->list != NULL); -} - -template -static -inline -ITERATOR_TYPE -_rt_coreclr_list_iterator_begin (CONST_LIST_TYPE *list) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL); - - return list->list->begin (); -} - -template -static -inline -bool -_rt_coreclr_list_iterator_end ( - CONST_LIST_TYPE *list, - CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (list != NULL && list->list != NULL && iterator != NULL); - - return (*iterator == list->list->end ()); -} - -template -static -inline -void -_rt_coreclr_list_iterator_next (ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL); - - (*iterator)++; -} - -template -static -inline -ITEM_TYPE -_rt_coreclr_list_iterator_value (CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL); - - return const_cast(iterator)->operator*(); -} - -template -static -inline -void -_rt_coreclr_queue_alloc (QUEUE_TYPE *queue) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL); - - queue->queue = new (nothrow) typename QUEUE_TYPE::queue_type_t (); -} - -template -static -inline -void -_rt_coreclr_queue_free (QUEUE_TYPE *queue) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL); - - if (queue->queue) - delete queue->queue; - queue->queue = NULL; -} - -template -static -inline -bool -_rt_coreclr_queue_pop_head ( - QUEUE_TYPE *queue, - ITEM_TYPE *item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL && queue->queue != NULL && item != NULL); - - bool found = true; - typename QUEUE_TYPE::element_type_t *node = queue->queue->RemoveHead (); - if (node) { - *item = node->m_Value; - delete node; - } else { - *item = NULL; - found = false; - } - return found; -} - -template -static -inline -bool -_rt_coreclr_queue_push_head ( - QUEUE_TYPE *queue, - ITEM_TYPE item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL && queue->queue != NULL); - - typename QUEUE_TYPE::element_type_t *node = new (nothrow) typename QUEUE_TYPE::element_type_t (item); - if (node) - queue->queue->InsertHead (node); - return (node != NULL); -} - -template -static -inline -bool -_rt_coreclr_queue_push_tail ( - QUEUE_TYPE *queue, - ITEM_TYPE item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL && queue->queue != NULL); - - typename QUEUE_TYPE::element_type_t *node = new (nothrow) typename QUEUE_TYPE::element_type_t (item); - if (node) - queue->queue->InsertTail (node); - return (node != NULL); -} - -template -static -inline -bool -_rt_coreclr_queue_is_empty (CONST_QUEUE_TYPE *queue) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (queue != NULL && queue->queue != NULL); - - return (queue->queue != NULL && queue->queue->IsEmpty ()); -} - -template -static -inline -bool -_rt_coreclr_queue_is_valid (CONST_QUEUE_TYPE *queue) -{ - STATIC_CONTRACT_NOTHROW; - return (queue != NULL && queue->queue != NULL); -} - -template -static -inline -void -_rt_coreclr_array_alloc (ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL); - - ep_array->array = new (nothrow) typename ARRAY_TYPE::array_type_t (); -} - -template -static -inline -void -_rt_coreclr_array_alloc_capacity ( - ARRAY_TYPE *ep_array, - size_t capacity) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL); - - ep_array->array = new (nothrow) typename ARRAY_TYPE::array_type_t (); - if (ep_array->array) - ep_array->array->AllocNoThrow (capacity); -} - -template -static -inline -void -_rt_coreclr_array_init_capacity ( - ARRAY_TYPE *ep_array, - size_t capacity) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL); - - if (ep_array->array) - ep_array->array->AllocNoThrow (capacity); -} - -template -static -inline -void -_rt_coreclr_array_free (ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL); - - if (ep_array->array) { - delete ep_array->array; - ep_array->array = NULL; - } -} - -template -static -inline -bool -_rt_coreclr_array_append ( - ARRAY_TYPE *ep_array, - ITEM_TYPE item) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - return ep_array->array->PushNoThrow (item); -} - -template -static -inline -void -_rt_coreclr_array_clear (ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - while (ep_array->array->Size () > 0) - ITEM_TYPE item = ep_array->array->Pop (); - ep_array->array->Shrink (); -} - -template -static -inline -size_t -_rt_coreclr_array_size (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - return ep_array->array->Size (); -} - -template -static -inline -ITEM_TYPE * -_rt_coreclr_array_data (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - return ep_array->array->Ptr (); -} - -template -static -inline -bool -_rt_coreclr_array_is_valid (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - return (ep_array->array != NULL); -} - -template -static -inline -ITERATOR_TYPE -_rt_coreclr_array_iterator_begin (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - ITERATOR_TYPE temp; - temp.array = ep_array->array; - temp.index = 0; - return temp; -} - -template -static -inline -bool -_rt_coreclr_array_iterator_end ( - CONST_ARRAY_TYPE *ep_array, - CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && iterator != NULL && iterator->array != NULL); - - return (iterator->index >= static_cast(iterator->array->Size ())); -} - -template -static -inline -void -_rt_coreclr_array_iterator_next (ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL); - - iterator->index++; -} - -template -static -inline -ITEM_TYPE -_rt_coreclr_array_iterator_value (const CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL && iterator->array != NULL); - EP_ASSERT (iterator->index < static_cast(iterator->array->Size ())); - - return iterator->array->operator[] (iterator->index); -} - -template -static -inline -ITERATOR_TYPE -_rt_coreclr_array_reverse_iterator_begin (CONST_ARRAY_TYPE *ep_array) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && ep_array->array != NULL); - - ITERATOR_TYPE temp; - temp.array = ep_array->array; - temp.index = static_cast(ep_array->array->Size ()); - return temp; -} - -template -static -inline -bool -_rt_coreclr_array_reverse_iterator_end ( - CONST_ARRAY_TYPE *ep_array, - CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (ep_array != NULL && iterator != NULL && iterator->array != NULL); - - return (iterator->index == 0); -} - -template -static -inline -void -_rt_coreclr_array_reverse_iterator_next (ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL); - - iterator->index--; -} - -template -static -inline -ITEM_TYPE -_rt_coreclr_array_reverse_iterator_value (CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (iterator != NULL && iterator->array != NULL); - EP_ASSERT (iterator->index > 0); - - return iterator->array->operator[] (iterator->index - 1); -} - -template -static -inline -void -_rt_coreclr_hash_map_alloc ( - HASH_MAP_TYPE *hash_map, - uint32_t (*hash_callback)(const void *), - bool (*eq_callback)(const void *, const void *), - void (*key_free_callback)(void *), - void (*value_free_callback)(void *)) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && key_free_callback == NULL); - - hash_map->table = new (nothrow) typename HASH_MAP_TYPE::table_type_t (); - hash_map->callbacks.key_free_func = key_free_callback; - hash_map->callbacks.value_free_func = value_free_callback; -} - -template -static -inline -void -_rt_coreclr_hash_map_free (HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL); - - if (hash_map->table) { - if (hash_map->callbacks.value_free_func) { - for (typename HASH_MAP_TYPE::table_type_t::Iterator iterator = hash_map->table->Begin (); iterator != hash_map->table->End (); ++iterator) - hash_map->callbacks.value_free_func (reinterpret_cast((ptrdiff_t)(iterator->Value ()))); - } - delete hash_map->table; - } -} - -template -static -inline -bool -_rt_coreclr_hash_map_add ( - HASH_MAP_TYPE *hash_map, - KEY_TYPE key, - VALUE_TYPE value) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - return hash_map->table->AddNoThrow (typename HASH_MAP_TYPE::table_type_t::element_t (key, value)); -} - -template -static -inline -bool -_rt_coreclr_hash_map_add_or_replace ( - HASH_MAP_TYPE *hash_map, - KEY_TYPE key, - VALUE_TYPE value) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - return hash_map->table->AddOrReplaceNoThrow (typename HASH_MAP_TYPE::table_type_t::element_t (key, value)); -} - -template -static -inline -void -_rt_coreclr_hash_map_remove_all (HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - if (hash_map->callbacks.value_free_func) { - for (typename HASH_MAP_TYPE::table_type_t::Iterator iterator = hash_map->table->Begin (); iterator != hash_map->table->End (); ++iterator) - hash_map->callbacks.value_free_func (reinterpret_cast((ptrdiff_t)(iterator->Value ()))); - } - hash_map->table->RemoveAll (); -} - -template -static -inline -bool -_rt_coreclr_hash_map_lookup ( - CONST_HASH_MAP_TYPE *hash_map, - CONST_KEY_TYPE key, - VALUE_TYPE *value) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - const typename HASH_MAP_TYPE::table_type_t::element_t *ret = hash_map->table->LookupPtr ((KEY_TYPE)key); - if (ret == NULL) - return false; - *value = ret->Value (); - return true; -} - -template -static -inline -uint32_t -_rt_coreclr_hash_map_count (CONST_HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - return hash_map->table->GetCount (); -} - -template -static -inline -bool -_rt_coreclr_hash_map_is_valid (CONST_HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - - return (hash_map != NULL && hash_map->table != NULL); -} - -template -static -inline -void -_rt_coreclr_hash_map_remove ( - HASH_MAP_TYPE *hash_map, - CONST_KEY_TYPE key) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - const typename HASH_MAP_TYPE::table_type_t::element_t *ret = NULL; - if (hash_map->callbacks.value_free_func) - ret = hash_map->table->LookupPtr ((KEY_TYPE)key); - hash_map->table->Remove ((KEY_TYPE)key); - if (ret) - hash_map->callbacks.value_free_func (reinterpret_cast(static_cast(ret->Value ()))); -} - -template -static -inline -ITERATOR_TYPE -_rt_coreclr_hash_map_iterator_begin (CONST_HASH_MAP_TYPE *hash_map) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL); - - return hash_map->table->Begin (); -} - -template -static -inline -bool -_rt_coreclr_hash_map_iterator_end ( - CONST_HASH_MAP_TYPE *hash_map, - CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (hash_map != NULL && hash_map->table != NULL && iterator != NULL); - - return (hash_map->table->End () == *iterator); -} - -template -static -inline -void -_rt_coreclr_hash_map_iterator_next (ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (iterator != NULL); - - (*iterator)++; -} - -template -static -inline -KEY_TYPE -_rt_coreclr_hash_map_iterator_key (CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (iterator != NULL); - - return (*iterator)->Key (); -} - -template -static -inline -VALUE_TYPE -_rt_coreclr_hash_map_iterator_value (CONST_ITERATOR_TYPE *iterator) -{ - STATIC_CONTRACT_NOTHROW; - EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow); - EP_ASSERT (iterator != NULL); - - return (*iterator)->Value (); -} - -#define EP_RT_DEFINE_LIST_PREFIX(prefix_name, list_name, list_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, alloc) (list_type *list) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_list_alloc(list); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, free) (list_type *list, void (*callback)(void *)) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_list_free(list, callback); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, clear) (list_type *list, void (*callback)(void *)) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_list_clear(list, callback); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, append) (list_type *list, item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_list_append(list, item); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, remove) (list_type *list, const item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_list_remove(list, item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, find) (const list_type *list, const item_type item_to_find, item_type *found_item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_list_find(list, item_to_find, found_item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_empty) (const list_type *list) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_list_is_empty(list); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_valid) (const list_type *list) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_list_is_valid(list); \ - } - -#undef EP_RT_DEFINE_LIST -#define EP_RT_DEFINE_LIST(list_name, list_type, item_type) \ - EP_RT_DEFINE_LIST_PREFIX(ep, list_name, list_type, item_type) - -#define EP_RT_DEFINE_LIST_ITERATOR_PREFIX(prefix_name, list_name, list_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_begin) (const list_type *list) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_list_iterator_begin(list); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_end) (const list_type *list, const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_list_iterator_end(list, iterator); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_next) (iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_list_iterator_next(iterator); \ - } \ - static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_value) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_list_iterator_value(iterator); \ - } - -#undef EP_RT_DEFINE_LIST_ITERATOR -#define EP_RT_DEFINE_LIST_ITERATOR(list_name, list_type, iterator_type, item_type) \ - EP_RT_DEFINE_LIST_ITERATOR_PREFIX(ep, list_name, list_type, iterator_type, item_type) - -#define EP_RT_DEFINE_QUEUE_PREFIX(prefix_name, queue_name, queue_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, alloc) (queue_type *queue) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_queue_alloc(queue); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, free) (queue_type *queue) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_queue_free(queue); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, pop_head) (queue_type *queue, item_type *item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_queue_pop_head(queue, item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_head) (queue_type *queue, item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_queue_push_head(queue, item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_tail) (queue_type *queue, item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_queue_push_tail(queue, item); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_empty) (const queue_type *queue) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_queue_is_empty(queue); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_valid) (const queue_type *queue) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_queue_is_valid(queue); \ - } - -#undef EP_RT_DEFINE_QUEUE -#define EP_RT_DEFINE_QUEUE(queue_name, queue_type, item_type) \ - EP_RT_DEFINE_QUEUE_PREFIX(ep, queue_name, queue_type, item_type) - -#define EP_RT_DEFINE_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc) (array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_array_alloc(ep_array); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc_capacity) (array_type *ep_array, size_t capacity) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_array_alloc_capacity(ep_array, capacity); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, free) (array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_array_free(ep_array); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, append) (array_type *ep_array, item_type item) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_append (ep_array, item); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, clear) (array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_array_clear (ep_array); \ - } \ - static inline size_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, size) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_size (ep_array); \ - } \ - static inline item_type * EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, data) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_data (ep_array); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, is_valid) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_is_valid (ep_array); \ - } - -#define EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init) (array_type *ep_array) { \ - STATIC_CONTRACT_NOTHROW; \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init_capacity) (array_type *ep_array, size_t capacity) { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_array_init_capacity(ep_array, capacity); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, fini) (array_type *ep_array) { \ - STATIC_CONTRACT_NOTHROW; \ - } - -#undef EP_RT_DEFINE_ARRAY -#define EP_RT_DEFINE_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#undef EP_RT_DEFINE_LOCAL_ARRAY -#define EP_RT_DEFINE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, var_type) \ - var_type::array_type_t _local_ ##var_name; \ - var_type var_name; \ - var_name.array = &_local_ ##var_name - -#define EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_begin) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_iterator_begin (ep_array); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_end) (const array_type *ep_array, const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_iterator_end (ep_array, iterator); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_next) (iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_array_iterator_next (iterator); \ - } \ - static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_value) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_iterator_value (iterator); \ - } - -#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_begin) (const array_type *ep_array) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_reverse_iterator_begin (ep_array); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_end) (const array_type *ep_array, const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_reverse_iterator_end (ep_array, iterator); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_next) (iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_array_reverse_iterator_next (iterator); \ - } \ - static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_value) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_array_reverse_iterator_value (iterator); \ - } - -#undef EP_RT_DEFINE_ARRAY_ITERATOR -#define EP_RT_DEFINE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#undef EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR -#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, alloc) (hash_map_type *hash_map, uint32_t (*hash_callback)(const void *), bool (*eq_callback)(const void *, const void *), void (*key_free_callback)(void *), void (*value_free_callback)(void *)) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_hash_map_alloc(hash_map, hash_callback, eq_callback, key_free_callback, value_free_callback); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, free) (hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_hash_map_free(hash_map); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add) (hash_map_type *hash_map, key_type key, value_type value) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_add(hash_map, key, value); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove_all) (hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_hash_map_remove_all(hash_map); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, lookup) (const hash_map_type *hash_map, const key_type key, value_type *value) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_lookup(hash_map, key, value); \ - } \ - static inline uint32_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, count) (const hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_count(hash_map); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, is_valid) (const hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_is_valid(hash_map); \ - } - -#define EP_RT_DEFINE_HASH_MAP_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add_or_replace) (hash_map_type *hash_map, key_type key, value_type value) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_add_or_replace(hash_map, key, value); \ - } \ - -#define EP_RT_DEFINE_HASH_MAP_REMOVE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove) (hash_map_type *hash_map, const key_type key) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_hash_map_remove(hash_map, key); \ - } - -#undef EP_RT_DEFINE_HASH_MAP -#define EP_RT_DEFINE_HASH_MAP(hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type) - -#undef EP_RT_DEFINE_HASH_MAP_REMOVE -#define EP_RT_DEFINE_HASH_MAP_REMOVE(hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_REMOVE_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type) - -#define EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(prefix_name, hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_begin) (const hash_map_type *hash_map) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_iterator_begin(hash_map); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_end) (const hash_map_type *hash_map, const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_iterator_end(hash_map, iterator); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_next) (iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - _rt_coreclr_hash_map_iterator_next(iterator); \ - } \ - static inline key_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_key) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_iterator_key(iterator); \ - } \ - static inline value_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_value) (const iterator_type *iterator) \ - { \ - STATIC_CONTRACT_NOTHROW; \ - return _rt_coreclr_hash_map_iterator_value(iterator); \ - } - -#undef EP_RT_DEFINE_HASH_MAP_ITERATOR -#define EP_RT_DEFINE_HASH_MAP_ITERATOR(hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(ep, hash_map_name, hash_map_type, iterator_type, key_type, value_type) - static inline ep_rt_lock_handle_t * @@ -1319,12 +247,6 @@ ep_rt_atomic_compare_exchange_utf8_string (ep_char8_t *volatile *target, ep_char * EventPipe. */ -EP_RT_DEFINE_ARRAY (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID) -EP_RT_DEFINE_ARRAY_ITERATOR (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID) - -EP_RT_DEFINE_ARRAY (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *) -EP_RT_DEFINE_ARRAY_ITERATOR (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *) - static void ep_rt_init (void) @@ -1566,84 +488,9 @@ ep_rt_provider_invoke_callback ( } /* - * EventPipeBuffer. - */ - -EP_RT_DEFINE_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) -EP_RT_DEFINE_LOCAL_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) -EP_RT_DEFINE_ARRAY_ITERATOR (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) - -#undef EP_RT_DECLARE_LOCAL_BUFFER_ARRAY -#define EP_RT_DECLARE_LOCAL_BUFFER_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_buffer_array_t) - -/* - * EventPipeBufferList. - */ - -EP_RT_DEFINE_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) -EP_RT_DEFINE_LOCAL_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) -EP_RT_DEFINE_ARRAY_ITERATOR (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) - -#undef EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY -#define EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_buffer_list_array_t) - -/* - * EventPipeEvent. - */ - -EP_RT_DEFINE_LIST (event_list, ep_rt_event_list_t, EventPipeEvent *) -EP_RT_DEFINE_LIST_ITERATOR (event_list, ep_rt_event_list_t, ep_rt_event_list_iterator_t, EventPipeEvent *) - -/* - * EventPipeFile. - */ - -EP_RT_DEFINE_HASH_MAP_REMOVE(metadata_labels_hash, ep_rt_metadata_labels_hash_map_t, EventPipeEvent *, uint32_t) -EP_RT_DEFINE_HASH_MAP(stack_hash, ep_rt_stack_hash_map_t, StackHashKey *, StackHashEntry *) -EP_RT_DEFINE_HASH_MAP_ITERATOR(stack_hash, ep_rt_stack_hash_map_t, ep_rt_stack_hash_map_iterator_t, StackHashKey *, StackHashEntry *) - -/* - * EventPipeProvider. - */ - -EP_RT_DEFINE_LIST (provider_list, ep_rt_provider_list_t, EventPipeProvider *) -EP_RT_DEFINE_LIST_ITERATOR (provider_list, ep_rt_provider_list_t, ep_rt_provider_list_iterator_t, EventPipeProvider *) - -EP_RT_DEFINE_QUEUE (provider_callback_data_queue, ep_rt_provider_callback_data_queue_t, EventPipeProviderCallbackData *) - -static -EventPipeProvider * -ep_rt_provider_list_find_by_name ( - const ep_rt_provider_list_t *list, - const ep_char8_t *name) -{ - STATIC_CONTRACT_NOTHROW; - - // The provider list should be non-NULL, but can be NULL on shutdown. - if (list) { - SList> *provider_list = list->list; - SListElem *element = provider_list->GetHead (); - while (element) { - EventPipeProvider *provider = element->GetValue (); - if (ep_rt_utf8_string_compare (ep_provider_get_provider_name (element->GetValue ()), name) == 0) - return provider; - - element = provider_list->GetNext (element); - } - } - - return NULL; -} - -/* * EventPipeProviderConfiguration. */ -EP_RT_DEFINE_ARRAY (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration) -EP_RT_DEFINE_ARRAY_ITERATOR (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration) - static inline bool @@ -1733,73 +580,6 @@ ep_rt_notify_profiler_provider_created (EventPipeProvider *provider) } /* - * EventPipeSessionProvider. - */ - -EP_RT_DEFINE_LIST (session_provider_list, ep_rt_session_provider_list_t, EventPipeSessionProvider *) -EP_RT_DEFINE_LIST_ITERATOR (session_provider_list, ep_rt_session_provider_list_t, ep_rt_session_provider_list_iterator_t, EventPipeSessionProvider *) - -static -EventPipeSessionProvider * -ep_rt_session_provider_list_find_by_name ( - const ep_rt_session_provider_list_t *list, - const ep_char8_t *name) -{ - STATIC_CONTRACT_NOTHROW; - - SList> *provider_list = list->list; - EventPipeSessionProvider *session_provider = NULL; - SListElem *element = provider_list->GetHead (); - while (element) { - EventPipeSessionProvider *candidate = element->GetValue (); - if (ep_rt_utf8_string_compare (ep_session_provider_get_provider_name (candidate), name) == 0) { - session_provider = candidate; - break; - } - element = provider_list->GetNext (element); - } - - return session_provider; -} - -/* - * EventPipeSequencePoint. - */ - -EP_RT_DEFINE_LIST (sequence_point_list, ep_rt_sequence_point_list_t, EventPipeSequencePoint *) -EP_RT_DEFINE_LIST_ITERATOR (sequence_point_list, ep_rt_sequence_point_list_t, ep_rt_sequence_point_list_iterator_t, EventPipeSequencePoint *) - -/* - * EventPipeThread. - */ - -EP_RT_DEFINE_LIST (thread_list, ep_rt_thread_list_t, EventPipeThread *) -EP_RT_DEFINE_LIST_ITERATOR (thread_list, ep_rt_thread_list_t, ep_rt_thread_list_iterator_t, EventPipeThread *) - -EP_RT_DEFINE_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) -EP_RT_DEFINE_LOCAL_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) -EP_RT_DEFINE_ARRAY_ITERATOR (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) - -#undef EP_RT_DECLARE_LOCAL_THREAD_ARRAY -#define EP_RT_DECLARE_LOCAL_THREAD_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_thread_array_t) - -/* - * EventPipeThreadSessionState. - */ - -EP_RT_DEFINE_LIST (thread_session_state_list, ep_rt_thread_session_state_list_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_LIST_ITERATOR (thread_session_state_list, ep_rt_thread_session_state_list_t, ep_rt_thread_session_state_list_iterator_t, EventPipeThreadSessionState *) - -EP_RT_DEFINE_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_LOCAL_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_ARRAY_ITERATOR (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) - -#undef EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY -#define EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY(var_name) \ - EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_thread_session_state_array_t) - -/* * Arrays. */ @@ -1982,7 +762,7 @@ ep_rt_is_running (void) static inline void -ep_rt_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints) +ep_rt_execute_rundown (dn_vector_ptr_t *execution_checkpoints) { STATIC_CONTRACT_NOTHROW; @@ -2348,12 +1128,9 @@ ep_rt_temp_path_get ( return 0; } -EP_RT_DEFINE_ARRAY (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *) -EP_RT_DEFINE_ARRAY_ITERATOR (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *) - static void -ep_rt_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array) +ep_rt_os_environment_get_utf16 (dn_vector_ptr_t *env_array) { STATIC_CONTRACT_NOTHROW; EP_ASSERT (env_array != NULL); @@ -2362,7 +1139,7 @@ ep_rt_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array) if (envs) { LPWSTR next = envs; while (*next) { - ep_rt_env_array_utf16_append (env_array, ep_rt_utf16_string_dup (reinterpret_cast(next))); + dn_vector_ptr_push_back (env_array, ep_rt_utf16_string_dup (reinterpret_cast(next))); next += ep_rt_utf16_string_len (reinterpret_cast(next)) + 1; } FreeEnvironmentStringsW (envs); @@ -2853,6 +1630,7 @@ thread_holder_free_func (EventPipeThreadHolder * thread_holder) class EventPipeCoreCLRThreadHolderTLS { public: EventPipeCoreCLRThreadHolderTLS () + : m_threadHolder (NULL) { STATIC_CONTRACT_NOTHROW; } @@ -3026,13 +1804,6 @@ ep_rt_thread_set_activity_id ( #define EP_YIELD_WHILE(condition) YIELD_WHILE(condition) /* - * ThreadSequenceNumberMap. - */ - -EP_RT_DEFINE_HASH_MAP_REMOVE(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, EventPipeThreadSessionState *, uint32_t) -EP_RT_DEFINE_HASH_MAP_ITERATOR(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, ep_rt_thread_sequence_number_hash_map_iterator_t, EventPipeThreadSessionState *, uint32_t) - -/* * Volatile. */ diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-types-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ep-rt-types-coreclr.h index 8f22d43..9661e9a 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-types-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-types-coreclr.h @@ -8,7 +8,6 @@ #include #ifdef ENABLE_PERFTRACING -#include "slist.h" #ifdef DEBUG #define EP_CHECKED_BUILD @@ -30,97 +29,6 @@ #undef EP_UNLIKELY #define EP_UNLIKELY(expr) expr -template -struct _rt_coreclr_list_internal_t { - typedef struct SListElem element_type_t; - typedef class SList list_type_t; - list_type_t *list; -}; - -template -struct _rt_coreclr_queue_internal_t { - typedef struct SListElem element_type_t; - typedef class SList queue_type_t; - queue_type_t *queue; -}; - -template -struct _rt_coreclr_array_internal_t { - typedef T element_type_t; - typedef class CQuickArrayList array_type_t; - array_type_t *array; -}; - -template -struct _rt_coreclr_array_iterator_internal_t { - typedef typename _rt_coreclr_array_internal_t::array_type_t array_iterator_type; - array_iterator_type *array; - size_t index; -}; - -typedef struct _rt_coreclr_table_callbacks_t { - void (*key_free_func)(void *); - void (*value_free_func)(void *); -} rt_coreclr_table_callbacks_t; - -template -struct _rt_coreclr_table_default_internal_t { - typedef class SHash > > table_type_t; - rt_coreclr_table_callbacks_t callbacks; - table_type_t *table; -}; - -template -struct _rt_coreclr_table_remove_internal_t { - typedef class SHash< MapSHashTraits > table_type_t; - rt_coreclr_table_callbacks_t callbacks; - table_type_t *table; -}; - -class EventPipeCoreCLRStackHashTraits : public NoRemoveSHashTraits< MapSHashTraits > -{ -public: - typedef typename MapSHashTraits::element_t element_t; - typedef typename MapSHashTraits::count_t count_t; - - typedef StackHashKey * key_t; - - static key_t GetKey (element_t e) - { - extern StackHashKey * ep_stack_hash_entry_get_key (StackHashEntry *); - return ep_stack_hash_entry_get_key (e.Value ()); - } - - static BOOL Equals (key_t k1, key_t k2) - { - extern bool ep_stack_hash_key_equal (const void *, const void *); - return ep_stack_hash_key_equal (k1, k2); - } - - static count_t Hash (key_t k) - { - extern uint32_t ep_stack_hash_key_hash (const void *); - return (count_t)ep_stack_hash_key_hash (k); - } - - static element_t Null () - { - return element_t (NULL, NULL); - } - - static bool IsNull (const element_t &e) - { - return (e.Key () == NULL|| e.Value () == NULL); - } -}; - -template -struct _rt_coreclr_table_custom_internal_t { - typedef class SHash table_type_t; - rt_coreclr_table_callbacks_t callbacks; - table_type_t *table; -}; - class CLREventStatic; struct _rt_coreclr_event_internal_t { CLREventStatic *event; @@ -137,155 +45,16 @@ struct _rt_coreclr_spin_lock_internal_t { }; /* - * EventPipeBuffer. - */ - -#undef ep_rt_buffer_array_t -typedef struct _rt_coreclr_array_internal_t ep_rt_buffer_array_t; - -#undef ep_rt_buffer_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ep_rt_buffer_array_iterator_t; - -/* - * EventPipeBufferList. - */ - -#undef ep_rt_buffer_list_array_t -typedef struct _rt_coreclr_array_internal_t ep_rt_buffer_list_array_t; - -#undef ep_rt_buffer_list_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ep_rt_buffer_list_array_iterator_t; - -/* - * EventPipeEvent. - */ - -#undef ep_rt_event_list_t -typedef struct _rt_coreclr_list_internal_t ep_rt_event_list_t; - -#undef ep_rt_event_list_iterator_t -typedef class _rt_coreclr_list_internal_t::list_type_t::Iterator ep_rt_event_list_iterator_t; - -/* - * EventPipeFile. - */ - -#undef ep_rt_metadata_labels_hash_map_t -typedef struct _rt_coreclr_table_remove_internal_t ep_rt_metadata_labels_hash_map_t; - -#undef ep_rt_metadata_labels_hash_map_iterator_t -typedef class _rt_coreclr_table_remove_internal_t::table_type_t::Iterator ep_rt_metadata_labels_hash_map_iterator_t; - -#undef ep_rt_stack_hash_map_t -typedef struct _rt_coreclr_table_custom_internal_t ep_rt_stack_hash_map_t; - -#undef ep_rt_stack_hash_map_iterator_t -typedef class _rt_coreclr_table_custom_internal_t::table_type_t::Iterator ep_rt_stack_hash_map_iterator_t; - -/* - * EventPipeProvider. - */ - -#undef ep_rt_provider_list_t -typedef struct _rt_coreclr_list_internal_t ep_rt_provider_list_t; - -#undef ep_rt_provider_list_iterator_t -typedef class _rt_coreclr_list_internal_t::list_type_t::Iterator ep_rt_provider_list_iterator_t; - -#undef ep_rt_provider_callback_data_queue_t -typedef struct _rt_coreclr_queue_internal_t ep_rt_provider_callback_data_queue_t; - -/* - * EventPipeProviderConfiguration. - */ - -#undef ep_rt_provider_config_array_t -typedef struct _rt_coreclr_array_internal_t ep_rt_provider_config_array_t; - -#undef ep_rt_provider_config_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ep_rt_provider_config_array_iterator_t; - -/* - * EventPipeSessionProvider. - */ - -#undef ep_rt_session_provider_list_t -typedef struct _rt_coreclr_list_internal_t ep_rt_session_provider_list_t; - -#undef ep_rt_session_provider_list_iterator_t -typedef class _rt_coreclr_list_internal_t::list_type_t::Iterator ep_rt_session_provider_list_iterator_t; - -/* - * EventPipeSequencePoint. - */ - -#undef ep_rt_sequence_point_list_t -typedef struct _rt_coreclr_list_internal_t ep_rt_sequence_point_list_t; - -#undef ep_rt_sequence_point_list_iterator_t -typedef class _rt_coreclr_list_internal_t::list_type_t::Iterator ep_rt_sequence_point_list_iterator_t; - -/* - * EventPipeThread. - */ - -#undef ep_rt_thread_list_t -typedef struct _rt_coreclr_list_internal_t ep_rt_thread_list_t; - -#undef ep_rt_thread_list_iterator_t -typedef class _rt_coreclr_list_internal_t::list_type_t::Iterator ep_rt_thread_list_iterator_t; - -#undef ep_rt_thread_array_t -typedef struct _rt_coreclr_array_internal_t ep_rt_thread_array_t; - -#undef ep_rt_thread_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ep_rt_thread_array_iterator_t; - -/* - * EventPipeThreadSessionState. - */ - -#undef ep_rt_thread_session_state_list_t -typedef struct _rt_coreclr_list_internal_t ep_rt_thread_session_state_list_t; - -#undef ep_rt_thread_session_state_list_iterator_t -typedef class _rt_coreclr_list_internal_t::list_type_t::Iterator ep_rt_thread_session_state_list_iterator_t; - -#undef ep_rt_thread_session_state_array_t -typedef struct _rt_coreclr_array_internal_t ep_rt_thread_session_state_array_t; - -#undef ep_rt_thread_session_state_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ep_rt_thread_session_state_array_iterator_t; - -/* * EventPipe. */ -#undef ep_rt_session_id_array_t -typedef struct _rt_coreclr_array_internal_t ep_rt_session_id_array_t; - -#undef ep_rt_session_id_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ep_rt_session_id_array_iterator_t; - #undef ep_rt_method_desc_t typedef class MethodDesc ep_rt_method_desc_t; -#undef ep_rt_execution_checkpoint_array_t -typedef struct _rt_coreclr_array_internal_t ep_rt_execution_checkpoint_array_t; - -#undef ep_rt_execution_checkpoint_array_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ep_rt_execution_checkpoint_array_iterator_t; - /* * PAL. */ -#undef ep_rt_env_array_utf16_t -typedef struct _rt_coreclr_array_internal_t ep_rt_env_array_utf16_t; - -#undef ep_rt_env_array_utf16_iterator_t -typedef struct _rt_coreclr_array_iterator_internal_t ep_rt_env_array_utf16_iterator_t; - #undef ep_rt_file_handle_t typedef class CFileStream * ep_rt_file_handle_t; @@ -329,15 +98,5 @@ typedef struct _rt_coreclr_thread_params_t { void *thread_params; } ep_rt_thread_params_t; -/* - * ThreadSequenceNumberMap. - */ - -#undef ep_rt_thread_sequence_number_hash_map_t -typedef struct _rt_coreclr_table_remove_internal_t ep_rt_thread_sequence_number_hash_map_t; - -#undef ep_rt_thread_sequence_number_hash_map_iterator_t -typedef class _rt_coreclr_table_remove_internal_t::table_type_t::Iterator ep_rt_thread_sequence_number_hash_map_iterator_t; - #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_RT_TYPES_CORECLR_H__ */ diff --git a/src/mono/mono/component/CMakeLists.txt b/src/mono/mono/component/CMakeLists.txt index 5516122..8a8964e 100644 --- a/src/mono/mono/component/CMakeLists.txt +++ b/src/mono/mono/component/CMakeLists.txt @@ -1,4 +1,5 @@ set(MONO_COMPONENT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../component") +set(SHARED_CONTAINERS_SOURCE_PATH "${CLR_SRC_NATIVE_DIR}/containers/") set(SHARED_EVENTPIPE_SOURCE_PATH "${CLR_SRC_NATIVE_DIR}/eventpipe/") set(MONO_EVENTPIPE_SHIM_SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../eventpipe/") set(MONO_EVENTPIPE_GEN_INCLUDE_PATH "${CMAKE_CURRENT_BINARY_DIR}/eventpipe") @@ -59,7 +60,7 @@ list(APPEND components ${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME} ) -include(${MONO_EVENTPIPE_SHIM_SOURCE_PATH}/CMakeLists.txt) +include(${MONO_EVENTPIPE_SHIM_SOURCE_PATH}/eventpipe.cmake) include_directories( ${MONO_EVENTPIPE_SHIM_SOURCE_PATH} @@ -67,6 +68,7 @@ include_directories( ) set(${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-sources + ${container_sources} ${eventpipe_sources} ${diagnostic_server_sources} ${MONO_COMPONENT_PATH}/event_pipe.c diff --git a/src/mono/mono/eglib/test/test.c b/src/mono/mono/eglib/test/test.c index d614e4e..f9947d7 100644 --- a/src/mono/mono/eglib/test/test.c +++ b/src/mono/mono/eglib/test/test.c @@ -67,7 +67,7 @@ run_group(const Group *group, gint iterations, gboolean quiet, gboolean time, const char *tests_to_run_s) { Test *tests = group->handler(); - gint i, j, passed = 0, total = 0; + gint passed = 0, total = 0; gdouble start_time_group, start_time_test; gchar **tests_to_run = NULL; @@ -85,15 +85,14 @@ run_group(const Group *group, gint iterations, gboolean quiet, start_time_group = get_timestamp(); - for(i = 0; tests[i].name != NULL; i++) { + for(gint i = 0; tests[i].name != NULL; i++) { gchar *result = (char*)""; gboolean iter_pass, run; iter_pass = FALSE; if(tests_to_run != NULL) { - gint j; run = FALSE; - for(j = 0; tests_to_run[j] != NULL; j++) { + for(gint j = 0; tests_to_run[j] != NULL; j++) { if(strcmp(tests_to_run[j], tests[i].name) == 0) { run = TRUE; break; @@ -115,7 +114,7 @@ run_group(const Group *group, gint iterations, gboolean quiet, start_time_test = get_timestamp(); - for(j = 0; j < iterations; j++) { + for(gint j = 0; j < iterations; j++) { iter_pass = run_test(&(tests[i]), &result); if(!iter_pass) { break; diff --git a/src/mono/mono/eventpipe/ds-rt-mono.h b/src/mono/mono/eventpipe/ds-rt-mono.h index e951ca1..2bde834 100644 --- a/src/mono/mono/eventpipe/ds-rt-mono.h +++ b/src/mono/mono/eventpipe/ds-rt-mono.h @@ -64,22 +64,6 @@ MONO_EXIT_GC_SAFE \ MONO_REQ_GC_UNSAFE_MODE -#undef DS_RT_DEFINE_ARRAY -#define DS_RT_DEFINE_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_LOCAL_ARRAY -#define DS_RT_DEFINE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_ARRAY_ITERATOR -#define DS_RT_DEFINE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#undef DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR -#define DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type) - bool ds_rt_mono_transport_get_default_name ( ep_char8_t *name, @@ -201,34 +185,6 @@ ds_rt_transport_get_default_name ( } /* - * DiagnosticsIpcPollHandle. - */ - -DS_RT_DEFINE_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) -DS_RT_DEFINE_LOCAL_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) -DS_RT_DEFINE_ARRAY_ITERATOR (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) - -#undef DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY -#define DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY(var_name) \ - ds_rt_ipc_poll_handle_array_t var_name - -/* - * DiagnosticsPort. - */ - -DS_RT_DEFINE_ARRAY (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *) -DS_RT_DEFINE_ARRAY_ITERATOR (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *) - -DS_RT_DEFINE_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_LOCAL_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_ARRAY_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_reverse_iterator_t, ep_char8_t *) - -#undef DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY -#define DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY(var_name) \ - ds_rt_port_config_array_t var_name - -/* * DiagnosticsProfiler. */ diff --git a/src/mono/mono/eventpipe/ds-rt-types-mono.h b/src/mono/mono/eventpipe/ds-rt-types-mono.h index b13d7f8..f3d4c1a 100644 --- a/src/mono/mono/eventpipe/ds-rt-types-mono.h +++ b/src/mono/mono/eventpipe/ds-rt-types-mono.h @@ -8,34 +8,5 @@ #include #include "ep-rt-types-mono.h" -/* - * DiagnosticsIpcPollHandle. - */ - -#undef ds_rt_ipc_poll_handle_array_t -typedef struct _rt_mono_array_internal_t ds_rt_ipc_poll_handle_array_t; - -#undef ds_rt_ipc_poll_handle_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ds_rt_ipc_poll_handle_array_iterator_t; - -/* - * DiagnosticsPort. - */ - -#undef ds_rt_port_array_t -typedef struct _rt_mono_array_internal_t ds_rt_port_array_t; - -#undef ds_rt_port_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ds_rt_port_array_iterator_t; - -#undef ds_rt_port_config_array_t -typedef struct _rt_mono_array_internal_t ds_rt_port_config_array_t; - -#undef ds_rt_port_config_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ds_rt_port_config_array_iterator_t; - -#undef ds_rt_port_config_array_reverse_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ds_rt_port_config_array_reverse_iterator_t; - #endif /* ENABLE_PERFTRACING */ #endif /* __DIAGNOSTICS_RT_TYPES_MONO_H__ */ diff --git a/src/mono/mono/eventpipe/ep-rt-config-mono.h b/src/mono/mono/eventpipe/ep-rt-config-mono.h index 618cfc6..7b08ff7 100644 --- a/src/mono/mono/eventpipe/ep-rt-config-mono.h +++ b/src/mono/mono/eventpipe/ep-rt-config-mono.h @@ -2,6 +2,5 @@ #define __EVENTPIPE_RT_CONFIG_MONO_H__ #define EP_THREAD_INCLUDE_ACTIVITY_ID -#define EP_RT_USE_CUSTOM_HASH_MAP_CALLBACKS #endif /* __EVENTPIPE_RT_CONFIG_MONO_H__ */ diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c index 2be10d5..7cedd7f 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.c +++ b/src/mono/mono/eventpipe/ep-rt-mono.c @@ -1179,7 +1179,7 @@ int64_t ep_rt_mono_system_timestamp_get (void); void -ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array); +ep_rt_mono_os_environment_get_utf16 (dn_vector_ptr_t *os_env); void ep_rt_mono_init_providers_and_events (void); @@ -1216,7 +1216,7 @@ ep_rt_mono_method_get_full_name ( size_t name_len); void -ep_rt_mono_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints); +ep_rt_mono_execute_rundown (dn_vector_ptr_t *execution_checkpoints); static inline @@ -2620,15 +2620,15 @@ G_END_DECLS #endif /* !defined (HOST_WIN32) */ void -ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array) +ep_rt_mono_os_environment_get_utf16 (dn_vector_ptr_t *os_env) { - EP_ASSERT (env_array != NULL); + EP_ASSERT (os_env != NULL); #ifdef HOST_WIN32 LPWSTR envs = GetEnvironmentStringsW (); if (envs) { LPWSTR next = envs; while (*next) { - ep_rt_env_array_utf16_append (env_array, ep_rt_utf16_string_dup (next)); + dn_vector_ptr_push_back (os_env, ep_rt_utf16_string_dup (next)); next += ep_rt_utf16_string_len (next) + 1; } FreeEnvironmentStringsW (envs); @@ -2636,7 +2636,7 @@ ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array) #else gchar **next = NULL; for (next = environ; *next != NULL; ++next) - ep_rt_env_array_utf16_append (env_array, ep_rt_utf8_to_utf16le_string (*next, -1)); + dn_vector_ptr_push_back (os_env, ep_rt_utf8_to_utf16le_string (*next, -1)); #endif } @@ -2855,7 +2855,7 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads ( } void -ep_rt_mono_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints) +ep_rt_mono_execute_rundown (dn_vector_ptr_t *execution_checkpoints) { ep_char8_t runtime_module_path [256]; const uint8_t object_guid [EP_GUID_SIZE] = { 0 }; @@ -2887,17 +2887,14 @@ ep_rt_mono_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkp NULL); if (execution_checkpoints) { - ep_rt_execution_checkpoint_array_iterator_t execution_checkpoints_iterator = ep_rt_execution_checkpoint_array_iterator_begin (execution_checkpoints); - while (!ep_rt_execution_checkpoint_array_iterator_end (execution_checkpoints, &execution_checkpoints_iterator)) { - EventPipeExecutionCheckpoint *checkpoint = ep_rt_execution_checkpoint_array_iterator_value (&execution_checkpoints_iterator); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeExecutionCheckpoint *, checkpoint, execution_checkpoints) { FireEtwExecutionCheckpointDCEnd ( clr_instance_get_id (), checkpoint->name, checkpoint->timestamp, NULL, NULL); - ep_rt_execution_checkpoint_array_iterator_next (&execution_checkpoints_iterator); - } + } DN_VECTOR_PTR_FOREACH_END; } FireEtwDCEndInit_V1 ( diff --git a/src/mono/mono/eventpipe/ep-rt-mono.h b/src/mono/mono/eventpipe/ep-rt-mono.h index cbc8038..1169b91 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.h +++ b/src/mono/mono/eventpipe/ep-rt-mono.h @@ -45,310 +45,6 @@ #undef EP_ALIGN_UP #define EP_ALIGN_UP(val,align) ALIGN_TO(val,align) -#ifndef EP_RT_BUILD_TYPE_FUNC_NAME -#define EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, type_name, func_name) \ -prefix_name ## _rt_ ## type_name ## _ ## func_name -#endif - -#define EP_RT_DEFINE_LIST_PREFIX(prefix_name, list_name, list_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, alloc) (list_type *list) { ; } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, free) (list_type *list, void (*callback)(void *)) { \ - if (list && list->list) { \ - if (callback) { \ - for (GSList *l = list->list; l; l = l->next) { \ - callback (l->data); \ - } \ - } \ - g_slist_free (list->list); \ - list->list = NULL; \ - } \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, clear) (list_type *list, void (*callback)(void *)) { \ - EP_ASSERT (list != NULL); \ - ep_rt_ ## list_name ## _free (list, callback); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, append) (list_type *list, item_type item) { \ - EP_ASSERT (list != NULL); \ - list->list = g_slist_append (list->list, ((gpointer)(gsize)item)); \ - return list->list != NULL; \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, remove) (list_type *list, const item_type item) { \ - EP_ASSERT (list != NULL); \ - list->list = g_slist_remove (list->list, ((gconstpointer)(const gsize)item)); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, find) (const list_type *list, const item_type item_to_find, item_type *found_item) { \ - EP_ASSERT (list != NULL && found_item != NULL); \ - GSList *found_glist_item = g_slist_find (list->list, ((gconstpointer)(const gsize)item_to_find)); \ - *found_item = (found_glist_item != NULL) ? ((item_type)(gsize)(found_glist_item->data)) : ((item_type)(gsize)NULL); \ - return *found_item != NULL; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_empty) (const list_type *list) { \ - EP_ASSERT (list != NULL); \ - return list->list == NULL; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_valid) (const list_type *list) { return (list != NULL && list->list == NULL); } - -#undef EP_RT_DEFINE_LIST -#define EP_RT_DEFINE_LIST(list_name, list_type, item_type) \ - EP_RT_DEFINE_LIST_PREFIX(ep, list_name, list_type, item_type) - -#define EP_RT_DEFINE_LIST_ITERATOR_PREFIX(prefix_name, list_name, list_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_begin) (const list_type *list) { \ - EP_ASSERT (list != NULL); \ - iterator_type temp; \ - temp.iterator = list->list; \ - return temp;\ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_end) (const list_type *list, const iterator_type *iterator) { \ - EP_ASSERT (list != NULL && iterator != NULL); \ - return iterator->iterator == NULL; \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_next) (iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL); \ - iterator->iterator = iterator->iterator->next; \ - } \ - static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_value) (const iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL); \ - return ((item_type)(gsize)(iterator->iterator->data)); \ - } - -#undef EP_RT_DEFINE_LIST_ITERATOR -#define EP_RT_DEFINE_LIST_ITERATOR(list_name, list_type, iterator_type, item_type) \ - EP_RT_DEFINE_LIST_ITERATOR_PREFIX(ep, list_name, list_type, iterator_type, item_type) - -#define EP_RT_DEFINE_QUEUE_PREFIX(prefix_name, queue_name, queue_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, alloc) (queue_type *queue) { queue->queue = g_queue_new (); } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, free) (queue_type *queue) { \ - EP_ASSERT (queue != NULL); \ - g_queue_free (queue->queue); \ - queue->queue = NULL; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, pop_head) (queue_type *queue, item_type *item) { \ - EP_ASSERT (queue != NULL && item != NULL); \ - *item = ((item_type)(gsize)g_queue_pop_head (queue->queue)); \ - return true; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_head) (queue_type *queue, item_type item) { \ - EP_ASSERT (queue != NULL); \ - g_queue_push_head (queue->queue, ((gpointer)(gsize)item)); \ - return true; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_tail) (queue_type *queue, item_type item) { \ - EP_ASSERT (queue != NULL); \ - g_queue_push_tail (queue->queue, ((gpointer)(gsize)item)); \ - return true; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_empty) (const queue_type *queue) { \ - EP_ASSERT (queue != NULL); \ - return (g_queue_is_empty (queue->queue) == TRUE) ? true : false; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_valid) (const queue_type *queue) { return (queue != NULL && queue->queue != NULL); } - -#undef EP_RT_DEFINE_QUEUE -#define EP_RT_DEFINE_QUEUE(queue_name, queue_type, item_type) \ - EP_RT_DEFINE_QUEUE_PREFIX(ep, queue_name, queue_type, item_type) - -#define EP_RT_DEFINE_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc) (array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - ep_array->array = g_array_new (FALSE, FALSE, (guint)sizeof (item_type)); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc_capacity) (array_type *ep_array, size_t capacity) { \ - EP_ASSERT (ep_array != NULL); \ - ep_array->array = g_array_sized_new (FALSE, FALSE, (guint)sizeof (item_type), (guint)capacity); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, free) (array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - g_array_free (ep_array->array, TRUE); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, append) (array_type *ep_array, item_type item) { \ - EP_ASSERT (ep_array != NULL); \ - return g_array_append_val (ep_array->array, item) != NULL; \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, clear) (array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - g_array_set_size (ep_array->array, 0); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, remove) (array_type *ep_array, iterator_type *pos) { \ - EP_ASSERT (ep_array != NULL && pos != NULL); \ - EP_ASSERT (pos->index < ep_array->array->len); \ - ep_array->array = g_array_remove_index_fast (ep_array->array, pos->index); \ - } \ - static inline size_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, size) (const array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - return ep_array->array->len; \ - } \ - static inline item_type * EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, data) (const array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - return (item_type *)ep_array->array->data; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, is_valid) (const array_type *ep_array) { return (ep_array != NULL && ep_array->array != NULL); } - -#define EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init) (array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - ep_array->array = g_array_new (FALSE, FALSE, (guint)sizeof (item_type)); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init_capacity) (array_type *ep_array, size_t capacity) { \ - EP_ASSERT (ep_array != NULL); \ - ep_array->array = g_array_sized_new (FALSE, FALSE, (guint)sizeof (item_type), (guint)capacity); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, fini) (array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - g_array_free (ep_array->array, TRUE); \ - } - -#undef EP_RT_DEFINE_ARRAY -#define EP_RT_DEFINE_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#undef EP_RT_DEFINE_LOCAL_ARRAY -#define EP_RT_DEFINE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_begin) (const array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - iterator_type temp; \ - temp.array = ep_array->array; \ - temp.index = 0; \ - return temp; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_end) (const array_type *ep_array, const iterator_type *iterator) { \ - EP_ASSERT (ep_array != NULL && iterator != NULL && iterator->array == ep_array->array); \ - return iterator->index >= iterator->array->len; \ - } \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_next) (iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL); \ - iterator->index++; \ - } \ - static item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_value) (const iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL); \ - return g_array_index(iterator->array, item_type, iterator->index); \ - } - -#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_begin) (const array_type *ep_array) { \ - EP_ASSERT (ep_array != NULL); \ - iterator_type temp; \ - temp.array = ep_array->array; \ - temp.index = ep_array->array->len - 1; \ - return temp; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_end) (const array_type *ep_array, const iterator_type *iterator) { \ - EP_ASSERT (ep_array != NULL && iterator != NULL && iterator->array == ep_array->array); \ - return iterator->index < 0; \ - } \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_next) (iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL && iterator->array != NULL); \ - iterator->index--; \ - } \ - static item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_value) (const iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL && iterator->array != NULL); \ - EP_ASSERT (iterator->index >= 0); \ - return g_array_index(iterator->array, item_type, iterator->index); \ - } - -#undef EP_RT_DEFINE_ARRAY_ITERATOR -#define EP_RT_DEFINE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#undef EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR -#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, alloc) (hash_map_type *hash_map, ep_rt_hash_map_hash_callback_t hash_callback, ep_rt_hash_map_equal_callback_t eq_callback, void (*key_free_callback)(void *), void (*value_free_callback)(void *)) { \ - EP_ASSERT (hash_map != NULL); \ - EP_ASSERT (key_free_callback == NULL); \ - hash_map->table = g_hash_table_new_full ((GHashFunc)hash_callback, (GEqualFunc)eq_callback, (GDestroyNotify)key_free_callback, (GDestroyNotify)value_free_callback); \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, free) (hash_map_type *hash_map) { \ - EP_ASSERT (hash_map != NULL); \ - g_hash_table_destroy (hash_map->table); \ - hash_map->table = NULL; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add) (hash_map_type *hash_map, key_type key, value_type value) { \ - EP_ASSERT (hash_map != NULL); \ - EP_ASSERT (!g_hash_table_lookup_extended (hash_map->table, (gconstpointer)key, NULL, NULL)); \ - g_hash_table_insert (hash_map->table, (gpointer)key, ((gpointer)(gsize)value)); \ - return true; \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove_all) (hash_map_type *hash_map) { \ - EP_ASSERT (hash_map != NULL); \ - g_hash_table_remove_all (hash_map->table); \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, lookup) (const hash_map_type *hash_map, const key_type key, value_type *value) { \ - EP_ASSERT (hash_map != NULL && value != NULL); \ - gpointer _value = NULL; \ - bool result = (g_hash_table_lookup_extended (hash_map->table, (gconstpointer)key, NULL, &_value) == TRUE) ? true : false; \ - *value = ((value_type)(gsize)_value); \ - return result; \ - } \ - static inline uint32_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, count) (const hash_map_type *hash_map) { \ - EP_ASSERT (hash_map != NULL); \ - return (hash_map->table != NULL) ? g_hash_table_size (hash_map->table) : 0; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, is_valid) (const hash_map_type *hash_map) { \ - EP_ASSERT (hash_map != NULL); \ - return (hash_map != NULL && hash_map->table != NULL); \ - } - -#define EP_RT_DEFINE_HASH_MAP_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add_or_replace) (hash_map_type *hash_map, key_type key, value_type value) { \ - EP_ASSERT (hash_map != NULL); \ - g_hash_table_replace (hash_map->table, (gpointer)key, ((gpointer)(gsize)value)); \ - return true; \ - } - -#define EP_RT_DEFINE_HASH_MAP_REMOVE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove) (hash_map_type *hash_map, const key_type key) { \ - EP_ASSERT (hash_map != NULL); \ - g_hash_table_remove (hash_map->table, (gconstpointer)key); \ - } - -#undef EP_RT_DEFINE_HASH_MAP -#define EP_RT_DEFINE_HASH_MAP(hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type) - -#undef EP_RT_DEFINE_HASH_MAP_REMOVE -#define EP_RT_DEFINE_HASH_MAP_REMOVE(hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_REMOVE_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type) - -#define EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(prefix_name, hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ - static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_begin) (const hash_map_type *hash_map) { \ - EP_ASSERT (hash_map != NULL); \ - iterator_type temp; \ - g_hash_table_iter_init (&temp.iterator, hash_map->table); \ - if (hash_map->table && g_hash_table_size (hash_map->table) > 0) \ - temp.end = !g_hash_table_iter_next (&temp.iterator, &temp.key, &temp.value); \ - else \ - temp.end = true; \ - return temp; \ - } \ - static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_end) (const hash_map_type *hash_map, const iterator_type *iterator) { \ - EP_ASSERT (hash_map != NULL && iterator != NULL); \ - return iterator->end; \ - } \ - static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_next) (iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL); \ - iterator->end = !g_hash_table_iter_next (&iterator->iterator, &iterator->key, &iterator->value); \ - } \ - static inline key_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_key) (const iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL); \ - return ((key_type)(gsize)iterator->key); \ - } \ - static inline value_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_value) (const iterator_type *iterator) { \ - EP_ASSERT (iterator != NULL); \ - return ((value_type)(gsize)iterator->value); \ - } - -#undef EP_RT_DEFINE_HASH_MAP_ITERATOR -#define EP_RT_DEFINE_HASH_MAP_ITERATOR(hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ - EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(ep, hash_map_name, hash_map_type, iterator_type, key_type, value_type) - extern char *_ep_rt_mono_os_cmd_line; extern mono_lazy_init_t _ep_rt_mono_os_cmd_line_init; extern char *_ep_rt_mono_managed_cmd_line; @@ -373,16 +69,14 @@ extern void ep_rt_mono_init_providers_and_events (void); extern bool ep_rt_mono_providers_validate_all_disabled (void); extern bool ep_rt_mono_sample_profiler_write_sampling_event_for_threads (ep_rt_thread_handle_t sampling_thread, EventPipeEvent *sampling_event); extern bool ep_rt_mono_rand_try_get_bytes (uint8_t *buffer,size_t buffer_size); -extern void ep_rt_mono_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints); +extern void ep_rt_mono_execute_rundown (dn_vector_ptr_t *execution_checkpoints); extern int64_t ep_rt_mono_perf_counter_query (void); extern int64_t ep_rt_mono_perf_frequency_query (void); extern void ep_rt_mono_system_time_get (EventPipeSystemTime *system_time); extern int64_t ep_rt_mono_system_timestamp_get (void); -extern void ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array); +extern void ep_rt_mono_os_environment_get_utf16 (dn_vector_ptr_t *os_env); extern MonoNativeTlsKey _ep_rt_mono_thread_holder_tls_id; extern EventPipeThread * ep_rt_mono_thread_get_or_create (void); -extern uint32_t ep_stack_hash_key_hash (const void *key); -extern bool ep_stack_hash_key_equal (const void *key1, const void *key2); static inline @@ -682,12 +376,6 @@ ep_rt_atomic_compare_exchange_utf8_string (ep_char8_t *volatile *target, ep_char * EventPipe. */ -EP_RT_DEFINE_ARRAY (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID) -EP_RT_DEFINE_ARRAY_ITERATOR (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID) - -EP_RT_DEFINE_ARRAY (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *) -EP_RT_DEFINE_ARRAY_ITERATOR (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *) - static inline void @@ -842,99 +530,9 @@ ep_rt_provider_invoke_callback ( } /* - * EventPipeBuffer. - */ - -EP_RT_DEFINE_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) -EP_RT_DEFINE_LOCAL_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) -EP_RT_DEFINE_ARRAY_ITERATOR (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) - -#undef EP_RT_DECLARE_LOCAL_BUFFER_ARRAY -#define EP_RT_DECLARE_LOCAL_BUFFER_ARRAY(var_name) \ - ep_rt_buffer_array_t var_name - -/* - * EventPipeBufferList. - */ - -EP_RT_DEFINE_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) -EP_RT_DEFINE_LOCAL_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) -EP_RT_DEFINE_ARRAY_ITERATOR (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) - -#undef EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY -#define EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY(var_name) \ - ep_rt_buffer_list_array_t var_name - -/* - * EventPipeEvent. - */ - -EP_RT_DEFINE_LIST (event_list, ep_rt_event_list_t, EventPipeEvent *) -EP_RT_DEFINE_LIST_ITERATOR (event_list, ep_rt_event_list_t, ep_rt_event_list_iterator_t, EventPipeEvent *) - -/* - * EventPipeFile. - */ - -EP_RT_DEFINE_HASH_MAP_REMOVE(metadata_labels_hash, ep_rt_metadata_labels_hash_map_t, EventPipeEvent *, uint32_t) -EP_RT_DEFINE_HASH_MAP(stack_hash, ep_rt_stack_hash_map_t, StackHashKey *, StackHashEntry *) -EP_RT_DEFINE_HASH_MAP_ITERATOR(stack_hash, ep_rt_stack_hash_map_t, ep_rt_stack_hash_map_iterator_t, StackHashKey *, StackHashEntry *) - -#ifdef EP_RT_USE_CUSTOM_HASH_MAP_CALLBACKS -static -inline -guint -ep_rt_stack_hash_key_hash (gconstpointer key) -{ - return (guint)ep_stack_hash_key_hash (key); -} - -static -inline -gboolean -ep_rt_stack_hash_key_equal (gconstpointer key1, gconstpointer key2) -{ - return !!ep_stack_hash_key_equal (key1, key2); -} -#endif - -/* - * EventPipeProvider. - */ - -EP_RT_DEFINE_LIST (provider_list, ep_rt_provider_list_t, EventPipeProvider *) -EP_RT_DEFINE_LIST_ITERATOR (provider_list, ep_rt_provider_list_t, ep_rt_provider_list_iterator_t, EventPipeProvider *) - -EP_RT_DEFINE_QUEUE (provider_callback_data_queue, ep_rt_provider_callback_data_queue_t, EventPipeProviderCallbackData *) - -static -inline -int -compare_provider_name ( - gconstpointer a, - gconstpointer b) -{ - return (a) ? ep_rt_utf8_string_compare (ep_provider_get_provider_name ((EventPipeProvider *)a), (const ep_char8_t *)b) : 1; -} - -static -inline -EventPipeProvider * -ep_rt_provider_list_find_by_name ( - const ep_rt_provider_list_t *list, - const ep_char8_t *name) -{ - GSList *item = g_slist_find_custom (list->list, name, compare_provider_name); - return (item != NULL) ? (EventPipeProvider *)item->data : NULL; -} - -/* * EventPipeProviderConfiguration. */ -EP_RT_DEFINE_ARRAY (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration) -EP_RT_DEFINE_ARRAY_ITERATOR (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration) - static inline bool @@ -1051,71 +649,6 @@ ep_rt_notify_profiler_provider_created (EventPipeProvider *provider) } /* - * EventPipeSessionProvider. - */ - -EP_RT_DEFINE_LIST (session_provider_list, ep_rt_session_provider_list_t, EventPipeSessionProvider *) -EP_RT_DEFINE_LIST_ITERATOR (session_provider_list, ep_rt_session_provider_list_t, ep_rt_session_provider_list_iterator_t, EventPipeSessionProvider *) - -static -inline -int -compare_session_provider_name ( - gconstpointer a, - gconstpointer b) -{ - return (a) ? ep_rt_utf8_string_compare (ep_session_provider_get_provider_name ((EventPipeSessionProvider *)a), (const ep_char8_t *)b) : 1; -} - -static -inline -EventPipeSessionProvider * -ep_rt_session_provider_list_find_by_name ( - const ep_rt_session_provider_list_t *list, - const ep_char8_t *name) -{ - GSList *item = g_slist_find_custom (list->list, name, compare_session_provider_name); - return (item != NULL) ? (EventPipeSessionProvider *)item->data : NULL; -} - -/* - * EventPipeSequencePoint. - */ - -EP_RT_DEFINE_LIST (sequence_point_list, ep_rt_sequence_point_list_t, EventPipeSequencePoint *) -EP_RT_DEFINE_LIST_ITERATOR (sequence_point_list, ep_rt_sequence_point_list_t, ep_rt_sequence_point_list_iterator_t, EventPipeSequencePoint *) - -/* - * EventPipeThread. - */ - -EP_RT_DEFINE_LIST (thread_list, ep_rt_thread_list_t, EventPipeThread *) -EP_RT_DEFINE_LIST_ITERATOR (thread_list, ep_rt_thread_list_t, ep_rt_thread_list_iterator_t, EventPipeThread *) - -EP_RT_DEFINE_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) -EP_RT_DEFINE_LOCAL_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) -EP_RT_DEFINE_ARRAY_ITERATOR (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) - -#undef EP_RT_DECLARE_LOCAL_THREAD_ARRAY -#define EP_RT_DECLARE_LOCAL_THREAD_ARRAY(var_name) \ - ep_rt_thread_array_t var_name - -/* - * EventPipeThreadSessionState. - */ - -EP_RT_DEFINE_LIST (thread_session_state_list, ep_rt_thread_session_state_list_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_LIST_ITERATOR (thread_session_state_list, ep_rt_thread_session_state_list_t, ep_rt_thread_session_state_list_iterator_t, EventPipeThreadSessionState *) - -EP_RT_DEFINE_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_LOCAL_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) -EP_RT_DEFINE_ARRAY_ITERATOR (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) - -#undef EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY -#define EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY(var_name) \ - ep_rt_thread_session_state_array_t var_name - -/* * Arrays. */ @@ -1289,7 +822,7 @@ ep_rt_is_running (void) static inline void -ep_rt_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints) +ep_rt_execute_rundown (dn_vector_ptr_t *execution_checkpoints) { if (ep_rt_config_value_get_rundown () > 0) { // Ask the runtime to emit rundown events. @@ -1575,15 +1108,12 @@ ep_on_error: ep_exit_error_handler (); } -EP_RT_DEFINE_ARRAY (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *) -EP_RT_DEFINE_ARRAY_ITERATOR (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *) - static inline void -ep_rt_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array) +ep_rt_os_environment_get_utf16 (dn_vector_ptr_t *os_env) { - ep_rt_mono_os_environment_get_utf16 (env_array); + ep_rt_mono_os_environment_get_utf16 (os_env); } /* @@ -2132,13 +1662,6 @@ ep_rt_mono_thread_yield (void) } /* - * ThreadSequenceNumberMap. - */ - -EP_RT_DEFINE_HASH_MAP_REMOVE(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, EventPipeThreadSessionState *, uint32_t) -EP_RT_DEFINE_HASH_MAP_ITERATOR(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, ep_rt_thread_sequence_number_hash_map_iterator_t, EventPipeThreadSessionState *, uint32_t) - -/* * Volatile. */ diff --git a/src/mono/mono/eventpipe/ep-rt-types-mono.h b/src/mono/mono/eventpipe/ep-rt-types-mono.h index 6583b55..129d3d5 100644 --- a/src/mono/mono/eventpipe/ep-rt-types-mono.h +++ b/src/mono/mono/eventpipe/ep-rt-types-mono.h @@ -29,43 +29,6 @@ #undef EP_UNLIKELY #define EP_UNLIKELY(expr) G_UNLIKELY(expr) -struct _rt_mono_list_internal_t { - GSList *list; -}; - -struct _rt_mono_list_iterator_internal_t { - GSList *iterator; -}; - -struct _rt_mono_queue_internal_t { - GQueue *queue; -}; - -struct _rt_mono_array_internal_t { - GArray *array; -}; - -struct _rt_mono_array_iterator_internal_t { - GArray *array; - int32_t index; -}; - -#ifdef EP_RT_USE_CUSTOM_HASH_MAP_CALLBACKS -typedef GHashFunc ep_rt_hash_map_hash_callback_t; -typedef GEqualFunc ep_rt_hash_map_equal_callback_t; -#endif - -struct _rt_mono_table_internal_t { - GHashTable *table; -}; - -struct _rt_mono_table_iterator_internal_t { - GHashTableIter iterator; - gpointer key; - gpointer value; - bool end; -}; - struct _rt_mono_event_internal_t { gpointer event; }; @@ -78,155 +41,16 @@ struct _rt_mono_lock_internal_t { }; /* - * EventPipeBuffer. - */ - -#undef ep_rt_buffer_array_t -typedef struct _rt_mono_array_internal_t ep_rt_buffer_array_t; - -#undef ep_rt_buffer_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ep_rt_buffer_array_iterator_t; - -/* - * EventPipeBufferList. - */ - -#undef ep_rt_buffer_list_array_t -typedef struct _rt_mono_array_internal_t ep_rt_buffer_list_array_t; - -#undef ep_rt_buffer_list_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ep_rt_buffer_list_array_iterator_t; - -/* - * EventPipeEvent. - */ - -#undef ep_rt_event_list_t -typedef struct _rt_mono_list_internal_t ep_rt_event_list_t; - -#undef ep_rt_event_list_iterator_t -typedef struct _rt_mono_list_iterator_internal_t ep_rt_event_list_iterator_t; - -/* - * EventPipeFile. - */ - -#undef ep_rt_metadata_labels_hash_map_t -typedef struct _rt_mono_table_internal_t ep_rt_metadata_labels_hash_map_t; - -#undef ep_rt_metadata_labels_hash_map_iterator_t -typedef struct _rt_mono_iterator_table_internal_t ep_rt_metadata_labels_hash_map_iterator_t; - -#undef ep_rt_stack_hash_map_t -typedef struct _rt_mono_table_internal_t ep_rt_stack_hash_map_t; - -#undef ep_rt_stack_hash_map_iterator_t -typedef struct _rt_mono_table_iterator_internal_t ep_rt_stack_hash_map_iterator_t; - -/* - * EventPipeProvider. - */ - -#undef ep_rt_provider_list_t -typedef struct _rt_mono_list_internal_t ep_rt_provider_list_t; - -#undef ep_rt_provider_list_iterator_t -typedef struct _rt_mono_list_iterator_internal_t ep_rt_provider_list_iterator_t; - -#undef ep_rt_provider_callback_data_queue_t -typedef struct _rt_mono_queue_internal_t ep_rt_provider_callback_data_queue_t; - -/* - * EventPipeProviderConfiguration. - */ - -#undef ep_rt_provider_config_array_t -typedef struct _rt_mono_array_internal_t ep_rt_provider_config_array_t; - -#undef ep_rt_provider_config_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ep_rt_provider_config_array_iterator_t; - -/* - * EventPipeSessionProvider. - */ - -#undef ep_rt_session_provider_list_t -typedef struct _rt_mono_list_internal_t ep_rt_session_provider_list_t; - -#undef ep_rt_session_provider_list_iterator_t -typedef struct _rt_mono_list_iterator_internal_t ep_rt_session_provider_list_iterator_t; - -/* - * EventPipeSequencePoint. - */ - -#undef ep_rt_sequence_point_list_t -typedef struct _rt_mono_list_internal_t ep_rt_sequence_point_list_t; - -#undef ep_rt_sequence_point_list_iterator_t -typedef struct _rt_mono_list_iterator_internal_t ep_rt_sequence_point_list_iterator_t; - -/* - * EventPipeThread. - */ - -#undef ep_rt_thread_list_t -typedef struct _rt_mono_list_internal_t ep_rt_thread_list_t; - -#undef ep_rt_thread_list_iterator_t -typedef struct _rt_mono_list_iterator_internal_t ep_rt_thread_list_iterator_t; - -#undef ep_rt_thread_array_t -typedef struct _rt_mono_array_internal_t ep_rt_thread_array_t; - -#undef ep_rt_thread_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ep_rt_thread_array_iterator_t; - -/* - * EventPipeThreadSessionState. - */ - -#undef ep_rt_thread_session_state_list_t -typedef struct _rt_mono_list_internal_t ep_rt_thread_session_state_list_t; - -#undef ep_rt_thread_session_state_list_iterator_t -typedef struct _rt_mono_list_iterator_internal_t ep_rt_thread_session_state_list_iterator_t; - -#undef ep_rt_thread_session_state_array_t -typedef struct _rt_mono_array_internal_t ep_rt_thread_session_state_array_t; - -#undef ep_rt_thread_session_state_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ep_rt_thread_session_state_array_iterator_t; - -/* * EventPipe. */ -#undef ep_rt_session_id_array_t -typedef struct _rt_mono_array_internal_t ep_rt_session_id_array_t; - -#undef ep_rt_session_id_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ep_rt_session_id_array_iterator_t; - #undef ep_rt_method_desc_t typedef MonoMethod ep_rt_method_desc_t; -#undef ep_rt_execution_checkpoint_array_t -typedef struct _rt_mono_array_internal_t ep_rt_execution_checkpoint_array_t; - -#undef ep_rt_execution_checkpoint_array_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ep_rt_execution_checkpoint_array_iterator_t; - /* * PAL. */ -#undef ep_rt_env_array_utf16_t -typedef struct _rt_mono_array_internal_t ep_rt_env_array_utf16_t; - -#undef ep_rt_env_array_utf16_iterator_t -typedef struct _rt_mono_array_iterator_internal_t ep_rt_env_array_utf16_iterator_t; - #undef ep_rt_file_handle_t typedef gpointer ep_rt_file_handle_t; @@ -266,15 +90,5 @@ typedef struct _rt_mono_thread_params_t { void *thread_params; } ep_rt_thread_params_t; -/* - * ThreadSequenceNumberMap. - */ - -#undef ep_rt_thread_sequence_number_hash_map_t -typedef struct _rt_mono_table_internal_t ep_rt_thread_sequence_number_hash_map_t; - -#undef ep_rt_thread_sequence_number_hash_map_iterator_t -typedef struct _rt_mono_table_iterator_internal_t ep_rt_thread_sequence_number_hash_map_iterator_t; - #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_RT_TYPES_MONO_H__ */ diff --git a/src/mono/mono/eventpipe/CMakeLists.txt b/src/mono/mono/eventpipe/eventpipe.cmake similarity index 90% rename from src/mono/mono/eventpipe/CMakeLists.txt rename to src/mono/mono/eventpipe/eventpipe.cmake index e1e9b20..cd0d4a6 100644 --- a/src/mono/mono/eventpipe/CMakeLists.txt +++ b/src/mono/mono/eventpipe/eventpipe.cmake @@ -26,7 +26,18 @@ if(ENABLE_PERFTRACING) add_definitions(-DBIGENDIAN) endif (TARGET_S390X) - include (${SHARED_EVENTPIPE_SOURCE_PATH}CMakeLists.txt) + include (${SHARED_CONTAINERS_SOURCE_PATH}containers.cmake) + + set(container_sources "") + + list(APPEND container_sources + ${SHARED_CONTAINER_SOURCES} + ${SHARED_CONTAINER_HEADERS} + ) + + addprefix(container_sources ${SHARED_CONTAINERS_SOURCE_PATH} "${container_sources}") + + include (${SHARED_EVENTPIPE_SOURCE_PATH}eventpipe.cmake) set(MONO_EVENTPIPE_SHIM_SOURCES "") set(MONO_EVENTPIPE_SHIM_HEADERS "") diff --git a/src/mono/mono/eventpipe/test/CMakeLists.txt b/src/mono/mono/eventpipe/test/CMakeLists.txt index 7f14908..5662e9c 100644 --- a/src/mono/mono/eventpipe/test/CMakeLists.txt +++ b/src/mono/mono/eventpipe/test/CMakeLists.txt @@ -20,6 +20,12 @@ if(ENABLE_PERFTRACING) ep-test-runner.c ep-test-driver.c ep-thread-tests.c + dn-vector-tests.c + dn-vector-ptr-tests.c + dn-fwd-list-tests.c + dn-list-tests.c + dn-queue-tests.c + dn-umap-tests.c ) list(APPEND EVENTPIPE_TEST_HEADERS @@ -33,7 +39,7 @@ if(ENABLE_PERFTRACING) set(CMAKE_SKIP_RPATH 1) add_executable(ep-test ${EVENTPIPE_TEST_SOURCES} ${EVENTPIPE_TEST_HEADERS}) target_sources(ep-test PRIVATE "${mono-components-objects}") - target_link_libraries(ep-test PUBLIC monosgen-static ${OS_LIBS} ${LLVM_LIBS} ${ICU_LIBS} ${Z_LIBS} monoapi) + target_link_libraries(ep-test PRIVATE eglib_api monosgen-static ${OS_LIBS} ${LLVM_LIBS} ${ICU_LIBS} ${Z_LIBS} monoapi) if(ICU_LDFLAGS) set_target_properties(ep-test PROPERTIES LINK_FLAGS ${ICU_LDFLAGS}) endif() diff --git a/src/mono/mono/eventpipe/test/dn-fwd-list-tests.c b/src/mono/mono/eventpipe/test/dn-fwd-list-tests.c new file mode 100644 index 0000000..9a4dc1a --- /dev/null +++ b/src/mono/mono/eventpipe/test/dn-fwd-list-tests.c @@ -0,0 +1,925 @@ +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include + + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState dn_fwd_list_memory_start_snapshot; +static _CrtMemState dn_fwd_list_memory_end_snapshot; +static _CrtMemState dn_fwd_list_memory_diff_snapshot; +#endif + +#define N_ELEMS 100 +#define POINTER_TO_INT32(v) ((int32_t)(ptrdiff_t)(v)) +#define INT32_TO_POINTER(v) ((void *)(ptrdiff_t)(v)) + +static +void +DN_CALLBACK_CALLTYPE +test_fwd_list_dispose_func (void *data) +{ + (*(uint32_t *)data)++; +} + +static int32_t test_fwd_list_dispose_count = 0; + +static +void +DN_CALLBACK_CALLTYPE +test_fwd_list_dispose_count_func (void *data) +{ + test_fwd_list_dispose_count++; +} + +static +bool +DN_CALLBACK_CALLTYPE +test_fwd_list_remove_if_func (const void *data, const void *user_data) +{ + return !strcmp ((const char *)data, (const char *)user_data); +} + +static +void +DN_CALLBACK_CALLTYPE +test_fwd_list_foreach_func ( + void *data, + void *user_data) +{ + (*(uint32_t *)user_data)++; +} + +static +int32_t +DN_CALLBACK_CALLTYPE +test_fwd_list_sort_compare ( + const void *p1, + const void *p2) +{ + return POINTER_TO_INT32 (p1) - POINTER_TO_INT32 (p2); +} + +static +RESULT +test_fwd_list_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_fwd_list_memory_start_snapshot); +#endif + return OK; +} + +static +RESULT +test_fwd_list_alloc (void) +{ + dn_fwd_list_t *list = dn_fwd_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_init (void) +{ + dn_fwd_list_t list; + if (!dn_fwd_list_init (&list)) + return FAILED ("failed to init list"); + + dn_fwd_list_dispose (&list); + + return OK; +} + +static +RESULT +test_fwd_list_free (void) +{ + uint32_t dispose_count = 0; + dn_fwd_list_t *list = dn_fwd_list_custom_alloc (DN_DEFAULT_ALLOCATOR); + if (!list) + return FAILED ("failed to custom alloc list"); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + + dn_fwd_list_custom_free (list, test_fwd_list_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on free"); + + return OK; +} + +static +RESULT +test_fwd_list_dispose (void) +{ + uint32_t dispose_count = 0; + dn_fwd_list_t list; + if (!dn_fwd_list_custom_init (&list, DN_DEFAULT_ALLOCATOR)) + return FAILED ("failed to custom init list"); + + dn_fwd_list_insert_after (dn_fwd_list_end (&list), &dispose_count); + dn_fwd_list_insert_after (dn_fwd_list_end (&list), &dispose_count); + + dn_fwd_list_custom_dispose (&list, test_fwd_list_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on free"); + + return OK; +} + +static +RESULT +test_fwd_list_front (void) +{ + const char * items[] = { "first", "second" }; + + dn_fwd_list_t *list = dn_fwd_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]); + + if (*dn_fwd_list_front_t (list, char *) != items [0]) + return FAILED ("failed list front #1"); + + dn_fwd_list_insert_after (dn_fwd_list_before_begin (list), (char *)items [1]); + dn_fwd_list_insert_after (dn_fwd_list_begin (list), (char *)items [0]); + + if (*dn_fwd_list_front_t (list, char *) != items [1]) + return FAILED ("failed list front #2"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_empty (void) +{ + const char * items[] = { "first", "second" }; + + dn_fwd_list_t *list = dn_fwd_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + if (!dn_fwd_list_empty (list)) + return FAILED ("failed empty #1"); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]); + + if (dn_fwd_list_empty (list)) + return FAILED ("failed empty #2"); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]); + + if (dn_fwd_list_empty (list)) + return FAILED ("failed empty #3"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_max_size (void) +{ + dn_fwd_list_t *list = dn_fwd_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + if (dn_fwd_list_max_size (list) != UINT32_MAX) + return FAILED ("max_size failed"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_clear (void) +{ + uint32_t dispose_count = 0; + const char * items[] = { "first", "second" }; + + dn_fwd_list_t *list = dn_fwd_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + if (!dn_fwd_list_empty (list)) + return FAILED ("failed empty #1"); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]); + + if (dn_fwd_list_empty (list)) + return FAILED ("failed empty #2"); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]); + + dn_fwd_list_clear (list); + + if (!dn_fwd_list_empty (list)) + return FAILED ("failed empty #3"); + + dn_fwd_list_free (list); + + list = dn_fwd_list_custom_alloc (DN_DEFAULT_ALLOCATOR); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + + dn_fwd_list_custom_clear (list, test_fwd_list_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on clear"); + + dispose_count = 0; + dn_fwd_list_custom_free (list, test_fwd_list_dispose_func); + + if (dispose_count != 0) + return FAILED ("invalid dispose count on clear/free"); + + return OK; +} + +static +RESULT +test_fwd_list_insert_after (void) +{ + const char *items[] = { "first", "second" }; + + dn_fwd_list_t *list = dn_fwd_list_alloc (); + if (!dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]).result) + return FAILED ("insert_after failed #1"); + + if (!dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]).result) + return FAILED ("insert_after failed #2"); + + size_t i = 0; + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (strcmp (item, items [i])) + return FAILED ("insert_range, found %s, expected %s #1", item, items [i]); + i++; + } DN_FWD_LIST_FOREACH_END; + + dn_fwd_list_free (list); + + list = dn_fwd_list_alloc (); + if (!dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]).result) + return FAILED ("insert_after failed #3"); + + if (!dn_fwd_list_insert_after (dn_fwd_list_before_begin (list), (char *)items [0]).result) + return FAILED ("insert_after failed #4"); + + i = 0; + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (strcmp (item, items [i])) + return FAILED ("insert_range, found %s, expected %s #1", item, items [i]); + i++; + } DN_FWD_LIST_FOREACH_END; + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_insert_range_after (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_fwd_list_t *list1 = dn_fwd_list_alloc (); + dn_fwd_list_t *list2 = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list1), (char *)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list2), (char *)items [1]); + + if (!dn_fwd_list_insert_range_after (dn_fwd_list_end (list1), dn_fwd_list_begin (list2), dn_fwd_list_end (list2)).result) + return FAILED ("insert_range_after failed #1"); + + size_t i = 0; + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list1) { + if (strcmp (item, items [i])) + return FAILED ("insert_range_after, found %s, expected %s #1", item, items [i]); + i++; + } DN_FWD_LIST_FOREACH_END; + + dn_fwd_list_free (list1); + dn_fwd_list_free (list2); + + list1 = dn_fwd_list_alloc (); + list2 = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list1), (char *)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list2), (char *)items [1]); + + if (!dn_fwd_list_insert_range_after (dn_fwd_list_before_begin (list1), dn_fwd_list_begin (list2), dn_fwd_list_end (list2)).result) + return FAILED ("insert_range_after failed #2"); + + i = 1; + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list1) { + if (strcmp (item, items [i])) + return FAILED ("insert_range_after, found %s, expected %s #2", item, items [i]); + i--; + } DN_FWD_LIST_FOREACH_END; + + dn_fwd_list_free (list1); + dn_fwd_list_free (list2); + + list1 = dn_fwd_list_alloc (); + list2 = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list1), (char*)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list1), (char*)items [1]); + dn_fwd_list_insert_after (dn_fwd_list_end (list1), (char*)items [3]); + dn_fwd_list_insert_after (dn_fwd_list_end (list2), (char*)items [2]); + + dn_fwd_list_it_t it = dn_fwd_list_begin (list1); + it = dn_fwd_list_it_next (it); + + if (!dn_fwd_list_insert_range_after (it, dn_fwd_list_begin (list2), dn_fwd_list_end (list2)).result) + return FAILED ("insert_range_after failed #2"); + + i = 0; + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list1) { + if (strcmp (item, items [i])) + return FAILED ("insert_range_after, found %s, expected %s #2", item, items [i]); + i++; + } DN_FWD_LIST_FOREACH_END; + + dn_fwd_list_free (list1); + dn_fwd_list_free (list2); + + return OK; +} + +static +RESULT +test_fwd_list_erase_after (void) +{ + uint32_t dispose_count = 0; + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_fwd_list_t *list = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char*)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char*)items [1]); + + dn_fwd_list_erase_after (dn_fwd_list_begin (list)); + + if (!list->head || !list->head->data || strcmp (list->head->data, "first") || list->head->next) + return FAILED ("erase_after failed #1"); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char*)items [1]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char*)items [2]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char*)items [3]); + + // Remove first. + dn_fwd_list_erase_after (dn_fwd_list_before_begin (list)); + + dn_fwd_list_it_t it = dn_fwd_list_begin (list); + it = dn_fwd_list_it_next (it); + + // Remove fourth. + dn_fwd_list_erase_after (it); + + // Remove third. + dn_fwd_list_erase_after (dn_fwd_list_begin (list)); + + if (!list->head || !list->head->data || strcmp (list->head->data, "second") || list->head->next) + return FAILED ("erase_after failed #2"); + + dn_fwd_list_free (list); + + list = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + + dn_fwd_list_custom_erase_after (dn_fwd_list_begin (list), test_fwd_list_dispose_func); + dn_fwd_list_custom_erase_after (dn_fwd_list_begin (list), test_fwd_list_dispose_func); + + if (dispose_count != 2) + return FAILED ("erase_after failed #3"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_push_front (void) +{ + const char *items[] = { "a", "b", "c"}; + + dn_fwd_list_t list; + + dn_fwd_list_init (&list); + + dn_fwd_list_push_front (&list, (char *)items [0]); + if (*dn_fwd_list_front_t (&list, char *) != items [0]) + return FAILED ("push_front failed #1"); + + dn_fwd_list_push_front (&list, (char *)items [1]); + if (*dn_fwd_list_front_t (&list, char *) != items [1]) + return FAILED ("push_front failed #2"); + + dn_fwd_list_push_front (&list, (char *)items [2]); + + uint32_t i = 2; + DN_FWD_LIST_FOREACH_BEGIN (char *, item, &list) { + if (strcmp (item, items [i])) + return FAILED ("push_front failed, found %s, expected %s #2", item, items [i]); + i--; + } DN_FWD_LIST_FOREACH_END; + + dn_fwd_list_dispose (&list); + + return OK; +} + +static +RESULT +test_fwd_list_pop_front (void) +{ + uint32_t dispose_count = 0; + const char *items[] = { "a", "b", "c"}; + + dn_fwd_list_t list; + + dn_fwd_list_custom_init (&list, DN_DEFAULT_ALLOCATOR); + + dn_fwd_list_push_front (&list, (char *)items [2]); + dn_fwd_list_push_front (&list, (char *)items [1]); + dn_fwd_list_push_front (&list, (char *)items [0]); + + if (*dn_fwd_list_front_t (&list, char *) != items [0]) + return FAILED ("push_front failed"); + + dn_fwd_list_pop_front (&list); + + if (*dn_fwd_list_front_t (&list, char *) != items [1]) + return FAILED ("pop_front failed #1"); + + dn_fwd_list_pop_front (&list); + + if (*dn_fwd_list_front_t (&list, char *) != items [2]) + return FAILED ("pop_front failed #2"); + + dn_fwd_list_pop_front (&list); + + dn_fwd_list_dispose (&list); + + dn_fwd_list_custom_init (&list, DN_DEFAULT_ALLOCATOR); + + dn_fwd_list_push_front (&list, &dispose_count); + dn_fwd_list_push_front (&list, &dispose_count); + dn_fwd_list_push_front (&list, &dispose_count); + + dn_fwd_list_custom_pop_front (&list, test_fwd_list_dispose_func); + + if (dispose_count == 0) + return FAILED ("pop_front dispose count failed #1"); + + dn_fwd_list_custom_dispose (&list, test_fwd_list_dispose_func); + + if (dispose_count != 3) + return FAILED ("pop_front dispose count failed #2"); + + return OK; +} + +static +RESULT +test_fwd_list_resize (void) +{ + uint32_t dispose_count = 0; + dn_fwd_list_t *list = dn_fwd_list_custom_alloc (DN_DEFAULT_ALLOCATOR); + + for (uint32_t i = 0; i < 100; i++) + dn_fwd_list_push_front (list, &dispose_count); + + dn_fwd_list_custom_resize (list, 90, test_fwd_list_dispose_func); + + if (dispose_count != 10) + return FAILED ("failed resize #1"); + + dispose_count = 0; + dn_fwd_list_custom_resize (list, 10, test_fwd_list_dispose_func); + + if (dispose_count != 80) + return FAILED ("failed resize #2"); + + dispose_count = 0; + + dn_fwd_list_custom_free (list, test_fwd_list_dispose_func); + + if (dispose_count != 10) + return FAILED ("failed free"); + + return OK; +} + +static +uint32_t fwd_list_size (dn_fwd_list_t *list) +{ + uint32_t size = 0; + for (dn_fwd_list_node_t *next = list->head; next; next = next->next) + size ++; + return size; +} + +static +RESULT +test_fwd_list_remove (void) +{ + uint32_t dispose_count = 0; + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_fwd_list_t *list = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [2]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [3]); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [2]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [3]); + + // Remove all "second" + dn_fwd_list_remove (list, items [1]); + + if (fwd_list_size (list) != 6) + return FAILED ("remove failed, incorrect size #1"); + + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [1])) + return FAILED ("remove failed, found removed item %s #1", item); + } DN_FWD_LIST_FOREACH_END; + + // Remove all "first" + dn_fwd_list_remove (list, items [0]); + + if (fwd_list_size (list) != 4) + return FAILED ("remove failed, incorrect size #2"); + + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [0])) + return FAILED ("remove failed, found removed item %s #2", item); + } DN_FWD_LIST_FOREACH_END; + + // Remove all "fourth" + dn_fwd_list_remove (list, items [3]); + + if (fwd_list_size (list) != 2) + return FAILED ("remove failed, incorrect size #3"); + + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [3])) + return FAILED ("remove failed, found removed item %s #3", item); + } DN_FWD_LIST_FOREACH_END; + + // "fourth" already removed. + dn_fwd_list_remove (list, items [3]); + + // Validate that only "third" is left. + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (strcmp (item, items [2])) + return FAILED ("remove failed, unexpected item %s #4", item); + } DN_FWD_LIST_FOREACH_END; + + dn_fwd_list_free (list); + + list = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + dn_fwd_list_insert_after (dn_fwd_list_end (list), &dispose_count); + + dn_fwd_list_custom_remove (list, &dispose_count, test_fwd_list_dispose_func); + if (dispose_count != 4) + return FAILED ("custom remove failed, incorrect dispose count"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_remove_if (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_fwd_list_t *list = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [2]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [3]); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [2]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [3]); + + // Remove all "second" + dn_fwd_list_remove_if (list, items [1], test_fwd_list_remove_if_func); + + if (fwd_list_size (list) != 6) + return FAILED ("remove failed, incorrect size #1"); + + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [1])) + return FAILED ("remove failed, found removed item %s #1", item); + } DN_FWD_LIST_FOREACH_END; + + // Remove all "first" + dn_fwd_list_remove_if (list, items [0], test_fwd_list_remove_if_func); + + if (fwd_list_size (list) != 4) + return FAILED ("remove failed, incorrect size #2"); + + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [0])) + return FAILED ("remove failed, found removed item %s #2", item); + } DN_FWD_LIST_FOREACH_END; + + // Remove all "fourth" + dn_fwd_list_remove_if (list, items [3], test_fwd_list_remove_if_func); + + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [3])) + return FAILED ("remove failed, found removed item %s #3", item); + } DN_FWD_LIST_FOREACH_END; + + // "fourth" already removed. + dn_fwd_list_remove_if (list, items [3], test_fwd_list_remove_if_func); + + if (fwd_list_size (list) != 2) + return FAILED ("remove failed, incorrect size #3"); + + // Validate that only "third" is left. + DN_FWD_LIST_FOREACH_BEGIN (char *, item, list) { + if (strcmp (item, items [2])) + return FAILED ("remove failed, unexpected item %s #4", item); + } DN_FWD_LIST_FOREACH_END; + + dn_fwd_list_free (list); + + list = dn_fwd_list_alloc (); + + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [0]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [1]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [2]); + dn_fwd_list_insert_after (dn_fwd_list_end (list), (char *)items [3]); + + test_fwd_list_dispose_count = 0; + dn_fwd_list_custom_remove_if (list, items [2], test_fwd_list_remove_if_func, test_fwd_list_dispose_count_func); + if (test_fwd_list_dispose_count != 1) + return FAILED ("custom remove if failed, incorrect dispose count"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_reverse (void) +{ + uint32_t count = N_ELEMS; + dn_fwd_list_t *list = dn_fwd_list_alloc (); + + for (uint32_t i = 0; i < N_ELEMS; ++i) + dn_fwd_list_insert_after (dn_fwd_list_end (list), INT32_TO_POINTER (i)); + + dn_fwd_list_reverse (list); + + DN_FWD_LIST_FOREACH_BEGIN (void *, data, list) { + if (POINTER_TO_INT32 (data) != count - 1) + return FAILED ("reverse failed #1"); + count--; + } DN_FWD_LIST_FOREACH_END; + + if (count != 0) + return FAILED ("reverse failed #2"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_for_each (void) +{ + uint32_t count = 0; + dn_fwd_list_t *list = dn_fwd_list_alloc (); + + for (uint32_t i = 0; i < N_ELEMS; ++i) + dn_fwd_list_insert_after (dn_fwd_list_before_begin (list), INT32_TO_POINTER (i)); + + dn_fwd_list_for_each (list, test_fwd_list_foreach_func, &count); + if (count != N_ELEMS) + return FAILED ("for_each failed"); + + dn_fwd_list_free (list); + + return OK; +} + +static +bool +fwd_list_verify_sort ( + dn_fwd_list_t *list, + int32_t len) +{ + int32_t prev = POINTER_TO_INT32 (*dn_fwd_list_front (list)); + dn_fwd_list_pop_front (list); + len--; + + DN_FWD_LIST_FOREACH_BEGIN (void *, item, list) { + int32_t curr = POINTER_TO_INT32 (item); + if (prev > curr) + return false; + prev = curr; + + if (len == 0) + return false; + len--; + } DN_FWD_LIST_FOREACH_END; + + return len == 0; +} + +static +RESULT +test_fwd_list_sort (void) +{ + int32_t i, j, mul; + dn_fwd_list_t *list = dn_fwd_list_alloc (); + + for (i = 0; i < N_ELEMS; ++i) + dn_fwd_list_push_front (list, INT32_TO_POINTER (i)); + + dn_fwd_list_sort (list, test_fwd_list_sort_compare); + if (!fwd_list_verify_sort (list, N_ELEMS)) + return FAILED ("decreasing list"); + + dn_fwd_list_free (list); + + list = dn_fwd_list_alloc (); + for (i = 0; i < N_ELEMS; ++i) + dn_fwd_list_push_front (list, INT32_TO_POINTER (-i)); + dn_fwd_list_sort (list, test_fwd_list_sort_compare); + if (!fwd_list_verify_sort (list, N_ELEMS)) + return FAILED ("increasing list"); + + dn_fwd_list_free (list); + + list = dn_fwd_list_alloc (); + dn_fwd_list_push_front (list, INT32_TO_POINTER (0)); + for (i = 1; i < N_ELEMS; ++i) { + dn_fwd_list_push_front (list, INT32_TO_POINTER (-i)); + dn_fwd_list_push_front (list, INT32_TO_POINTER (i)); + } + + dn_fwd_list_sort (list, test_fwd_list_sort_compare); + if (!fwd_list_verify_sort (list, 2*N_ELEMS-1)) + return FAILED ("alternating list"); + + dn_fwd_list_free (list); + + list = dn_fwd_list_alloc (); + mul = 1; + for (i = 1; i < N_ELEMS; ++i) { + mul = -mul; + for (j = 0; j < i; ++j) + dn_fwd_list_push_front (list, INT32_TO_POINTER (mul * j)); + } + dn_fwd_list_sort (list, test_fwd_list_sort_compare); + if (!fwd_list_verify_sort (list, (N_ELEMS*N_ELEMS - N_ELEMS)/2)) + return FAILED ("wavering list"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_find (void) +{ + dn_fwd_list_t *list = dn_fwd_list_alloc (); + + dn_fwd_list_push_front (list, (char*)"three"); + dn_fwd_list_push_front (list, (char*)"two"); + dn_fwd_list_push_front (list, (char*)"one"); + + char *data = (char*)"four"; + dn_fwd_list_insert_after (dn_fwd_list_end (list), data); + + dn_fwd_list_it_t found = dn_fwd_list_find (list, data); + + if (*dn_fwd_list_it_data_t (found, char *) != data) + return FAILED ("find failed #1"); + + found = dn_fwd_list_find (list, NULL); + if (found.it != dn_fwd_list_end (list).it) + return FAILED ("find failed #2"); + + dn_fwd_list_free (list); + + return OK; +} + +static +RESULT +test_fwd_list_iterator (void) +{ + uint32_t count = 0; + dn_fwd_list_t *list = dn_fwd_list_alloc (); + + for (uint32_t i = 0; i < N_ELEMS; ++i) + dn_fwd_list_insert_after (dn_fwd_list_end (list), INT32_TO_POINTER (i)); + + DN_FWD_LIST_FOREACH_BEGIN (void *, data, list) { + if (POINTER_TO_INT32 (data) != count) + return FAILED ("foreach iterator failed #1"); + count++; + } DN_FWD_LIST_FOREACH_END; + + if (count != N_ELEMS) + return FAILED ("foreach iterator failed #2"); + + dn_fwd_list_free (list); + + return OK; +} + +//ADD MORE TEST USING CUSTOM ALLOCATORS. + +static +RESULT +test_fwd_list_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_fwd_list_memory_end_snapshot); + if ( _CrtMemDifference(&dn_fwd_list_memory_diff_snapshot, &dn_fwd_list_memory_start_snapshot, &dn_fwd_list_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &dn_fwd_list_memory_diff_snapshot ); + return FAILED ("memory leak detected!"); + } +#endif + return OK; +} + +static Test dn_fwd_list_tests [] = { + {"test_fwd_list_setup", test_fwd_list_setup}, + {"test_fwd_list_alloc", test_fwd_list_alloc}, + {"test_fwd_list_init", test_fwd_list_init}, + {"test_fwd_list_free", test_fwd_list_free}, + {"test_fwd_list_dispose", test_fwd_list_dispose}, + {"test_fwd_list_front", test_fwd_list_front}, + {"test_fwd_list_empty", test_fwd_list_empty}, + {"test_fwd_list_max_size", test_fwd_list_max_size}, + {"test_fwd_list_clear", test_fwd_list_clear}, + {"test_fwd_list_insert_after", test_fwd_list_insert_after}, + {"test_fwd_list_insert_range_after", test_fwd_list_insert_range_after}, + {"test_fwd_list_erase_after", test_fwd_list_erase_after}, + {"test_fwd_list_push_front", test_fwd_list_push_front}, + {"test_fwd_list_pop_front", test_fwd_list_pop_front}, + {"test_fwd_list_resize", test_fwd_list_resize}, + {"test_fwd_list_remove", test_fwd_list_remove}, + {"test_fwd_list_remove_if", test_fwd_list_remove_if}, + {"test_fwd_list_reverse", test_fwd_list_reverse}, + {"test_fwd_list_for_each", test_fwd_list_for_each}, + {"test_fwd_list_sort", test_fwd_list_sort}, + {"test_fwd_list_find", test_fwd_list_find}, + {"test_fwd_list_iterator", test_fwd_list_iterator}, + {"test_fwd_list_teardown", test_fwd_list_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(dn_fwd_list_tests_init, dn_fwd_list_tests) diff --git a/src/mono/mono/eventpipe/test/dn-list-tests.c b/src/mono/mono/eventpipe/test/dn-list-tests.c new file mode 100644 index 0000000..710a32b --- /dev/null +++ b/src/mono/mono/eventpipe/test/dn-list-tests.c @@ -0,0 +1,1106 @@ +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include + + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState dn_list_memory_start_snapshot; +static _CrtMemState dn_list_memory_end_snapshot; +static _CrtMemState dn_list_memory_diff_snapshot; +#endif + +#define N_ELEMS 101 +#define POINTER_TO_INT32(v) ((int32_t)(ptrdiff_t)(v)) +#define INT32_TO_POINTER(v) ((void *)(ptrdiff_t)(v)) + +static +void +DN_CALLBACK_CALLTYPE +test_list_dispose_func (void *data) +{ + (*(uint32_t *)data)++; +} + +static int32_t test_list_dispose_count = 0; + +static +void +DN_CALLBACK_CALLTYPE +test_list_dispose_count_func (void *data) +{ + test_list_dispose_count++; +} + +static +bool +DN_CALLBACK_CALLTYPE +test_list_remove_if_func (const void *data, const void *user_data) +{ + return !strcmp ((const char *)data, (const char *)user_data); +} + +static +void +DN_CALLBACK_CALLTYPE +test_list_foreach_func ( + void *data, + void *user_data) +{ + (*(uint32_t *)user_data)++; +} + +static +int32_t +DN_CALLBACK_CALLTYPE +test_list_sort_compare ( + const void *p1, + const void *p2) +{ + return POINTER_TO_INT32 (p1) - POINTER_TO_INT32 (p2); +} + +static +bool +DN_CALLBACK_CALLTYPE +test_list_find_func ( + const void *a, + const void *b) +{ + if (!a || !b) + return false; + + return !strcmp ((const char *)a, (const char *)b); +} + +static +RESULT +test_list_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_list_memory_start_snapshot); +#endif + return OK; +} + +static +RESULT +test_list_alloc (void) +{ + dn_list_t *list = dn_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_init (void) +{ + dn_list_t list; + if (!dn_list_init (&list)) + return FAILED ("failed to init list"); + + dn_list_dispose (&list); + + return OK; +} + +static +RESULT +test_list_free (void) +{ + uint32_t dispose_count = 0; + dn_list_t *list = dn_list_custom_alloc (DN_DEFAULT_ALLOCATOR); + if (!list) + return FAILED ("failed to custom alloc list"); + + dn_list_insert (dn_list_end (list), &dispose_count); + dn_list_insert (dn_list_end (list), &dispose_count); + + dn_list_custom_free (list, test_list_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on free"); + + return OK; +} + +static +RESULT +test_list_dispose (void) +{ + uint32_t dispose_count = 0; + dn_list_t list; + if (!dn_list_custom_init (&list, DN_DEFAULT_ALLOCATOR)) + return FAILED ("failed to custom init list"); + + dn_list_insert (dn_list_end (&list), &dispose_count); + dn_list_insert (dn_list_end (&list), &dispose_count); + + dn_list_custom_dispose (&list, test_list_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on free"); + + return OK; +} + +static +RESULT +test_list_front (void) +{ + const char * items[] = { "first", "second" }; + + dn_list_t *list = dn_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + + if (*dn_list_front_t (list, char *) != items [0]) + return FAILED ("failed list front #1"); + + dn_list_insert (dn_list_begin (list), (char *)items [1]); + + if (*dn_list_front_t (list, char *) != items [1]) + return FAILED ("failed list front #2"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_empty (void) +{ + const char * items[] = { "first", "second" }; + + dn_list_t *list = dn_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + if (!dn_list_empty (list)) + return FAILED ("failed empty #1"); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + + if (dn_list_empty (list)) + return FAILED ("failed empty #2"); + + dn_list_insert (dn_list_end (list), (char *)items [1]); + + if (dn_list_empty (list)) + return FAILED ("failed empty #3"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_max_size (void) +{ + dn_list_t *list = dn_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + if (dn_list_max_size (list) != UINT32_MAX) + return FAILED ("max_size failed"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_clear (void) +{ + uint32_t dispose_count = 0; + const char * items[] = { "first", "second" }; + + dn_list_t *list = dn_list_alloc (); + if (!list) + return FAILED ("failed to alloc list"); + + if (!dn_list_empty (list)) + return FAILED ("failed empty #1"); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + + if (dn_list_empty (list)) + return FAILED ("failed empty #2"); + + dn_list_insert (dn_list_end (list), (char *)items [1]); + + dn_list_clear (list); + + if (!dn_list_empty (list)) + return FAILED ("failed empty #3"); + + dn_list_free (list); + + list = dn_list_custom_alloc (DN_DEFAULT_ALLOCATOR); + + dn_list_insert (dn_list_end (list), &dispose_count); + dn_list_insert (dn_list_end (list), &dispose_count); + + dn_list_custom_clear (list, test_list_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on clear"); + + dispose_count = 0; + dn_list_custom_free (list, test_list_dispose_func); + + if (dispose_count != 0) + return FAILED ("invalid dispose count on clear/free"); + + return OK; +} + +static +RESULT +test_list_insert (void) +{ + const char *items[] = { "first", "second" }; + + dn_list_t *list = dn_list_alloc (); + if (!dn_list_insert (dn_list_end (list), (char *)items [0]).result) + return FAILED ("insert failed #1"); + + if (!dn_list_insert (dn_list_end (list), (char *)items [1]).result) + return FAILED ("insert failed #2"); + + size_t i = 0; + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (strcmp (item, items [i])) + return FAILED ("insert, found %s, expected %s #1", item, items [i]); + i++; + } DN_LIST_FOREACH_END; + + dn_list_free (list); + + list = dn_list_alloc (); + if (!dn_list_insert (dn_list_end (list), (char *)items [1]).result) + return FAILED ("insert failed #3"); + + if (!dn_list_insert (dn_list_begin (list), (char *)items [0]).result) + return FAILED ("insert failed #4"); + + i = 0; + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (strcmp (item, items [i])) + return FAILED ("insert, found %s, expected %s #1", item, items [i]); + i++; + } DN_LIST_FOREACH_END; + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_insert_range (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_list_t *list1 = dn_list_alloc (); + dn_list_t *list2 = dn_list_alloc (); + + dn_list_insert (dn_list_end (list1), (char *)items [0]); + dn_list_insert (dn_list_end (list2), (char *)items [1]); + + if (!dn_list_insert_range (dn_list_end (list1), dn_list_begin (list2), dn_list_end (list2)).result) + return FAILED ("insert_range failed #1"); + + size_t i = 0; + DN_LIST_FOREACH_BEGIN (char *, item, list1) { + if (strcmp (item, items [i])) + return FAILED ("insert_range, found %s, expected %s #1", item, items [i]); + i++; + } DN_LIST_FOREACH_END; + + dn_list_free (list1); + dn_list_free (list2); + + list1 = dn_list_alloc (); + list2 = dn_list_alloc (); + + dn_list_insert (dn_list_end (list1), (char *)items [1]); + dn_list_insert (dn_list_end (list2), (char *)items [0]); + + if (!dn_list_insert_range (dn_list_begin (list1), dn_list_begin (list2), dn_list_end (list2)).result) + return FAILED ("insert_range failed #2"); + + i = 0; + DN_LIST_FOREACH_BEGIN (char *, item, list1) { + if (strcmp (item, items [i])) + return FAILED ("insert_range, found %s, expected %s #2", item, items [i]); + i++; + } DN_LIST_FOREACH_END; + + dn_list_free (list1); + dn_list_free (list2); + + list1 = dn_list_alloc (); + list2 = dn_list_alloc (); + + dn_list_insert (dn_list_end (list1), (char *)items [0]); + dn_list_insert (dn_list_end (list1), (char *)items [1]); + dn_list_insert (dn_list_end (list1), (char *)items [3]); + dn_list_insert (dn_list_end (list2), (char *)items [2]); + + dn_list_it_t it = dn_list_begin (list1); + it = dn_list_it_next_n (it, 2); + + if (!dn_list_insert_range (it, dn_list_begin (list2), dn_list_end (list2)).result) + return FAILED ("insert_range failed #2"); + + i = 0; + DN_LIST_FOREACH_BEGIN (char *, item, list1) { + if (strcmp (item, items [i])) + return FAILED ("insert_range, found %s, expected %s #2", item, items [i]); + i++; + } DN_LIST_FOREACH_END; + + dn_list_free (list1); + dn_list_free (list2); + + return OK; +} + +static +RESULT +test_list_erase (void) +{ + uint32_t dispose_count = 0; + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_list_t *list = dn_list_alloc (); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + dn_list_insert (dn_list_end (list), (char *)items [1]); + + // Remove first. + dn_list_erase (dn_list_begin (list)); + + if (!list->head || !list->head->data || strcmp (list->head->data, "second") || list->head->next) + return FAILED ("erase failed #1"); + + dn_list_insert (dn_list_end (list), (char *)items [2]); + dn_list_insert (dn_list_end (list), (char *)items [3]); + + dn_list_it_t it = dn_list_begin (list); + dn_list_it_advance (&it,1); + + // Remove third. + dn_list_erase (it); + + it = dn_list_begin (list); + dn_list_it_advance (&it,1); + + // Remove forth. + dn_list_erase (it); + + if (!list->head || !list->head->data || strcmp (list->head->data, "second") || list->head->next) + return FAILED ("erase failed #2"); + + dn_list_free (list); + + list = dn_list_alloc (); + + dn_list_insert (dn_list_end (list), &dispose_count); + dn_list_insert (dn_list_end (list), &dispose_count); + dn_list_insert (dn_list_end (list), &dispose_count); + + dn_list_custom_erase (dn_list_begin (list), test_list_dispose_func); + dn_list_custom_erase (dn_list_begin (list), test_list_dispose_func); + + if (dispose_count != 2) + return FAILED ("erase failed #3"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_push_front (void) +{ + const char *items[] = { "a", "b", "c"}; + + dn_list_t list; + + dn_list_init (&list); + + dn_list_push_front (&list, (char *)items [0]); + if (*dn_list_front_t (&list, char *) != items [0]) + return FAILED ("push_front failed #1"); + + dn_list_push_front (&list, (char *)items [1]); + if (*dn_list_front_t (&list, char *) != items [1]) + return FAILED ("push_front failed #2"); + + dn_list_push_front (&list, (char *)items [2]); + + uint32_t i = 2; + DN_LIST_FOREACH_BEGIN (char *, item, &list) { + if (strcmp (item, items [i])) + return FAILED ("push_front failed, found %s, expected %s #2", item, items [i]); + i--; + } DN_LIST_FOREACH_END; + + dn_list_dispose (&list); + + return OK; +} + +static +RESULT +test_list_pop_front (void) +{ + uint32_t dispose_count = 0; + const char *items[] = { "a", "b", "c"}; + + dn_list_t list; + + dn_list_custom_init (&list, DN_DEFAULT_ALLOCATOR); + + dn_list_push_front (&list, (char *)items [2]); + dn_list_push_front (&list, (char *)items [1]); + dn_list_push_front (&list, (char *)items [0]); + + if (*dn_list_front_t (&list, char *) != items [0]) + return FAILED ("push_front failed"); + + dn_list_pop_front (&list); + + if (*dn_list_front_t (&list, char *) != items [1]) + return FAILED ("pop_front failed #1"); + + dn_list_pop_front (&list); + + if (*dn_list_front_t (&list, char *) != items [2]) + return FAILED ("pop_front failed #2"); + + dn_list_pop_front (&list); + + dn_list_dispose (&list); + + dn_list_custom_init (&list, DN_DEFAULT_ALLOCATOR); + + dn_list_push_front (&list, &dispose_count); + dn_list_push_front (&list, &dispose_count); + dn_list_push_front (&list, &dispose_count); + + dn_list_custom_pop_front (&list, test_list_dispose_func); + + if (dispose_count == 0) + return FAILED ("pop_front dispose count failed #1"); + + dn_list_custom_dispose (&list, test_list_dispose_func); + + if (dispose_count != 3) + return FAILED ("pop_front dispose count failed #2"); + + return OK; +} + +static +RESULT +test_list_push_back (void) +{ + const char *items[] = { "a", "b", "c"}; + + dn_list_t list; + + dn_list_init (&list); + + dn_list_push_back (&list, (char *)items [0]); + if (*dn_list_back_t (&list, char *) != items [0]) + return FAILED ("push_back failed #1"); + + dn_list_push_back (&list, (char *)items [1]); + if (*dn_list_back_t (&list, char *) != items [1]) + return FAILED ("push_back failed #2"); + + dn_list_push_back (&list, (char *)items [2]); + + uint32_t i = 0; + DN_LIST_FOREACH_BEGIN (char *, item, &list) { + if (strcmp (item, items [i])) + return FAILED ("push_back failed, found %s, expected %s #2", item, items [i]); + i++; + } DN_LIST_FOREACH_END; + + dn_list_dispose (&list); + + return OK; +} + +static +RESULT +test_list_pop_back (void) +{ + uint32_t dispose_count = 0; + const char *items[] = { "a", "b", "c"}; + + dn_list_t list; + + dn_list_custom_init (&list, DN_DEFAULT_ALLOCATOR); + + dn_list_push_back (&list, (char *)items [2]); + dn_list_push_back (&list, (char *)items [1]); + dn_list_push_back (&list, (char *)items [0]); + + if (*dn_list_back_t (&list, char *) != items [0]) + return FAILED ("push_back failed"); + + dn_list_pop_back (&list); + + if (*dn_list_back_t (&list, char *) != items [1]) + return FAILED ("pop_back failed #1"); + + dn_list_pop_back (&list); + + if (*dn_list_front_t (&list, char *) != items [2]) + return FAILED ("pop_back failed #2"); + + dn_list_pop_back (&list); + + dn_list_dispose (&list); + + dn_list_custom_init (&list, DN_DEFAULT_ALLOCATOR); + + dn_list_push_back (&list, &dispose_count); + dn_list_push_back (&list, &dispose_count); + dn_list_push_back (&list, &dispose_count); + + dn_list_custom_pop_back (&list, test_list_dispose_func); + + if (dispose_count == 0) + return FAILED ("pop_back dispose count failed #1"); + + dn_list_custom_dispose (&list, test_list_dispose_func); + + if (dispose_count != 3) + return FAILED ("pop_back dispose count failed #2"); + + return OK; +} + +static +RESULT +test_list_resize (void) +{ + uint32_t dispose_count = 0; + dn_list_t *list = dn_list_custom_alloc (DN_DEFAULT_ALLOCATOR); + + for (uint32_t i = 0; i < 10; i++) + dn_list_push_front (list, &dispose_count); + + dn_list_custom_resize (list, 0, test_list_dispose_func); + + if (dispose_count != 10) + return FAILED ("failed resize #1"); + + for (uint32_t i = 0; i < 100; i++) + dn_list_push_front (list, &dispose_count); + + dispose_count = 0; + dn_list_custom_resize (list, 90, test_list_dispose_func); + + if (dispose_count != 10) + return FAILED ("failed resize #2"); + + dispose_count = 0; + dn_list_custom_resize (list, 10, test_list_dispose_func); + + if (dispose_count != 80) + return FAILED ("failed resize #3"); + + dispose_count = 0; + + dn_list_custom_free (list, test_list_dispose_func); + + if (dispose_count != 10) + return FAILED ("failed free"); + + return OK; +} + +static +RESULT +test_list_remove (void) +{ + uint32_t dispose_count = 0; + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_list_t *list = dn_list_alloc (); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + dn_list_insert (dn_list_end (list), (char *)items [1]); + dn_list_insert (dn_list_end (list), (char *)items [2]); + dn_list_insert (dn_list_end (list), (char *)items [3]); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + dn_list_insert (dn_list_end (list), (char *)items [1]); + dn_list_insert (dn_list_end (list), (char *)items [2]); + dn_list_insert (dn_list_end (list), (char *)items [3]); + + // Remove all "second" + dn_list_remove (list, items [1]); + + if (dn_list_size (list) != 6) + return FAILED ("remove failed, incorrect size #1"); + + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [1])) + return FAILED ("remove failed, found removed item %s #1", item); + } DN_LIST_FOREACH_END; + + // Remove all "first" + dn_list_remove (list, items [0]); + + if (dn_list_size (list) != 4) + return FAILED ("remove failed, incorrect size #2"); + + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [0])) + return FAILED ("remove failed, found removed item %s #2", item); + } DN_LIST_FOREACH_END; + + // Remove all "fourth" + dn_list_remove (list, items [3]); + + if (dn_list_size (list) != 2) + return FAILED ("remove failed, incorrect size #3"); + + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [3])) + return FAILED ("remove failed, found removed item %s #3", item); + } DN_LIST_FOREACH_END; + + // "fourth" already removed. + dn_list_remove (list, items [3]); + + // Validate that only "third" is left. + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (strcmp (item, items [2])) + return FAILED ("remove failed, unexpected item %s #4", item); + } DN_LIST_FOREACH_END; + + dn_list_free (list); + + list = dn_list_alloc (); + + dn_list_insert (dn_list_end (list), &dispose_count); + dn_list_insert (dn_list_end (list), &dispose_count); + dn_list_insert (dn_list_end (list), &dispose_count); + dn_list_insert (dn_list_end (list), &dispose_count); + + dn_list_custom_remove (list, &dispose_count, test_list_dispose_func); + if (dispose_count != 4) + return FAILED ("custom remove failed, incorrect dispose count"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_remove_if (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_list_t *list = dn_list_alloc (); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + dn_list_insert (dn_list_end (list), (char *)items [1]); + dn_list_insert (dn_list_end (list), (char *)items [2]); + dn_list_insert (dn_list_end (list), (char *)items [3]); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + dn_list_insert (dn_list_end (list), (char *)items [1]); + dn_list_insert (dn_list_end (list), (char *)items [2]); + dn_list_insert (dn_list_end (list), (char *)items [3]); + + // Remove all "second" + dn_list_remove_if (list, items [1], test_list_remove_if_func); + + if (dn_list_size (list) != 6) + return FAILED ("remove failed, incorrect size #1"); + + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [1])) + return FAILED ("remove failed, found removed item %s #1", item); + } DN_LIST_FOREACH_END; + + // Remove all "first" + dn_list_remove_if (list, items [0], test_list_remove_if_func); + + if (dn_list_size (list) != 4) + return FAILED ("remove failed, incorrect size #2"); + + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [0])) + return FAILED ("remove failed, found removed item %s #2", item); + } DN_LIST_FOREACH_END; + + // Remove all "fourth" + dn_list_remove_if (list, items [3], test_list_remove_if_func); + + if (dn_list_size (list) != 2) + return FAILED ("remove failed, incorrect size #3"); + + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (!strcmp (item, items [3])) + return FAILED ("remove failed, found removed item %s #3", item); + } DN_LIST_FOREACH_END; + + // "fourth" already removed. + dn_list_remove_if (list, items [3], test_list_remove_if_func); + + // Validate that only "third" is left. + DN_LIST_FOREACH_BEGIN (char *, item, list) { + if (strcmp (item, items [2])) + return FAILED ("remove failed, unexpected item %s #4", item); + } DN_LIST_FOREACH_END; + + dn_list_free (list); + + list = dn_list_alloc (); + + dn_list_insert (dn_list_end (list), (char *)items [0]); + dn_list_insert (dn_list_end (list), (char *)items [1]); + dn_list_insert (dn_list_end (list), (char *)items [2]); + dn_list_insert (dn_list_end (list), (char *)items [3]); + + test_list_dispose_count = 0; + dn_list_custom_remove_if (list, items [2], test_list_remove_if_func, test_list_dispose_count_func); + if (test_list_dispose_count != 1) + return FAILED ("custom remove if failed, incorrect dispose count"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_reverse (void) +{ + uint32_t count = N_ELEMS; + dn_list_t *list = dn_list_alloc (); + + for (uint32_t i = 0; i < N_ELEMS; ++i) + dn_list_insert (dn_list_end (list), INT32_TO_POINTER (i)); + + dn_list_reverse (list); + + DN_LIST_FOREACH_BEGIN (void *, data, list) { + if (POINTER_TO_INT32 (data) != count - 1) + return FAILED ("reverse failed #1"); + count--; + } DN_LIST_FOREACH_END; + + if (count != 0) + return FAILED ("reverse failed #2"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_for_each (void) +{ + uint32_t count = 0; + dn_list_t *list = dn_list_alloc (); + + for (uint32_t i = 0; i < N_ELEMS; ++i) + dn_list_insert (dn_list_begin (list), INT32_TO_POINTER (i)); + + dn_list_for_each (list, test_list_foreach_func, &count); + if (count != N_ELEMS) + return FAILED ("for_each failed"); + + dn_list_free (list); + + return OK; +} + +static +bool +list_verify_sort ( + dn_list_t *list, + int32_t len) +{ + int32_t prev = POINTER_TO_INT32 (*dn_list_front (list)); + dn_list_pop_front (list); + len--; + + DN_LIST_FOREACH_BEGIN (void *, item, list) { + int32_t curr = POINTER_TO_INT32 (item); + if (prev > curr) + return false; + prev = curr; + + if (len == 0) + return false; + len--; + } DN_LIST_FOREACH_END; + + return len == 0; +} + +static +RESULT +test_list_sort (void) +{ + int32_t i, j, mul; + dn_list_t *list = dn_list_alloc (); + + for (i = 0; i < N_ELEMS; ++i) + dn_list_push_front (list, INT32_TO_POINTER (i)); + + dn_list_sort (list, test_list_sort_compare); + if (!list_verify_sort (list, N_ELEMS)) + return FAILED ("decreasing list"); + + dn_list_free (list); + + list = dn_list_alloc (); + for (i = 0; i < N_ELEMS; ++i) + dn_list_push_front (list, INT32_TO_POINTER (-i)); + dn_list_sort (list, test_list_sort_compare); + if (!list_verify_sort (list, N_ELEMS)) + return FAILED ("increasing list"); + + dn_list_free (list); + + list = dn_list_alloc (); + dn_list_push_front (list, INT32_TO_POINTER (0)); + for (i = 1; i < N_ELEMS; ++i) { + dn_list_push_front (list, INT32_TO_POINTER (-i)); + dn_list_push_front (list, INT32_TO_POINTER (i)); + } + + dn_list_sort (list, test_list_sort_compare); + if (!list_verify_sort (list, 2*N_ELEMS-1)) + return FAILED ("alternating list"); + + dn_list_free (list); + + list = dn_list_alloc (); + mul = 1; + for (i = 1; i < N_ELEMS; ++i) { + mul = -mul; + for (j = 0; j < i; ++j) + dn_list_push_front (list, INT32_TO_POINTER (mul * j)); + } + dn_list_sort (list, test_list_sort_compare); + if (!list_verify_sort (list, (N_ELEMS*N_ELEMS - N_ELEMS)/2)) + return FAILED ("wavering list"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_find (void) +{ + dn_list_t *list = dn_list_alloc (); + + dn_list_push_front (list, (char*)"three"); + dn_list_push_front (list, (char*)"two"); + dn_list_push_front (list, (char*)"one"); + + char *data = (char*)"four"; + dn_list_insert (dn_list_end (list), data); + + dn_list_it_t found1 = dn_list_find (list, data); + dn_list_it_t found2 = dn_list_custom_find (list, data, test_list_find_func); + + if (*dn_list_it_data_t (found1, char *) != data || *dn_list_it_data_t (found2, char *) != data) + return FAILED ("find failed #1"); + + found1 = dn_list_find (list, NULL); + found2 = dn_list_custom_find (list, NULL, test_list_find_func); + if (found1.it != dn_list_end (list).it || found2.it != dn_list_end (list).it) + return FAILED ("find failed #2"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_find_erase (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_list_t *list = dn_list_alloc (); + + dn_list_push_front (list, items [2]); + dn_list_push_front (list, items [1]); + dn_list_push_front (list, items [0]); + + dn_list_insert (dn_list_end (list), items [3]); + + dn_list_it_t found = dn_list_find (list, items [1]); + if (dn_list_it_end (found)) + return FAILED ("find failed #1"); + + if (*dn_list_it_data_t (found, char *) != items [1]) + return FAILED ("find failed #2"); + + dn_list_it_t erased = dn_list_erase (found); + if (dn_list_it_end (erased)) + return FAILED ("erase failed"); + + found = dn_list_find (list, items [1]); + if (!dn_list_it_end (found)) + return FAILED ("find failed #3"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_iterator (void) +{ + uint32_t count = 0; + dn_list_t *list = dn_list_alloc (); + + for (uint32_t i = 0; i < N_ELEMS; ++i) + dn_list_insert (dn_list_end (list), INT32_TO_POINTER (i)); + + DN_LIST_FOREACH_BEGIN (void *, data, list) { + if (POINTER_TO_INT32 (data) != count) + return FAILED ("foreach iterator failed #1"); + count++; + } DN_LIST_FOREACH_END; + + if (count != N_ELEMS) + return FAILED ("foreach iterator failed #2"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_rev_iterator (void) +{ + uint32_t count = N_ELEMS; + dn_list_t *list = dn_list_alloc (); + + for (uint32_t i = 0; i < N_ELEMS; ++i) + dn_list_insert (dn_list_end (list), INT32_TO_POINTER (i)); + + DN_LIST_FOREACH_RBEGIN (void *, data, list) { + if (POINTER_TO_INT32 (data) != count - 1) + return FAILED ("foreach rev iterator failed #1"); + count--; + } DN_LIST_FOREACH_END; + + if (count != 0) + return FAILED ("foreach rev iterator failed #2"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_iterate_remove (void) +{ + dn_list_t *list = dn_list_alloc (); + + for (uint32_t i = 0; i < N_ELEMS; ++i) + dn_list_insert (dn_list_end (list), INT32_TO_POINTER (i)); + + for (dn_list_it_t it = dn_list_begin (list); !dn_list_it_end (it); ) { + void *data = *dn_list_it_data (it); + it = dn_list_it_next (it); + dn_list_remove (list, data); + } + + if (dn_list_size (list) != 0) + return FAILED ("iterate remove failed"); + + dn_list_free (list); + + return OK; +} + +static +RESULT +test_list_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_list_memory_end_snapshot); + if ( _CrtMemDifference(&dn_list_memory_diff_snapshot, &dn_list_memory_start_snapshot, &dn_list_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &dn_list_memory_diff_snapshot ); + return FAILED ("memory leak detected!"); + } +#endif + return OK; +} + +static Test dn_list_tests [] = { + {"test_list_setup", test_list_setup}, + {"test_list_alloc", test_list_alloc}, + {"test_list_init", test_list_init}, + {"test_list_free", test_list_free}, + {"test_list_dispose", test_list_dispose}, + {"test_list_front", test_list_front}, + {"test_list_empty", test_list_empty}, + {"test_list_max_size", test_list_max_size}, + {"test_list_clear", test_list_clear}, + {"test_list_insert", test_list_insert}, + {"test_list_insert_range", test_list_insert_range}, + {"test_list_erase", test_list_erase}, + {"test_list_push_front", test_list_push_front}, + {"test_list_pop_front", test_list_pop_front}, + {"test_list_push_back", test_list_push_back}, + {"test_list_pop_back", test_list_pop_back}, + {"test_list_resize", test_list_resize}, + {"test_list_remove", test_list_remove}, + {"test_list_remove_if", test_list_remove_if}, + {"test_list_reverse", test_list_reverse}, + {"test_list_for_each", test_list_for_each}, + {"test_list_sort", test_list_sort}, + {"test_list_find", test_list_find}, + {"test_list_find_erase", test_list_find_erase}, + {"test_list_iterator", test_list_iterator}, + {"test_list_rev_iterator", test_list_rev_iterator}, + {"test_list_iterate_remove", test_list_iterate_remove}, + {"test_list_teardown", test_list_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(dn_list_tests_init, dn_list_tests) diff --git a/src/mono/mono/eventpipe/test/dn-queue-tests.c b/src/mono/mono/eventpipe/test/dn-queue-tests.c new file mode 100644 index 0000000..39a35c5 --- /dev/null +++ b/src/mono/mono/eventpipe/test/dn-queue-tests.c @@ -0,0 +1,337 @@ +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include + + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState dn_queue_memory_start_snapshot; +static _CrtMemState dn_queue_memory_end_snapshot; +static _CrtMemState dn_queue_memory_diff_snapshot; +#endif + +#define N_ELEMS 101 +#define POINTER_TO_INT32(v) ((int32_t)(ptrdiff_t)(v)) +#define INT32_TO_POINTER(v) ((void *)(ptrdiff_t)(v)) + +static +void +DN_CALLBACK_CALLTYPE +test_queue_dispose_func (void *data) +{ + (*(uint32_t *)data)++; +} + +static +RESULT +test_queue_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_queue_memory_start_snapshot); +#endif + return OK; +} + +static +RESULT +test_queue_alloc (void) +{ + dn_queue_t *queue = dn_queue_alloc (); + if (!queue) + return FAILED ("failed to alloc queue"); + + dn_queue_free (queue); + + return OK; +} + +static +RESULT +test_queue_init (void) +{ + dn_queue_t queue; + if (!dn_queue_init (&queue)) + return FAILED ("failed to init queue"); + + dn_queue_dispose (&queue); + + return OK; +} + +static +RESULT +test_queue_free (void) +{ + uint32_t dispose_count = 0; + dn_queue_t *queue = dn_queue_custom_alloc (DN_DEFAULT_ALLOCATOR); + if (!queue) + return FAILED ("failed to custom alloc queue"); + + dn_queue_push (queue, &dispose_count); + dn_queue_push (queue, &dispose_count); + + dn_queue_custom_free (queue, test_queue_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on free"); + + return OK; +} + +static +RESULT +test_queue_dispose (void) +{ + uint32_t dispose_count = 0; + dn_queue_t queue; + if (!dn_queue_custom_init (&queue, DN_DEFAULT_ALLOCATOR)) + return FAILED ("failed to custom init queue"); + + dn_queue_push (&queue, &dispose_count); + dn_queue_push (&queue, &dispose_count); + + dn_queue_custom_dispose (&queue, test_queue_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on free"); + + return OK; +} + +static +RESULT +test_queue_front (void) +{ + const char * items[] = { "first", "second" }; + + dn_queue_t *queue = dn_queue_alloc (); + if (!queue) + return FAILED ("failed to alloc queue"); + + dn_queue_push (queue, (char *)items [0]); + + if (*dn_queue_front_t (queue, char *) != items [0]) + return FAILED ("failed queue front #1"); + + dn_queue_push (queue, (char *)items [1]); + + if (*dn_queue_front_t (queue, char *) != items [0]) + return FAILED ("failed queue front #2"); + + dn_queue_free (queue); + + return OK; +} + +static +RESULT +test_queue_back (void) +{ + const char * items[] = { "first", "second" }; + + dn_queue_t *queue = dn_queue_alloc (); + if (!queue) + return FAILED ("failed to alloc queue"); + + dn_queue_push (queue, (char *)items [0]); + + if (*dn_queue_back_t (queue, char *) != items [0]) + return FAILED ("failed queue front #1"); + + dn_queue_push (queue, (char *)items [1]); + + if (*dn_queue_back_t (queue, char *) != items [1]) + return FAILED ("failed queue front #2"); + + dn_queue_free (queue); + + return OK; +} + +static +RESULT +test_queue_empty (void) +{ + const char * items[] = { "first", "second" }; + + dn_queue_t *queue = dn_queue_alloc (); + if (!queue) + return FAILED ("failed to alloc queue"); + + if (!dn_queue_empty (queue)) + return FAILED ("failed empty #1"); + + dn_queue_push (queue, (char *)items [0]); + + if (dn_queue_empty (queue)) + return FAILED ("failed empty #2"); + + dn_queue_push (queue, (char *)items [1]); + + if (dn_queue_empty (queue)) + return FAILED ("failed empty #3"); + + dn_queue_pop (queue); + + if (dn_queue_empty (queue)) + return FAILED ("failed empty #4"); + + dn_queue_pop (queue); + + if (!dn_queue_empty (queue)) + return FAILED ("failed empty #5"); + + dn_queue_free (queue); + + return OK; +} + +static +RESULT +test_queue_size (void) +{ + dn_queue_t *queue = dn_queue_alloc (); + if (!queue) + return FAILED ("failed to alloc queue"); + + for (uint32_t i = 0; i < N_ELEMS; i++) + dn_queue_push_t (queue, uint32_t, i); + + if (dn_queue_size (queue) != N_ELEMS) + return FAILED ("failed queue size"); + + dn_queue_free (queue); + + return OK; +} + +static +RESULT +test_queue_push_pop (void) +{ + uint32_t dispose_count = 0; + dn_queue_t *queue = dn_queue_alloc (); + if (!queue) + return FAILED ("failed to alloc queue"); + + for (uint32_t i = 0; i < N_ELEMS; i++) { + if (!dn_queue_push_t (queue, uint32_t, i)) + return FAILED ("failed to push to queue"); + } + + if (*dn_queue_back_t (queue, uint32_t) != N_ELEMS - 1) + return FAILED ("incorrect back of queue"); + + uint32_t count; + for (count = 0; count < N_ELEMS && !dn_queue_empty (queue); count++) { + uint32_t current = *dn_queue_front_t (queue, uint32_t); + if (current != count) + return FAILED ("incorrect queue order"); + + dn_queue_pop (queue); + } + + if (count != N_ELEMS) + return FAILED ("incorrect queue count"); + + dn_queue_clear (queue); + + dn_queue_push (queue, &dispose_count); + dn_queue_push (queue, &dispose_count); + dn_queue_push (queue, &dispose_count); + + dn_queue_custom_pop (queue, test_queue_dispose_func); + dn_queue_custom_pop (queue, test_queue_dispose_func); + + if (dn_queue_size (queue) != 1) + return FAILED ("incorrect queue count after custom pop"); + if (dispose_count != 2) + return FAILED ("incorrect dispose count after custom pop"); + + dn_queue_free (queue); + + return OK; +} + +static +RESULT +test_queue_clear (void) +{ + uint32_t dispose_count = 0; + const char * items[] = { "first", "second" }; + + dn_queue_t *queue = dn_queue_alloc (); + if (!queue) + return FAILED ("failed to alloc queue"); + + if (!dn_queue_empty (queue)) + return FAILED ("failed empty #1"); + + dn_queue_push (queue, (char *)items [0]); + + if (dn_queue_empty (queue)) + return FAILED ("failed empty #2"); + + dn_queue_push (queue, (char *)items [1]); + + dn_queue_clear (queue); + + if (!dn_queue_empty (queue)) + return FAILED ("failed empty #3"); + + dn_queue_free (queue); + + queue = dn_queue_custom_alloc (DN_DEFAULT_ALLOCATOR); + + dn_queue_push (queue, &dispose_count); + dn_queue_push (queue, &dispose_count); + + dn_queue_custom_clear (queue, test_queue_dispose_func); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on clear"); + + dispose_count = 0; + dn_queue_custom_free (queue, test_queue_dispose_func); + + if (dispose_count != 0) + return FAILED ("invalid dispose count on clear/free"); + + return OK; +} + +static +RESULT +test_queue_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_queue_memory_end_snapshot); + if ( _CrtMemDifference(&dn_queue_memory_diff_snapshot, &dn_queue_memory_start_snapshot, &dn_queue_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &dn_queue_memory_diff_snapshot ); + return FAILED ("memory leak detected!"); + } +#endif + return OK; +} + +static Test dn_queue_tests [] = { + {"test_queue_setup", test_queue_setup}, + {"test_queue_alloc", test_queue_alloc}, + {"test_queue_init", test_queue_init}, + {"test_queue_free", test_queue_free}, + {"test_queue_dispose", test_queue_dispose}, + {"test_queue_front", test_queue_front}, + {"test_queue_back", test_queue_back}, + {"test_queue_empty", test_queue_empty}, + {"test_queue_size", test_queue_size}, + {"test_queue_push_pop", test_queue_push_pop}, + {"test_queue_clear", test_queue_clear}, + {"test_queue_teardown", test_queue_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(dn_queue_tests_init, dn_queue_tests) diff --git a/src/mono/mono/eventpipe/test/dn-umap-tests.c b/src/mono/mono/eventpipe/test/dn-umap-tests.c new file mode 100644 index 0000000..4a7aebf --- /dev/null +++ b/src/mono/mono/eventpipe/test/dn-umap-tests.c @@ -0,0 +1,941 @@ +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include + + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState dn_umap_memory_start_snapshot; +static _CrtMemState dn_umap_memory_end_snapshot; +static _CrtMemState dn_umap_memory_diff_snapshot; +#endif + +#define POINTER_TO_INT32(v) ((int32_t)(ptrdiff_t)(v)) +#define INT32_TO_POINTER(v) ((void *)(ptrdiff_t)(v)) + +static +void +DN_CALLBACK_CALLTYPE +test_umap_key_dispose_func (void *data) +{ + (*(uint32_t *)data)++; +} + +static +void +DN_CALLBACK_CALLTYPE +test_umap_value_dispose_func (void *data) +{ + (*(uint32_t *)data)++; +} + +static +void +DN_CALLBACK_CALLTYPE +test_umap_str_key_dispose_func (void *data) +{ + free (data); +} + +static +bool +DN_CALLBACK_CALLTYPE +test_umap_find_func ( + const void *a, + const void *b) +{ + if (!a || !b) + return false; + + return !strcmp ((const char *)a, (const char *)b); +} + +static +void +DN_CALLBACK_CALLTYPE +test_umap_for_each_func ( + void *key, + void *value, + void *user_data) +{ + (*(uint32_t *)user_data)++; +} + +static +RESULT +test_umap_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_umap_memory_start_snapshot); +#endif + return OK; +} + +static +RESULT +test_umap_alloc (void) +{ + dn_umap_t *map = dn_umap_alloc (); + if (!map) + return FAILED ("failed to alloc map"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_init (void) +{ + dn_umap_t map; + if (!dn_umap_init (&map)) + return FAILED ("failed to init map"); + + dn_umap_dispose (&map); + + return OK; +} + +static +RESULT +test_umap_free (void) +{ + uint32_t dispose_count = 0; + + dn_umap_custom_alloc_params_t params = {0, }; + params.value_dispose_func = test_umap_value_dispose_func; + + dn_umap_t *map = dn_umap_custom_alloc (¶ms); + if (!map) + return FAILED ("failed to custom alloc map"); + + dn_umap_insert (map, INT32_TO_POINTER (1), &dispose_count); + dn_umap_insert (map, INT32_TO_POINTER (2), &dispose_count); + + dn_umap_free (map); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on free"); + + return OK; +} + +static +RESULT +test_umap_dispose (void) +{ + uint32_t dispose_count = 0; + dn_umap_t map; + dn_umap_custom_init_params_t params = {0, }; + + params.value_dispose_func = test_umap_value_dispose_func; + if (!dn_umap_custom_init (&map, ¶ms)) + return FAILED ("failed to custom init map"); + + dn_umap_insert (&map, INT32_TO_POINTER (1), &dispose_count); + dn_umap_insert (&map, INT32_TO_POINTER (2), &dispose_count); + + dn_umap_dispose (&map); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on free"); + + return OK; +} + +static +RESULT +test_umap_empty (void) +{ + const char * items[] = { "first", "second" }; + + dn_umap_t *map = dn_umap_alloc (); + if (!map) + return FAILED ("failed to alloc map"); + + if (!dn_umap_empty (map)) + return FAILED ("failed empty #1"); + + dn_umap_insert (map, (char *)items [0], (char *)items [0]); + + if (dn_umap_empty (map)) + return FAILED ("failed empty #2"); + + dn_umap_insert (map, (char *)items [1], (char *)items [1]); + + if (dn_umap_empty (map)) + return FAILED ("failed empty #3"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_size (void) +{ + dn_umap_t *map = dn_umap_alloc (); + + if (dn_umap_size (map) != 0) + return FAILED ("map size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_umap_insert (map, INT32_TO_POINTER (i), NULL); + + if (dn_umap_size (map) != 10) + return FAILED ("size failed #1"); + + dn_umap_clear (map); + + if (dn_umap_size (map) != 0) + return FAILED ("size failed #2"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_max_size (void) +{ + dn_umap_t *map = dn_umap_alloc (); + if (!map) + return FAILED ("failed to alloc map"); + + if (dn_umap_max_size (map) != UINT32_MAX) + return FAILED ("max_size failed"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_clear (void) +{ + uint32_t dispose_count = 0; + + const char * items[] = { "first", "second" }; + + dn_umap_t *map = dn_umap_alloc (); + if (!map) + return FAILED ("failed to alloc map"); + + if (!dn_umap_empty (map)) + return FAILED ("failed empty #1"); + + dn_umap_insert (map, (char *)items [0], (char *)items [0]); + + if (dn_umap_empty (map)) + return FAILED ("failed empty #2"); + + dn_umap_insert (map, (char *)items [1], (char *)items [1]); + + dn_umap_clear (map); + + if (!dn_umap_empty (map)) + return FAILED ("failed empty #3"); + + dn_umap_free (map); + + dn_umap_custom_alloc_params_t params = {0, }; + params.value_dispose_func = test_umap_value_dispose_func; + + map = dn_umap_custom_alloc (¶ms); + + dn_umap_insert (map, INT32_TO_POINTER (1), &dispose_count); + dn_umap_insert (map, INT32_TO_POINTER (2), &dispose_count); + + dn_umap_clear (map); + + if (dispose_count != 2) + return FAILED ("invalid dispose count on clear"); + + dispose_count = 0; + dn_umap_free (map); + + if (dispose_count != 0) + return FAILED ("invalid dispose count on clear/free"); + + return OK; +} + +static +RESULT +test_umap_insert (void) +{ + dn_umap_result_t result; + const char *items[] = { "first", "second" }; + + dn_umap_t *map = dn_umap_alloc (); + result = dn_umap_insert (map, (char *)items [0], (char *)items [0]); + if (!result.result || dn_umap_it_key (result.it) != items [0] || dn_umap_it_value (result.it) != items [0]) + return FAILED ("insert failed #1"); + + result = dn_umap_insert (map, (char *)items [1], (char *)items [1]); + if (!result.result || dn_umap_it_key (result.it) != items [1] || dn_umap_it_value (result.it) != items [1]) + return FAILED ("insert failed #2"); + + result = dn_umap_insert (map, (char *)items [1], NULL); + if (result.result || dn_umap_it_key (result.it) != items [1] || dn_umap_it_value (result.it) != items [1]) + return FAILED ("insert failed #3"); + + dn_umap_free (map); + + dn_umap_custom_alloc_params_t params = {0, }; + + params.hash_func = dn_str_hash; + params.equal_func = dn_str_equal; + params.key_dispose_func = test_umap_str_key_dispose_func; + + map = dn_umap_custom_alloc (¶ms); + dn_umap_insert (map, strdup ("first"), (char *)items [0]); + + char *exists = strdup ("first"); + result = dn_umap_insert (map, exists, (char *)items [0]); + if (result.result) + return FAILED ("insert failed #4"); + free (exists); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_insert_or_assign (void) +{ + dn_umap_result_t result; + const char *items[] = { "first", "second" }; + + dn_umap_t *map = dn_umap_alloc (); + result = dn_umap_insert_or_assign (map, (char *)items [0], (char *)items [0]); + if (!result.result || dn_umap_it_key (result.it) != items [0] || dn_umap_it_value (result.it) != items [0]) + return FAILED ("insert_or_assign failed #1"); + + result = dn_umap_insert_or_assign (map, (char *)items [1], (char *)items [1]); + if (!result.result || dn_umap_it_key (result.it) != items [1] || dn_umap_it_value (result.it) != items [1]) + return FAILED ("insert_or_assign failed #2"); + + result = dn_umap_insert_or_assign (map, (char *)items [1], NULL); + if (!result.result || dn_umap_it_key (result.it) != items [1] || dn_umap_it_value (result.it) != NULL) + return FAILED ("insert_or_assign failed #3"); + + dn_umap_free (map); + + dn_umap_custom_alloc_params_t params = {0, }; + + params.hash_func = dn_str_hash; + params.equal_func = dn_str_equal; + params.key_dispose_func = test_umap_str_key_dispose_func; + + map = dn_umap_custom_alloc (¶ms); + dn_umap_insert_or_assign (map, strdup ("first"), (char *)items [0]); + + result = dn_umap_insert_or_assign (map, (char *)"first", (char *)items [1]); + if (!result.result || strcmp (dn_umap_it_key (result.it), items [0]) || dn_umap_it_value (result.it) != items [1]) + return FAILED ("insert_or_assign failed #4"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_erase (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_insert (map, (char *)items [0], (char *)items [0]); + dn_umap_insert (map, (char *)items [1], (char *)items [1]); + + dn_umap_it_t it = dn_umap_begin (map); + char *key = dn_umap_it_key (it); + char *value = dn_umap_it_value (it); + + dn_umap_it_t result = dn_umap_erase (it); + if (dn_umap_size (map) != 1 || dn_umap_it_key (result) == key || dn_umap_it_value (result) == value) + return FAILED ("erase failed #1"); + + if (dn_umap_erase_key (map, NULL) != 0) + return FAILED ("erase failed #2"); + + dn_umap_insert (map, (char *)items [2], (char *)items [2]); + dn_umap_insert (map, (char *)items [3], (char *)items [3]); + + if (dn_umap_erase_key (map, items [2]) == 0) + return FAILED ("erase failed #3"); + + result = dn_umap_erase (dn_umap_begin (map)); + result = dn_umap_erase (dn_umap_begin (map)); + + if (!dn_umap_it_end (result)) + return FAILED ("erase failed #4"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_extract (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_insert (map, (char *)items [0], (char *)items [1]); + dn_umap_insert (map, (char *)items [2], (char *)items [3]); + + char *key; + char *value; + + if (!dn_umap_extract_key (map, items [0], (void **)&key, (void **)&value) || key != items [0] || value != items [1]) + return FAILED ("extract failed #1"); + + if (dn_umap_size (map) != 1) + return FAILED ("extract failed #2"); + + dn_umap_free (map); + + uint32_t key_dispose_count = 0; + uint32_t value_dispose_count = 0; + + dn_umap_custom_alloc_params_t params = {0, }; + + params.key_dispose_func = test_umap_str_key_dispose_func; + params.value_dispose_func = test_umap_value_dispose_func; + + map = dn_umap_custom_alloc (¶ms); + + dn_umap_insert (map, &key_dispose_count, &value_dispose_count); + if (!dn_umap_extract_key (map, &key_dispose_count, NULL, NULL)) + return FAILED ("extract failed #3"); + + if (key_dispose_count != 0 || value_dispose_count != 0 || dn_umap_size (map) != 0) + return FAILED ("extract failed #4"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_find (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_insert (map, (char *)items [2], (char *)items [2]); + dn_umap_insert (map, (char *)items [1], (char *)items [1]); + dn_umap_insert (map, (char *)items [0], (char *)items [0]); + + const char *data = items [3]; + dn_umap_insert (map, (char *)data, (char *)data); + + dn_umap_it_t found1 = dn_umap_find (map, data); + dn_umap_it_t found2 = dn_umap_custom_find (map, data, test_umap_find_func); + + if (dn_umap_it_key_t (found1, char *) != data || dn_umap_it_key_t (found2, char *) != data) + return FAILED ("find failed #1"); + + found1 = dn_umap_find (map, NULL); + found2 = dn_umap_custom_find (map, NULL, test_umap_find_func); + if (!dn_umap_it_end (found1) || !dn_umap_it_end (found2)) + return FAILED ("find failed #2"); + + dn_umap_free (map); + + dn_umap_custom_alloc_params_t params = {0, }; + + params.hash_func = dn_str_hash; + params.equal_func = dn_str_equal; + + map = dn_umap_custom_alloc (¶ms); + + dn_umap_insert (map, (char *)items [2], (char *)items [2]); + dn_umap_insert (map, (char *)items [1], (char *)items [1]); + dn_umap_insert (map, (char *)items [0], (char *)items [0]); + + found1 = dn_umap_find (map, "second"); + found2 = dn_umap_custom_find (map, "second", test_umap_find_func); + + if (dn_umap_it_key (found1) != dn_umap_it_key (found2)) + return FAILED ("find failed #3"); + + dn_umap_free (map); + + return OK; +} + +static RESULT +test_umap_find_2 (void) +{ + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_insert (map, NULL, INT32_TO_POINTER (1)); + dn_umap_insert (map, INT32_TO_POINTER (1), INT32_TO_POINTER (2)); + + dn_umap_it_t found = dn_umap_find (map, NULL); + if (dn_umap_it_end (found)) + return FAILED ("Did not find the NULL"); + + if (dn_umap_it_key (found) != NULL) + return FAILED ("Incorrect key found"); + + if (dn_umap_it_value (found) != INT32_TO_POINTER (1)) + return FAILED ("Got wrong value %p\n", dn_umap_it_value (found)); + + found = dn_umap_find (map, INT32_TO_POINTER (1)); + if (dn_umap_it_end (found)) + return FAILED ("Did not find the 1"); + + if (dn_umap_it_key (found) != INT32_TO_POINTER(1)) + return FAILED ("Incorrect key found"); + + if (dn_umap_it_value (found) != INT32_TO_POINTER (2)) + return FAILED ("Got wrong value %p\n", dn_umap_it_value (found)); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_contains (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_insert (map, (char *)items [2], (char *)items [2]); + dn_umap_insert (map, (char *)items [1], (char *)items [1]); + dn_umap_insert (map, (char *)items [0], (char *)items [0]); + + if (!dn_umap_contains (map, items [0])) + return FAILED ("contains failed #1"); + + if (dn_umap_contains (map, "unkown")) + return FAILED ("contains failed #2"); + + dn_umap_erase_key (map, items [1]); + + if (dn_umap_contains (map, items [1])) + return FAILED ("contains failed #3"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_rehash (void) +{ + dn_umap_t *map = dn_umap_alloc (); + + for (uint32_t i = 0; i < 1000; i++) + dn_umap_insert (map, INT32_TO_POINTER (i), INT32_TO_POINTER (i)); + + dn_umap_rehash (map, dn_umap_size (map) * 2); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_reserve (void) +{ + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_reserve (map, 1000); + + for (uint32_t i = 0; i < 1000; i++) + dn_umap_insert (map, INT32_TO_POINTER (i), INT32_TO_POINTER (i)); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_for_each (void) +{ + uint32_t count = 0; + dn_umap_t *map = dn_umap_alloc (); + + for (uint32_t i = 0; i < 100; ++i) + dn_umap_insert (map, INT32_TO_POINTER (i), INT32_TO_POINTER (i)); + + dn_umap_for_each (map, test_umap_for_each_func, &count); + if (count != 100) + return FAILED ("for_each failed"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_iterator (void) +{ + uint32_t count = 0; + dn_umap_t *map = dn_umap_alloc (); + + for (uint32_t i = 0; i < 100; ++i) + dn_umap_insert (map, INT32_TO_POINTER (i), INT32_TO_POINTER (i)); + + DN_UMAP_FOREACH_BEGIN (uint32_t, key, uint32_t, value, map) { + if (key == value) + count++; + } DN_UMAP_FOREACH_END; + + if (count != 100) + return FAILED ("foreach iterator failed #2"); + + count = 0; + DN_UMAP_FOREACH_KEY_BEGIN (uint32_t, key, map) { + count += key; + } DN_UMAP_FOREACH_END; + + if (count != 4950) + return FAILED ("foreach iterator failed #4"); + + dn_umap_free (map); + + return OK; +} + +static RESULT +test_umap_iterator_2 (void) +{ + dn_umap_custom_alloc_params_t params = {0, }; + + params.hash_func = dn_direct_hash; + params.equal_func = dn_direct_equal; + + dn_umap_t *map = dn_umap_custom_alloc (¶ms); + + uint32_t sum = 0; + for (uint32_t i = 0; i < 1000; i++) { + sum += i; + dn_umap_insert (map, INT32_TO_POINTER (i), INT32_TO_POINTER (i)); + } + + uint32_t keys_sum = 0; + uint32_t values_sum = 0; + + DN_UMAP_FOREACH_BEGIN (uint32_t, key, uint32_t, value, map) { + if (key != value) + return FAILED ("key != value"); + keys_sum += key; + values_sum += value; + } DN_UMAP_FOREACH_END; + + if (keys_sum != sum || values_sum != sum) + return FAILED ("Did not find all key-value pairs"); + + dn_umap_free (map); + + return OK; +} + +uint32_t foreach_count = 0; +uint32_t foreach_fail = 0; + +static void +umap_for_each_str_str_func (void *key, void *value, void *user_data) +{ + foreach_count++; + if (POINTER_TO_INT32 (user_data) != 'a') + foreach_fail = 1; +} + +static RESULT +test_umap_str_str_map (void) +{ + dn_umap_custom_alloc_params_t params = {0, }; + params.hash_func = dn_str_hash; + params.equal_func = dn_str_equal; + + dn_umap_t *map = dn_umap_custom_alloc (¶ms); + + foreach_count = 0; + foreach_fail = 0; + + dn_umap_insert (map, (char *)"hello", (char *)"world"); + dn_umap_insert (map, (char*)"my", (char*)"god"); + + dn_umap_for_each (map, umap_for_each_str_str_func, INT32_TO_POINTER ('a')); + + if (foreach_count != 2) + return FAILED ("did not find all keys, got %d expected 2", foreach_count); + + if (foreach_fail) + return FAILED("failed to pass the user-data to foreach"); + + if (dn_umap_erase_key (map, "my") == 0) + return FAILED ("did not find known key"); + + if (dn_umap_size (map) != 1) + return FAILED ("unexpected size"); + + dn_umap_insert_or_assign (map, (char *)"hello", (char *)"moon"); + dn_umap_it_t found = dn_umap_find (map, "hello"); + if (dn_umap_it_end (found) || strcmp (dn_umap_it_value_t (found, char *), "moon") != 0) + return FAILED ("did not replace world with moon"); + + if (dn_umap_erase_key (map, "hello") == 0) + return FAILED ("did not find known key"); + + if (dn_umap_size (map) != 0) + return FAILED ("unexpected size"); + + dn_umap_free (map); + + return OK; +} + +static RESULT +test_umap_grow (void) +{ + dn_umap_custom_alloc_params_t params = {0, }; + params.hash_func = dn_str_hash; + params.equal_func = dn_str_equal; + params.key_dispose_func = free; + params.value_dispose_func = free; + + dn_umap_t *map = dn_umap_custom_alloc (¶ms); + + char buffer1 [30]; + char buffer2 [30]; + uint32_t count = 0; + + for (uint32_t i = 0; i < 1000; i++) { + sprintf (buffer1, "%d", i); + sprintf (buffer2, "x-%d", i); + dn_umap_insert (map, strdup (buffer1), strdup (buffer2)); + } + + for (uint32_t i = 0; i < 1000; i++){ + sprintf (buffer1, "%d", i); + dn_umap_it_t found = dn_umap_find (map, buffer1); + sprintf (buffer1, "x-%d", i); + if (strcmp (dn_umap_it_value_t (found, char *), buffer1) != 0) + return FAILED ("Failed to lookup the key %d, the value was %s\n", i, dn_umap_it_value_t (found, char *)); + } + + if (dn_umap_size (map) != 1000) + return FAILED ("Did not find 1000 elements on the hash, found %d\n", dn_umap_size (map)); + + dn_umap_for_each (map, test_umap_for_each_func, &count); + if (count != 1000){ + return FAILED ("for each count is not 1000"); + } + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_find_erase (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_insert (map, (char *)items [2], (char *)items [2]); + dn_umap_insert (map, (char *)items [1], (char *)items [1]); + dn_umap_insert (map, (char *)items [0], (char *)items [0]); + + const char *data = items [3]; + dn_umap_insert (map, (char *)data, (char *)data); + + dn_umap_it_t found = dn_umap_find (map, data); + + if (dn_umap_it_key_t (found, char *) != data) + return FAILED ("find failed #1"); + + dn_umap_erase (found); + + found = dn_umap_find (map, data); + + if (!dn_umap_it_end (found)) + return FAILED ("find failed #2"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_ptr_uint32_insert_or_assign (void) +{ + dn_umap_result_t result; + const char *items[] = { "first", "second" }; + + dn_umap_t *map = dn_umap_alloc (); + + result = dn_umap_ptr_uint32_insert (map, (void *) items [0], 1); + if (!result.result || dn_umap_it_key_ptr (result.it) != (void *)items [0] || dn_umap_it_value_uint32_t (result.it) != 1) + return FAILED ("insert failed #1"); + + result = dn_umap_ptr_uint32_insert (map, (void *) items [1], 2); + if (!result.result || dn_umap_it_key_ptr (result.it) != (void *)items [1] || dn_umap_it_value_uint32_t (result.it) != 2) + return FAILED ("insert failed #2"); + + result = dn_umap_insert_or_assign (map, (void *)items [1], 0); + if (!result.result || dn_umap_it_key_ptr (result.it) != (void *)items [1] || dn_umap_it_value_uint32_t (result.it) != 0) + return FAILED ("insert_or_assign failed"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_ptr_uint32_find_erase (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_ptr_uint32_insert (map, (void *)items [2], 3); + dn_umap_ptr_uint32_insert (map, (void *)items [1], 2); + dn_umap_ptr_uint32_insert (map, (void *)items [0], 1); + + const void *data = items [3]; + dn_umap_ptr_uint32_insert (map, (void *)data, 4); + + dn_umap_it_t found = dn_umap_ptr_uint32_find (map, data); + + if (dn_umap_it_key_ptr (found) != (void *)data) + return FAILED ("find failed #1"); + + dn_umap_erase (found); + + found = dn_umap_find (map, data); + + if (!dn_umap_it_end (found)) + return FAILED ("find failed #2"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_ptr_uint32_find_erase_insert (void) +{ + const char *items[] = { "first", "second", "third", "fourth"}; + + dn_umap_t *map = dn_umap_alloc (); + + dn_umap_ptr_uint32_insert (map, (char *)items [3], 4); + dn_umap_ptr_uint32_insert (map, (char *)items [2], 3); + dn_umap_ptr_uint32_insert (map, (char *)items [1], 2); + dn_umap_ptr_uint32_insert (map, (char *)items [0], 1); + + dn_umap_it_t found = dn_umap_ptr_uint32_find (map, items [1]); + + if (dn_umap_it_end (found)) + return FAILED ("find failed #1"); + + if (dn_umap_it_key_ptr (found) != (void *)items [1]) + return FAILED ("find failed #2"); + + if (dn_umap_it_value_uint32_t (found) != 2) + return FAILED ("find failed #3"); + + dn_umap_erase (found); + + found = dn_umap_find (map, items [1]); + if (!dn_umap_it_end (found)) + return FAILED ("find failed #4"); + + dn_umap_result_t result = dn_umap_ptr_uint32_insert (map, (char *)items [1], 2); + if (!result.result || dn_umap_it_end (result.it)) + return FAILED ("insert failed"); + + found = dn_umap_find (map, items [1]); + if (dn_umap_it_end (found)) + return FAILED ("find failed #5"); + + dn_umap_free (map); + + return OK; +} + +static +RESULT +test_umap_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_umap_memory_end_snapshot); + if ( _CrtMemDifference(&dn_umap_memory_diff_snapshot, &dn_umap_memory_start_snapshot, &dn_umap_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &dn_umap_memory_diff_snapshot ); + return FAILED ("memory leak detected!"); + } +#endif + return OK; +} + +static Test dn_umap_tests [] = { + {"test_umap_setup", test_umap_setup}, + {"test_umap_alloc", test_umap_alloc}, + {"test_umap_init", test_umap_init}, + {"test_umap_free", test_umap_free}, + {"test_umap_dispose", test_umap_dispose}, + {"test_umap_empty", test_umap_empty}, + {"test_umap_size", test_umap_size}, + {"test_umap_max_size", test_umap_max_size}, + {"test_umap_clear", test_umap_clear}, + {"test_umap_insert", test_umap_insert}, + {"test_umap_insert_or_assign", test_umap_insert_or_assign}, + {"test_umap_erase", test_umap_erase}, + {"test_umap_extract", test_umap_extract}, + {"test_umap_find", test_umap_find}, + {"test_umap_find_2", test_umap_find_2}, + {"test_umap_contains", test_umap_contains}, + {"test_umap_rehash", test_umap_rehash}, + {"test_umap_reserve", test_umap_reserve}, + {"test_umap_for_each", test_umap_for_each}, + {"test_umap_iterator", test_umap_iterator}, + {"test_umap_iterator_2", test_umap_iterator_2}, + {"test_umap_str_str_map", test_umap_str_str_map}, + {"test_umap_grow", test_umap_grow}, + {"test_umap_find_erase", test_umap_find_erase}, + {"test_umap_ptr_uint32_insert_or_assign", test_umap_ptr_uint32_insert_or_assign}, + {"test_umap_ptr_uint32_find_erase", test_umap_ptr_uint32_find_erase}, + {"test_umap_ptr_uint32_find_erase_insert", test_umap_ptr_uint32_find_erase_insert}, + {"test_umap_teardown", test_umap_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(dn_umap_tests_init, dn_umap_tests) diff --git a/src/mono/mono/eventpipe/test/dn-vector-ptr-tests.c b/src/mono/mono/eventpipe/test/dn-vector-ptr-tests.c new file mode 100644 index 0000000..e766268 --- /dev/null +++ b/src/mono/mono/eventpipe/test/dn-vector-ptr-tests.c @@ -0,0 +1,965 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState dn_vector_ptr_memory_start_snapshot; +static _CrtMemState dn_vector_ptr_memory_end_snapshot; +static _CrtMemState dn_vector_ptr_memory_diff_snapshot; +#endif + +#define POINTER_TO_INT32(v) ((int32_t)(ptrdiff_t)(v)) +#define INT32_TO_POINTER(v) ((void *)(ptrdiff_t)(v)) + +/* Don't add more than 32 items to this please */ +static const char *test_vector_ptr_items [] = { + "Apples", "Oranges", "Plumbs", "Goats", "Snorps", "Grapes", + "Tickle", "Place", "Coffee", "Cookies", "Cake", "Cheese", + "Tseng", "Holiday", "Avenue", "Smashing", "Water", "Toilet", + NULL +}; + +static int32_t test_vector_ptr_foreach_iterate_index = 0; +static char *test_vector_ptr_foreach_iterate_error = NULL; + +static +void +DN_CALLBACK_CALLTYPE +test_vector_ptr_foreach_callback ( + void *data, + void *user_data) +{ + char *item = *((char **)data); + const char *item_cmp = test_vector_ptr_items [test_vector_ptr_foreach_iterate_index++]; + + if (test_vector_ptr_foreach_iterate_error != NULL) { + return; + } + + if (item != item_cmp) { + test_vector_ptr_foreach_iterate_error = FAILED ( + "expected item at %d to be %s, but it was %s", + test_vector_ptr_foreach_iterate_index - 1, item_cmp, item); + } +} + +static +void +DN_CALLBACK_CALLTYPE +test_vector_ptr_free_func(void *data) +{ + free (*(char **)data); +} + +static +void +DN_CALLBACK_CALLTYPE +test_vector_ptr_clear_func(void *data) +{ + (**((uint32_t **)data))++; +} + +static +int32_t +DN_CALLBACK_CALLTYPE +test_vector_ptr_sort_compare ( + const void *a, + const void *b) +{ + char *stra = *(char **) a; + char *strb = *(char **) b; + return strcmp(stra, strb); +} + +static +RESULT +test_vector_ptr_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_vector_ptr_memory_start_snapshot); +#endif + return OK; +} + +static +dn_vector_ptr_t * +vector_ptr_alloc_and_fill (uint32_t *item_count) +{ + dn_vector_ptr_t *vector = dn_vector_ptr_alloc (); + int32_t i; + + for(i = 0; test_vector_ptr_items [i] != NULL; i++) { + dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i]); + } + + if (item_count != NULL) { + *item_count = i; + } + + return vector; +} + +static +uint32_t +vector_ptr_guess_capacity (uint32_t capacity) +{ + return ((capacity + (capacity >> 1) + 63) & ~63); +} + +static +RESULT +test_vector_ptr_alloc (void) +{ + dn_vector_ptr_t *vector; + uint32_t i; + + vector = vector_ptr_alloc_and_fill (&i); + + if (dn_vector_ptr_capacity (vector) != vector_ptr_guess_capacity (vector->size)) { + return FAILED ("capacity should be %d, but it is %d", + vector_ptr_guess_capacity (vector->size), dn_vector_ptr_capacity (vector)); + } + + if (vector->size != i) { + return FAILED ("expected %d node(s) in the vector", i); + } + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_free (void) +{ + int32_t v = 27; + dn_vector_ptr_t *vector = NULL; + + vector = dn_vector_ptr_alloc (); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + dn_vector_ptr_free (vector); + + vector = dn_vector_ptr_alloc (); + if (vector->size != 0) + return FAILED ("vector size didn't match #2"); + + dn_vector_ptr_push_back (vector, &v); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_alloc_capacity (void) +{ + dn_vector_ptr_t *vector = NULL; + dn_vector_ptr_custom_alloc_params_t params = {0, }; + + params.capacity = ARRAY_SIZE (test_vector_ptr_items); + vector = dn_vector_ptr_custom_alloc (¶ms); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + if (dn_vector_ptr_capacity (vector) < ARRAY_SIZE (test_vector_ptr_items)) + return FAILED ("capacity didn't match"); + + void **data = dn_vector_ptr_data (vector); + for (int32_t i = 0; i < ARRAY_SIZE (test_vector_ptr_items); ++i) { + dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i]); + if (dn_vector_ptr_data (vector) != data) + return FAILED ("vector pre-alloc failed"); + } + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_for_iterate (void) +{ + dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL); + uint32_t i = 0; + + DN_VECTOR_PTR_FOREACH_BEGIN (char *, item, vector) { + if (item != test_vector_ptr_items [i]) { + return FAILED ( + "expected item at %d to be %s, but it was %s", + i, test_vector_ptr_items [i], item); + } + i++; + } DN_VECTOR_PTR_FOREACH_END; + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_foreach_iterate (void) +{ + dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (NULL); + + test_vector_ptr_foreach_iterate_index = 0; + test_vector_ptr_foreach_iterate_error = NULL; + + dn_vector_ptr_for_each (vector, test_vector_ptr_foreach_callback, vector); + + dn_vector_ptr_free (vector); + + return test_vector_ptr_foreach_iterate_error; +} + +static +RESULT +test_vector_ptr_resize (void) +{ + dn_vector_ptr_t *vector= dn_vector_ptr_alloc (); + uint32_t i, grow_length = 50; + + dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0]); + dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [1]); + dn_vector_ptr_resize (vector, grow_length); + + if (vector->size != grow_length) { + return FAILED ("vector size should be 50, it is %d", vector->size); + } else if (*dn_vector_ptr_index (vector, 0) != test_vector_ptr_items [0]) { + return FAILED ("item 0 was overwritten, should be %s", test_vector_ptr_items [0]); + } else if (*dn_vector_ptr_index (vector, 1) != test_vector_ptr_items [1]) { + return FAILED ("item 1 was overwritten, should be %s", test_vector_ptr_items [1]); + } + + for (i = 2; i < vector->size; i++) { + if (*dn_vector_ptr_index (vector, i) != NULL) { + return FAILED ("item %d is not NULL, it is %p", i, vector->data[i]); + } + } + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_erase (void) +{ + dn_vector_ptr_t *vector; + uint32_t i; + + vector = vector_ptr_alloc_and_fill (&i); + + dn_vector_ptr_erase (dn_vector_ptr_begin (vector)); + if (*dn_vector_ptr_index (vector, 0) != test_vector_ptr_items [1]) { + return FAILED ("first item is not %s, it is %s", test_vector_ptr_items [1], + *dn_vector_ptr_index (vector, 0)); + } + + dn_vector_ptr_erase (dn_vector_ptr_it_prev (dn_vector_ptr_end (vector))); + + if (*dn_vector_ptr_index (vector, vector->size - 1) != test_vector_ptr_items [vector->size]) { + return FAILED ("last item is not %s, it is %s", + test_vector_ptr_items [vector->size - 2], *dn_vector_ptr_index (vector, vector->size - 1)); + } + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_erase_fast (void) +{ + dn_vector_ptr_t *vector; + uint32_t i; + + vector = vector_ptr_alloc_and_fill (&i); + + dn_vector_ptr_erase_fast (dn_vector_ptr_begin (vector)); + if (*dn_vector_ptr_index (vector, 0) != test_vector_ptr_items [vector->size]) { + return FAILED ("first item is not %s, it is %s", test_vector_ptr_items [vector->size], + *dn_vector_ptr_index (vector, 0)); + } + + dn_vector_ptr_erase_fast (dn_vector_ptr_it_prev (dn_vector_ptr_end (vector))); + if (*dn_vector_ptr_index (vector, vector->size - 1) != test_vector_ptr_items [vector->size - 1]) { + return FAILED ("last item is not %s, it is %s", + test_vector_ptr_items [vector->size - 1], *dn_vector_ptr_index (vector, vector->size - 1)); + } + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_capacity (void) +{ + uint32_t size; + dn_vector_ptr_t *vector = vector_ptr_alloc_and_fill (&size); + + if (dn_vector_ptr_capacity (vector) < size) + return FAILED ("invalid vector capacity #1"); + + if (dn_vector_ptr_capacity (vector) < vector->size) + return FAILED ("invalid arvectorray capacity #2"); + + uint32_t capacity = dn_vector_ptr_capacity (vector); + + dn_vector_ptr_it_t it = dn_vector_ptr_begin (vector); + + void *value0 = *dn_vector_ptr_index (vector, 0); + dn_vector_ptr_erase (it); + + void *value1 = *dn_vector_ptr_index (vector, 1); + + it = dn_vector_ptr_it_next (it); + dn_vector_ptr_erase (it); + + void *value2 = *dn_vector_ptr_index (vector, 2); + + it = dn_vector_ptr_it_next (it); + dn_vector_ptr_erase (it); + + if (dn_vector_ptr_capacity (vector) != capacity) + return FAILED ("invalid vector capacity #3"); + + dn_vector_ptr_push_back (vector, value0); + dn_vector_ptr_push_back (vector, value1); + dn_vector_ptr_push_back (vector, value2); + + if (dn_vector_ptr_capacity (vector) != capacity) + return FAILED ("invalid vector capacity #4"); + + dn_vector_ptr_free (vector); + + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.capacity = ARRAY_SIZE (test_vector_ptr_items); + + vector = dn_vector_ptr_custom_alloc (¶ms); + if (vector->size != 0) + return FAILED ("vector len didn't match"); + + if (dn_vector_ptr_capacity (vector) < ARRAY_SIZE (test_vector_ptr_items)) + return FAILED ("invalid vector capacity #5"); + + capacity = dn_vector_ptr_capacity (vector); + for (int32_t i = 0; i < ARRAY_SIZE (test_vector_ptr_items); ++i) + dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i]); + + if (dn_vector_ptr_capacity (vector) != capacity) + return FAILED ("invalid vector capacity #6"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_custom_free (void) +{ + int32_t count = 0; + dn_vector_ptr_t *vector = dn_vector_ptr_alloc (); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + + dn_vector_ptr_custom_free (vector, test_vector_ptr_clear_func); + + if (count != 2) + return FAILED ("callback called incorrect number of times"); + + vector = dn_vector_ptr_alloc (); + + dn_vector_ptr_push_back (vector, malloc (10)); + dn_vector_ptr_push_back (vector, malloc (100)); + + dn_vector_ptr_custom_free (vector, test_vector_ptr_free_func); + + return OK; +} + +static +RESULT +test_vector_ptr_clear (void) +{ + uint32_t count = 0; + dn_vector_ptr_t *vector = dn_vector_ptr_alloc (); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + + dn_vector_ptr_clear (vector); + if (vector->size != 0) + return FAILED ("vector size didn't match #2"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_custom_clear (void) +{ + uint32_t count = 0; + dn_vector_ptr_t *vector = dn_vector_ptr_alloc (); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + dn_vector_ptr_push_back (vector, &count); + + uint32_t capacity = dn_vector_ptr_capacity (vector); + + dn_vector_ptr_custom_clear (vector, test_vector_ptr_clear_func); + + if (vector->size != 0) + return FAILED ("vector size didn't match #2"); + + if (dn_vector_ptr_capacity (vector) != capacity) + return FAILED ("incorrect vector capacity"); + + if (count != 5) + return FAILED ("allback called incorrect number of times"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_foreach_it (void) +{ + uint32_t count = 0; + dn_vector_ptr_t *vector = dn_vector_ptr_alloc (); + + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (uint32_t i = 0; i < 100; ++i) + dn_vector_ptr_push_back (vector, INT32_TO_POINTER (i)); + + DN_VECTOR_PTR_FOREACH_BEGIN (uint32_t *, value, vector) { + if (POINTER_TO_INT32 (value) != count) + return FAILED ("foreach iterator failed #1"); + count++; + } DN_VECTOR_PTR_FOREACH_END; + + if (count != dn_vector_ptr_size (vector)) + return FAILED ("foreach iterator failed #2"); + + dn_vector_ptr_free (vector); + return OK; +} + +static +RESULT +test_vector_ptr_foreach_rev_it (void) +{ + uint32_t count = 100; + dn_vector_ptr_t *vector = dn_vector_ptr_alloc (); + + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (uint32_t i = 0; i < 100; ++i) + dn_vector_ptr_push_back (vector, INT32_TO_POINTER (i)); + + DN_VECTOR_PTR_FOREACH_RBEGIN (uint32_t *, value, vector) { + if (POINTER_TO_INT32 (value) != count - 1) + return FAILED ("foreach reverse iterator failed #1"); + count--; + } DN_VECTOR_PTR_FOREACH_END; + + if (count != 0) + return FAILED ("foreach reverse iterator failed #2"); + + dn_vector_ptr_free (vector); + return OK; +} + +static +RESULT +test_vector_ptr_sort (void) +{ + dn_vector_ptr_t *vector = dn_vector_ptr_alloc (); + uint32_t i; + + static char * const letters [] = { (char*)"A", (char*)"B", (char*)"C", (char*)"D", (char*)"E" }; + + dn_vector_ptr_push_back (vector, letters [0]); + dn_vector_ptr_push_back (vector, letters [1]); + dn_vector_ptr_push_back (vector, letters [2]); + dn_vector_ptr_push_back (vector, letters [3]); + dn_vector_ptr_push_back (vector, letters [4]); + + dn_vector_ptr_sort (vector, test_vector_ptr_sort_compare); + + for (i = 0; i < vector->size; i++) { + if (vector->data [i] != letters [i]) { + return FAILED ("vector out of order, expected %s got %s at position %d", + letters [i], (char *) vector->data [i], i); + } + } + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_find (void) +{ + dn_vector_ptr_t *vector = dn_vector_ptr_alloc (); + + static char * const letters [] = { (char*)"A", (char*)"B", (char*)"C", (char*)"D", (char*)"E" }; + + dn_vector_ptr_push_back (vector, letters [0]); + dn_vector_ptr_push_back (vector, letters [1]); + dn_vector_ptr_push_back (vector, letters [2]); + dn_vector_ptr_push_back (vector, letters [3]); + dn_vector_ptr_push_back (vector, letters [4]); + + if (dn_vector_ptr_find (vector, letters [0]).it == dn_vector_ptr_size (vector)) + return FAILED ("failed to find value #1"); + + if (dn_vector_ptr_find (vector, letters [1]).it == dn_vector_ptr_size (vector)) + return FAILED ("failed to find value #2"); + + if (dn_vector_ptr_find (vector, letters [2]).it == dn_vector_ptr_size (vector)) + return FAILED ("failed to find value #3"); + + if (dn_vector_ptr_find (vector, letters [3]).it == dn_vector_ptr_size (vector)) + return FAILED ("failed to find value #4"); + + if (dn_vector_ptr_find (vector, letters [4]).it == dn_vector_ptr_size (vector)) + return FAILED ("failed to find value #5"); + + if (dn_vector_ptr_find (vector, NULL).it != dn_vector_ptr_size (vector)) + return FAILED ("find failed #6"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_default_local_alloc (void) +{ + DN_DEFAULT_LOCAL_ALLOCATOR (allocator, dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + + uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc"); + + for (uint32_t i = 0; i < init_capacity; ++i) { + for (uint32_t j = 0; j < ARRAY_SIZE (test_vector_ptr_items); ++j) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [j])) + return FAILED ("failed vector push_back using custom alloc"); + } + } + + for (uint32_t i = 0; i < init_capacity; ++i) { + for (uint32_t j = 0; j < ARRAY_SIZE (test_vector_ptr_items); ++j) { + if (*dn_vector_ptr_index (vector, ARRAY_SIZE (test_vector_ptr_items) * i + j) != test_vector_ptr_items [j]) + return FAILED ("vector realloc failure using default local alloc"); + } + } + + dn_vector_ptr_free (vector); + + return OK; +} + +static +bool +vector_ptr_owned_by_fixed_allocator ( + dn_allocator_fixed_t *allocator, + dn_vector_ptr_t *vector) +{ + return allocator->_data._begin <= (void *)dn_vector_ptr_data (vector) && + allocator->_data._end > (void *)dn_vector_ptr_data (vector); +} + +static +RESULT +test_vector_ptr_local_alloc (void) +{ + uint8_t buffer [1024]; + dn_allocator_fixed_or_malloc_t allocator; + + dn_allocator_fixed_or_malloc_init (&allocator, buffer, ARRAY_SIZE (buffer)); + memset (buffer, 0, ARRAY_SIZE (buffer)); + + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + + dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc"); + + // All should fit in fixed allocator. + for (uint32_t i = 0; i < ARRAY_SIZE (test_vector_ptr_items); ++i) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i])) + return FAILED ("failed vector push_back using custom alloc #1"); + } + + if (!vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("custom alloc using fixed allocator failed"); + + // Make sure we run out of fixed allocator memory, should switch to dynamic allocator. + for (uint32_t i = 0; i < ARRAY_SIZE (buffer); ++i) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i % ARRAY_SIZE (test_vector_ptr_items)])) + return FAILED ("failed vector push_back using custom alloc #2"); + } + + if (vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("custom alloc using dynamic allocator failed"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_local_alloc_capacity (void) +{ + uint8_t buffer [dn_vector_ptr_default_local_allocator_byte_size]; + dn_allocator_fixed_or_malloc_t allocator; + + dn_allocator_fixed_or_malloc_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size); + memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size); + + uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = init_capacity; + + dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc"); + + if (dn_vector_ptr_capacity (vector) != dn_vector_ptr_default_local_allocator_capacity_size) + return FAILED ("default local vector should have %d in capacity #1", dn_vector_ptr_default_local_allocator_capacity_size); + + // Make sure pre-allocted fixed allocator is used. + if (!vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("custom alloc using fixed allocator failed #1"); + + // Add pre-allocated amount of test_vector_ptr_items, should fit into fixed buffer. + for (uint32_t i = 0; i < dn_vector_ptr_capacity (vector); ++i) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i % ARRAY_SIZE (test_vector_ptr_items)])) + return FAILED ("failed vector push_back using custom alloc"); + } + + if (dn_vector_ptr_capacity (vector) != dn_vector_ptr_default_local_allocator_capacity_size) + return FAILED ("default local vector should have %d in capacity #2", dn_vector_ptr_default_local_allocator_capacity_size); + + // Make sure pre-allocted fixed allocator is used without reallocs (would cause OOM and switch to dynamic). + if (!vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("custom alloc using fixed allocator failed #2"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_fixed_alloc_capacity (void) +{ + uint8_t buffer [dn_vector_ptr_default_local_allocator_byte_size]; + dn_allocator_fixed_t allocator; + + dn_allocator_fixed_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size); + memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size); + + uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = init_capacity; + + dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc"); + + // Add pre-allocated amount of test_vector_ptr_items, should fit into fixed buffer. + for (uint32_t i = 0; i < dn_vector_ptr_capacity (vector); ++i) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i % ARRAY_SIZE (test_vector_ptr_items)])) + return FAILED ("failed vector push_back using custom alloc"); + } + + // Adding one more should hit OOM. + if (dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0])) + return FAILED ("vector push_back failed to triggered OOM"); + + // Make room for on more item. + dn_vector_ptr_pop_back (vector); + + // Adding one more should not hit OOM. + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0])) + return FAILED ("vector push_back triggered OOM"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_fixed_or_malloc_alloc_capacity (void) +{ + uint8_t buffer [dn_vector_ptr_default_local_allocator_byte_size]; + dn_allocator_fixed_or_malloc_t allocator; + + dn_allocator_fixed_or_malloc_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size); + memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size); + + uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = init_capacity; + + dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc"); + + // Add pre-allocated amount of test_vector_ptr_items, should fit into fixed allocator. + for (uint32_t i = 0; i < dn_vector_ptr_capacity (vector); ++i) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i % ARRAY_SIZE (test_vector_ptr_items)])) + return FAILED ("failed vector push_back using custom alloc #1"); + } + + // Make sure pre-allocted fixed allocator is used. + if (!vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("custom alloc using fixed allocator failed"); + + // Adding one more should not hit OOM. + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0])) + return FAILED ("failed vector push_back using custom alloc #2"); + + if (dn_vector_ptr_capacity (vector) <= init_capacity) + return FAILED ("unexpected vector capacity #1"); + + init_capacity = dn_vector_ptr_capacity (vector); + + // Make room for on more item. + dn_vector_ptr_pop_back (vector); + + if (dn_vector_ptr_capacity (vector) < init_capacity) + return FAILED ("unexpected vector capacity #2"); + + // Validate continious use of dynamic allocator. + if (vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("unexpected switch to fixed allocator"); + + // Adding one more should not hit OOM. + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0])) + return FAILED ("failed vector push_back using custom alloc #3"); + + if (dn_vector_ptr_capacity (vector) < init_capacity) + return FAILED ("unexpected vector capacity #3"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_fixed_reset_alloc_capacity (void) +{ + uint8_t buffer [dn_vector_ptr_default_local_allocator_byte_size]; + dn_allocator_fixed_t allocator; + + dn_allocator_fixed_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size); + memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size); + + uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = init_capacity; + + dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc #1"); + + // Add pre-allocated amount of test_vector_ptr_items, should fit into fixed allocator. + for (uint32_t i = 0; i < dn_vector_ptr_capacity (vector); ++i) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i % ARRAY_SIZE (test_vector_ptr_items)])) + return FAILED ("failed vector push_back using custom alloc"); + } + + // Adding one more should hit OOM. + if (dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0])) + return FAILED ("vector push_back failed to triggered OOM"); + + dn_vector_ptr_free (vector); + + // Reset fixed allocator. + dn_allocator_fixed_reset (&allocator); + memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size); + + vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc #2"); + + // Add pre-allocated amount of test_vector_ptr_items, should fit into fixed buffer. + for (uint32_t i = 0; i < dn_vector_ptr_capacity (vector); ++i) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i % ARRAY_SIZE (test_vector_ptr_items)])) + return FAILED ("failed vector push_back using custom alloc"); + } + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_fixed_or_malloc_reset_alloc_capacity (void) +{ + uint8_t buffer [dn_vector_ptr_default_local_allocator_byte_size]; + dn_allocator_fixed_or_malloc_t allocator; + + dn_allocator_fixed_or_malloc_init (&allocator, buffer, dn_vector_ptr_default_local_allocator_byte_size); + memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size); + + uint32_t init_capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = init_capacity; + + dn_vector_ptr_t *vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc #1"); + + // Add pre-allocated amount of test_vector_ptr_items, should fit into fixed allocator. + for (uint32_t i = 0; i < dn_vector_ptr_capacity (vector); ++i) { + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [i % ARRAY_SIZE (test_vector_ptr_items)])) + return FAILED ("failed vector push_back using custom alloc #1"); + } + + // Adding one more should not hit OOM but switch to dynamic allocator. + if (!dn_vector_ptr_push_back (vector, (char *)test_vector_ptr_items [0])) + return FAILED ("failed vector push_back using custom alloc #2"); + + // Validate use of dynamic allocator. + if (vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("unexpected switch to fixed allocator #1"); + + dn_vector_ptr_free (vector); + + vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc #2"); + + // Validate use of dynamic allocator. + if (vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("unexpected switch to fixed allocator #2"); + + dn_vector_ptr_free (vector); + + // Reset fixed part of allocator. + dn_allocator_fixed_or_malloc_reset (&allocator); + memset (buffer, 0, dn_vector_ptr_default_local_allocator_byte_size); + + vector = dn_vector_ptr_custom_alloc (¶ms); + if (!vector) + return FAILED ("failed vector custom alloc #2"); + + // Validate use of fixed allocator. + if (!vector_ptr_owned_by_fixed_allocator ((dn_allocator_fixed_t *)&allocator, vector)) + return FAILED ("custom alloc using fixed allocator failed"); + + dn_vector_ptr_free (vector); + + return OK; +} + +static +RESULT +test_vector_ptr_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_vector_ptr_memory_end_snapshot); + if ( _CrtMemDifference(&dn_vector_ptr_memory_diff_snapshot, &dn_vector_ptr_memory_start_snapshot, &dn_vector_ptr_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &dn_vector_ptr_memory_diff_snapshot ); + return FAILED ("memory leak detected!"); + } +#endif + return OK; +} + +static Test dn_vector_ptr_tests [] = { + {"test_vector_ptr_setup", test_vector_ptr_setup}, + {"test_vector_ptr_alloc", test_vector_ptr_alloc}, + {"test_vector_ptr_free", test_vector_ptr_free}, + {"test_vector_ptr_alloc_capacity", test_vector_ptr_alloc_capacity}, + {"test_vector_ptr_for_iterate", test_vector_ptr_for_iterate}, + {"test_vector_ptr_foreach_iterate", test_vector_ptr_foreach_iterate}, + {"test_vector_ptr_resize", test_vector_ptr_resize}, + {"test_vector_ptr_erase", test_vector_ptr_erase}, + {"test_vector_ptr_erase_fast", test_vector_ptr_erase_fast}, + {"test_vector_ptr_capacity", test_vector_ptr_capacity}, + {"test_vector_ptr_custom_free", test_vector_ptr_custom_free}, + {"test_vector_ptr_clear", test_vector_ptr_clear}, + {"test_vector_ptr_custom_clear", test_vector_ptr_custom_clear}, + {"test_vector_ptr_foreach_it", test_vector_ptr_foreach_it}, + {"test_vector_ptr_foreach_rev_it", test_vector_ptr_foreach_rev_it}, + {"test_vector_ptr_sort", test_vector_ptr_sort}, + {"test_vector_ptr_find", test_vector_ptr_find}, + {"test_vector_ptr_default_local_alloc", test_vector_ptr_default_local_alloc}, + {"test_vector_ptr_local_alloc", test_vector_ptr_local_alloc}, + {"test_vector_ptr_local_alloc_capacity", test_vector_ptr_local_alloc_capacity}, + {"test_vector_ptr_fixed_alloc_capacity", test_vector_ptr_fixed_alloc_capacity}, + {"test_vector_ptr_fixed_or_malloc_alloc_capacity", test_vector_ptr_fixed_or_malloc_alloc_capacity}, + {"test_vector_ptr_fixed_reset_alloc_capacity", test_vector_ptr_fixed_reset_alloc_capacity}, + {"test_vector_ptr_fixed_or_malloc_reset_alloc_capacity", test_vector_ptr_fixed_or_malloc_reset_alloc_capacity}, + {"test_vector_ptr_teardown", test_vector_ptr_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(dn_vector_ptr_tests_init, dn_vector_ptr_tests) diff --git a/src/mono/mono/eventpipe/test/dn-vector-tests.c b/src/mono/mono/eventpipe/test/dn-vector-tests.c new file mode 100644 index 0000000..2c15be3 --- /dev/null +++ b/src/mono/mono/eventpipe/test/dn-vector-tests.c @@ -0,0 +1,1245 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState dn_vector_memory_start_snapshot; +static _CrtMemState dn_vector_memory_end_snapshot; +static _CrtMemState dn_vector_memory_diff_snapshot; +#endif + +static int32_t test_vector_last_disposed_value = 0; +static int32_t test_vector_dispose_call_count = 0; + +static +void +DN_CALLBACK_CALLTYPE +test_vector_dispose_call_func(void *data) +{ + test_vector_last_disposed_value = *((int32_t *)data); + test_vector_dispose_call_count++; +} + +static +RESULT +test_vector_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_vector_memory_start_snapshot); +#endif + return OK; +} + +static +RESULT +test_vector_alloc (void) +{ + dn_vector_t *vector = NULL; + + vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_free (vector); + + dn_vector_custom_alloc_params_t params = {0,}; + params.capacity = 32; + params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT; + + vector = dn_vector_custom_alloc_t (¶ms, int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_init (void) +{ + dn_vector_t vector; + + if (!dn_vector_init_t (&vector, int32_t)) + return FAILED ("init vector"); + + if (vector.size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_dispose (&vector); + + dn_vector_custom_init_params_t params = {0, }; + if (!dn_vector_custom_init_t (&vector, ¶ms, int32_t)) + return FAILED ("init vector"); + + if (vector.size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_dispose (&vector); + + return OK; +} + +#define PREALLOC_SIZE 127 + +static +RESULT +test_vector_alloc_capacity (void) +{ + dn_vector_t *vector = NULL; + + dn_vector_custom_alloc_params_t params = {0, }; + params.capacity = PREALLOC_SIZE; + + vector = dn_vector_custom_alloc_t (¶ms, int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + uint8_t *pre_alloc_data = vector->data; + for (int32_t i = 0; i < PREALLOC_SIZE; ++i) { + dn_vector_insert (dn_vector_end (vector), i); + if (pre_alloc_data != vector->data) + return FAILED ("vector pre-alloc failed"); + } + + dn_vector_free (vector); + + vector = dn_vector_custom_alloc_t (¶ms, int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < PREALLOC_SIZE; ++i) { + if (0 != *((int32_t *)(vector->data) + i)) + return FAILED ("vector was not cleared when allocated"); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_init_capacity (void) +{ + dn_vector_t vector; + dn_vector_custom_init_params_t params = {0, }; + params.capacity = PREALLOC_SIZE; + + if (!dn_vector_custom_init_t (&vector, ¶ms, int32_t)) + return FAILED ("init vector"); + + if (vector.size != 0) + return FAILED ("vector size didn't match"); + + uint8_t *pre_alloc_data = vector.data; + for (int32_t i = 0; i < PREALLOC_SIZE; ++i) { + dn_vector_insert (dn_vector_end (&vector), i); + if (pre_alloc_data != vector.data) + return FAILED ("vector pre-alloc failed"); + } + + dn_vector_dispose (&vector); + + if (!dn_vector_custom_init_t (&vector, ¶ms, int32_t)) + return FAILED ("init vector"); + + if (vector.size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < PREALLOC_SIZE; ++i) { + if (0 != *((int32_t *)(vector.data) + i)) + return FAILED ("vector was not cleared when allocated"); + } + + dn_vector_dispose (&vector); + + return OK; +} + +static +RESULT +test_vector_free (void) +{ + dn_vector_t *vector = NULL; + + vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_free_2 (void) +{ + dn_vector_t *vector = NULL; + + vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < PREALLOC_SIZE; i++) + dn_vector_push_back (vector, i); + + test_vector_last_disposed_value = 0; + test_vector_dispose_call_count = 0; + dn_vector_custom_free (vector, test_vector_dispose_call_func); + if (test_vector_dispose_call_count != PREALLOC_SIZE || test_vector_last_disposed_value != PREALLOC_SIZE - 1) + return FAILED ("vector custom free failed"); + + return OK; +} + +static +RESULT +test_vector_dispose (void) +{ + dn_vector_t vector; + dn_vector_custom_init_params_t params = {0, }; + + if (!dn_vector_custom_init_t (&vector, ¶ms, int32_t)) + return FAILED ("init vector"); + if (vector.size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_dispose (&vector); + + return OK; +} + +static +RESULT +test_vector_dispose_2 (void) +{ + dn_vector_t vector; + dn_vector_custom_init_params_t params = {0, }; + + if (!dn_vector_custom_init_t (&vector, ¶ms, int32_t)) + return FAILED ("init vector"); + if (vector.size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < PREALLOC_SIZE; i++) + dn_vector_push_back (&vector, i); + + test_vector_last_disposed_value = 0; + test_vector_dispose_call_count = 0; + dn_vector_custom_dispose (&vector, test_vector_dispose_call_func); + if (test_vector_dispose_call_count != PREALLOC_SIZE || test_vector_last_disposed_value != PREALLOC_SIZE - 1) + return FAILED ("vector custom dispose failed"); + + return OK; +} + +static +RESULT +test_vector_index (void) +{ + int32_t v; + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + v = 27; + dn_vector_push_back (vector, v); + + if (27 != *dn_vector_index_t (vector, int32_t, 0)) + return FAILED ("dn_vector_index failed"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_front (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (0 != *dn_vector_front_t (vector, int32_t)) + return FAILED ("dn_vector_front_t failed"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_back (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (9 != *dn_vector_back_t (vector, int32_t)) + return FAILED ("dn_vector_back_t failed"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_data (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + int32_t *vector_data = dn_vector_data_t (vector, int32_t); + vector_data++; + + if (1 != *vector_data) + return FAILED ("dn_vector_data_t failed"); + + vector_data = dn_vector_data_t (vector, int32_t); + vector_data += 2; + + if (2 != *vector_data) + return FAILED ("dn_vector_data_t failed"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_begin (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (dn_vector_begin (vector).it != 0) + return FAILED ("vector_begin didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (dn_vector_begin (vector).it != 0) + return FAILED ("vector_begin didn't match"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_end (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (dn_vector_end (vector).it != 0) + return FAILED ("vector_end didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (dn_vector_end (vector).it != dn_vector_size (vector)) + return FAILED ("vector_end didn't didn't return expected value"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_empty (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (dn_vector_empty (vector)) + return FAILED ("empty failed #1"); + + dn_vector_clear (vector); + + if (!dn_vector_empty (vector)) + return FAILED ("empty failed #2"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_size (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != dn_vector_size (vector)) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (dn_vector_size (vector) != 10) + return FAILED ("vector_size failed #1"); + + dn_vector_clear (vector); + + if (dn_vector_size (vector) != 0) + return FAILED ("vector_size failed #2"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_max_size (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (dn_vector_max_size (vector) != UINT32_MAX) + return FAILED ("vector max size didn't match"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_reserve (void) +{ + dn_vector_custom_alloc_params_t params = {0, }; + params.capacity = 10; + + dn_vector_t *vector = dn_vector_custom_alloc_t (¶ms, int32_t); + uint32_t capacity = dn_vector_capacity (vector); + + dn_vector_reserve (vector, 1024); + if (capacity >= dn_vector_capacity (vector)) + return FAILED ("vector reserve failed #1"); + + if (dn_vector_capacity (vector) < 1024) + return FAILED ("vector reserve failed #2"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_capacity (void) +{ + dn_vector_custom_alloc_params_t params = {0, }; + params.capacity = 1024; + + dn_vector_t *vector = dn_vector_custom_alloc_t (¶ms, int32_t); + uint32_t capacity = dn_vector_capacity (vector); + if (capacity < 1024) + return FAILED ("vector capacity didn't match #1"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (dn_vector_capacity (vector) != capacity) + return FAILED ("vector capacity didn't match #2"); + + dn_vector_clear (vector); + + if (dn_vector_capacity (vector) != capacity) + return FAILED ("vector capacity didn't match #3"); + + dn_vector_free (vector); + + params.capacity = 0; + vector = dn_vector_custom_alloc_t (¶ms, int32_t); + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_insert_range (void) +{ + int32_t vs1 [] = {0, 1, 2}; + int32_t vs2 [] = { 3 }; + int32_t vs3 [] = { 4, 5, 6 }; + int32_t vs4 [] = { 7, 8, 9 }; + + dn_vector_t *vector = NULL; + + vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_it_t it = dn_vector_begin (vector); + dn_vector_insert_range (dn_vector_it_next_n (it, 0), (const uint8_t *)vs1, ARRAY_SIZE (vs1)); + dn_vector_insert_range (dn_vector_it_next_n (it, 3), (const uint8_t *)vs3, ARRAY_SIZE (vs3)); + dn_vector_insert_range (dn_vector_it_next_n (it, 6), (const uint8_t *)vs4, ARRAY_SIZE (vs4)); + dn_vector_insert_range (dn_vector_it_next_n (it, 3), (const uint8_t *)vs2, ARRAY_SIZE (vs2)); + + for (uint32_t i = 0; i < vector->size; ++i) { + if (i != *dn_vector_index_t (vector, int32_t, i)) + return FAILED ("insert failed"); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_insert_range_end (void) +{ + int32_t v = 0; + int32_t vs [] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + dn_vector_t *vector = NULL; + + vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_push_back (vector, v); + dn_vector_insert_range (dn_vector_end (vector), (const uint8_t *)vs, ARRAY_SIZE (vs)); + + for (uint32_t i = 0; i < vector->size; ++i) { + if (i != *dn_vector_index_t (vector, int32_t, i)) + return FAILED ("insert_range failed"); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_insert (void) +{ + void *ptr0, *ptr1, *ptr2, *ptr3; + dn_vector_t *vector = dn_vector_alloc_t (void *); + if (vector->size != 0) + return FAILED ("1 Vector size didn't match"); + + dn_vector_it_t it = dn_vector_begin (vector); + dn_vector_insert (it, vector); + + if (vector != *dn_vector_index_t (vector, void *, 0)) + return FAILED ("2 The value in the vector is incorrect"); + + dn_vector_insert (dn_vector_it_next_n (it, 1), vector); + if (vector != *dn_vector_index_t (vector, void *, 1)) + return FAILED ("3 The value in the vector is incorrect"); + + dn_vector_insert (dn_vector_it_next_n (it, 2), vector); + if (vector != *dn_vector_index_t (vector, void *, 2)) + return FAILED ("4 The value in the vector is incorrect"); + + dn_vector_free (vector); + + vector = dn_vector_alloc_t (void *); + if (vector->size != 0) + return FAILED ("5 Vector size didn't match"); + + ptr0 = vector; + ptr1 = vector + 1; + ptr2 = vector + 2; + ptr3 = vector + 3; + + it = dn_vector_begin (vector); + dn_vector_insert (it, ptr0); + dn_vector_insert (dn_vector_it_next_n (it, 1), ptr1); + dn_vector_insert (dn_vector_it_next_n (it, 2), ptr2); + dn_vector_insert (dn_vector_it_next_n (it, 1), ptr3); + + if (ptr0 != *dn_vector_index_t (vector, void *, 0)) + return FAILED ("6 The value in the vector is incorrect"); + + if (ptr3 != *dn_vector_index_t (vector, void *, 1)) + return FAILED ("7 The value in the vector is incorrect"); + + if (ptr1 != *dn_vector_index_t (vector, void *, 2)) + return FAILED ("8 The value in the vector is incorrect"); + + if (ptr2 != *dn_vector_index_t (vector, void *, 3)) + return FAILED ("9 The value in the vector is incorrect"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_push_back (void) +{ + int32_t v; + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + if (0 != vector->size) + return FAILED ("initial vector size is not zero"); + + v = 27; + + dn_vector_push_back (vector, v); + + if (1 != vector->size) + return FAILED ("vector push_back failed"); + + if (27 != *dn_vector_index_t (vector, int32_t, 0)) + return FAILED ("dn_vector_index failed"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_push_back_2 (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + for (uint32_t i = 0; i < vector->size; ++i) { + if (i != *dn_vector_index_t (vector, int32_t, i)) + return FAILED ("vector push_back failed"); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_pop_back (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (*dn_vector_back_t (vector, int32_t) != 9) + return FAILED ("vector back failed"); + + dn_vector_pop_back (vector); + + if (*dn_vector_back_t (vector, int32_t) != 8) + return FAILED ("vector pop_back failed"); + + dn_vector_pop_back (vector); + + if (*dn_vector_back_t (vector, int32_t) != 7) + return FAILED ("vector pop_back failed"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_pop_back_2 (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + if (*dn_vector_back_t (vector, int32_t) != 9) + return FAILED ("vector back failed"); + + test_vector_last_disposed_value = 0; + dn_vector_custom_pop_back (vector, test_vector_dispose_call_func); + if (test_vector_last_disposed_value != 9) + return FAILED ("vector custom_pop_back failed, wrong disposed value #1"); + + if (*dn_vector_back_t (vector, int32_t) != 8) + return FAILED ("vector pop_back failed"); + + test_vector_last_disposed_value = 0; + dn_vector_custom_pop_back (vector, test_vector_dispose_call_func); + if (test_vector_last_disposed_value != 8) + return FAILED ("vector custom_pop_back failed, wrong disposed value #2"); + + if (*dn_vector_back_t (vector, int32_t) != 7) + return FAILED ("vector pop_back failed"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_erase (void) +{ + int32_t v [] = { 30, 29, 28, 27, 26, 25 }; + + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_insert_range (dn_vector_end (vector), (const uint8_t *)v, ARRAY_SIZE (v)); + + if (ARRAY_SIZE (v) != vector->size) + return FAILED ("insert_range fail"); + + dn_vector_erase (dn_vector_it_next_n (dn_vector_begin (vector), 3)); + + if (5 != vector->size) + return FAILED ("erase failed to update size"); + + if (26 != *dn_vector_index_t (vector, int32_t, 3)) + return FAILED ("erase failed to update the vector"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_erase_2 (void) +{ + int32_t vs [] = { 0, 2, 3, 4, 5, 6, 7, 9 }; + + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + test_vector_last_disposed_value = 0; + dn_vector_custom_erase (dn_vector_it_next_n (dn_vector_begin (vector), 1), test_vector_dispose_call_func); + if (test_vector_last_disposed_value != 1) + return FAILED ("vector custom erase failed #1"); + + test_vector_last_disposed_value = 0; + dn_vector_custom_erase (dn_vector_it_next_n (dn_vector_begin (vector), 7), test_vector_dispose_call_func); + if (test_vector_last_disposed_value != 8) + return FAILED ("vector custom erase failed #2"); + + for (uint32_t i = 0; i < vector->size; ++i) { + if (vs [i] != *dn_vector_index_t (vector, int32_t, i)) + return FAILED ("vector erase failed"); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_erase_3 (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_erase (dn_vector_begin (vector)); + + if (((uint32_t *)vector->data) [9] != 0) + return FAILED ("erase didn't zero memory."); + + dn_vector_free (vector); + + dn_vector_custom_alloc_params_t params = {0, }; + params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT; + vector = dn_vector_custom_alloc_t (¶ms, int32_t); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_erase (dn_vector_begin (vector)); + + if (((uint32_t *)vector->data) [9] == 0) + return FAILED ("resize zeroed memory, but shouldn't."); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_erase_fast (void) +{ + int32_t v [] = { 30, 29, 28, 27, 26, 25 }; + + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_insert_range (dn_vector_end (vector), (const uint8_t *)v, ARRAY_SIZE (v)); + + if (ARRAY_SIZE (v) != vector->size) + return FAILED ("insert_range fail"); + + dn_vector_erase_fast (dn_vector_it_next_n (dn_vector_begin (vector), 3)); + + if (5 != vector->size) + return FAILED ("erase failed to update size"); + + if (27 == *dn_vector_index_t (vector, int32_t, 3)) + return FAILED ("erase failed to update the vector"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_erase_fast_2 (void) +{ + int32_t v [] = { 30, 29, 28, 27, 26, 25 }; + + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + dn_vector_insert_range (dn_vector_end (vector), (const uint8_t *)v, ARRAY_SIZE (v)); + + if (ARRAY_SIZE (v) != vector->size) + return FAILED ("insert_range fail"); + + test_vector_last_disposed_value = 0; + dn_vector_custom_erase_fast (dn_vector_it_next_n (dn_vector_begin (vector), 3), test_vector_dispose_call_func); + if (test_vector_last_disposed_value != 27) + return FAILED ("custom erase failed to dispose correct value"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_erase_fast_3 (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_erase_fast (dn_vector_begin (vector)); + + if (((uint32_t *)vector->data) [9] != 0) + return FAILED ("erase didn't zero memory."); + + dn_vector_free (vector); + + dn_vector_custom_alloc_params_t params = {0, }; + params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT; + vector = dn_vector_custom_alloc_t (¶ms, int32_t); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_erase_fast (dn_vector_begin (vector)); + + if (((uint32_t *)vector->data) [9] == 0) + return FAILED ("resize zeroed memory, but shouldn't."); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_resize (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_resize (vector, 5); + if (vector->size != 5) + return FAILED ("vector size didn't match #2"); + + for (uint32_t i = 0; i < vector->size; ++i) { + if (i != *dn_vector_index_t (vector, int32_t, i)) + return FAILED ("resize didn't preserve data"); + } + + dn_vector_resize (vector, 0); + if (vector->size != 0) + return FAILED ("vector size didn't match #3"); + + dn_vector_free (vector); + + vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match #4"); + + dn_vector_resize (vector, PREALLOC_SIZE); + + const uint8_t *vector_data = vector->data; + for (int32_t i = 0; i < PREALLOC_SIZE; ++i) { + *dn_vector_index_t (vector, int32_t, i) = i; + if (vector->data != vector_data) + return FAILED ("vector resize failed"); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_resize_2 (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + test_vector_dispose_call_count = 0; + test_vector_last_disposed_value = 0; + dn_vector_custom_resize (vector, 5, test_vector_dispose_call_func); + if (vector->size != 5 || test_vector_dispose_call_count != 5 || test_vector_last_disposed_value != 9) + return FAILED ("vector custom resize failed #1"); + + for (uint32_t i = 0; i < vector->size; ++i) { + if (i != *dn_vector_index_t (vector, int32_t, i)) + return FAILED ("resize didn't preserve data"); + } + + test_vector_dispose_call_count = 0; + test_vector_last_disposed_value = 0; + dn_vector_custom_resize (vector, 0, test_vector_dispose_call_func); + if (vector->size != 0 || test_vector_dispose_call_count != 5 || test_vector_last_disposed_value != 4) + return FAILED ("vector custom resize failed #2"); + + dn_vector_free (vector); + + vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match #2"); + + test_vector_dispose_call_count = 0; + test_vector_last_disposed_value = 0; + dn_vector_custom_resize (vector, PREALLOC_SIZE, test_vector_dispose_call_func); + if (test_vector_dispose_call_count != 0 || test_vector_last_disposed_value != 0) + return FAILED ("vector custom resize failed #3"); + + const uint8_t *vector_data = vector->data; + for (int32_t i = 0; i < PREALLOC_SIZE; ++i) { + *dn_vector_index_t (vector, int32_t, i) = i; + if (vector->data != vector_data) + return FAILED ("vector resize failed"); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_resize_3 (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_resize (vector, 5); + + for (uint32_t i = 5; i < 10; ++i) { + if (((uint32_t *)vector->data) [i] != 0) + return FAILED ("resize didn't zero memory."); + } + + dn_vector_free (vector); + + dn_vector_custom_alloc_params_t params = {0, }; + params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT; + vector = dn_vector_custom_alloc_t (¶ms, int32_t); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_resize (vector, 5); + + for (uint32_t i = 5; i < 10; ++i) { + if (((uint32_t *)vector->data) [i] != i) + return FAILED ("resize zeroed memory, but shouldn't."); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_clear (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_clear (vector); + if (vector->size != 0) + return FAILED ("vector size didn't match #2"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_clear_2 (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + test_vector_dispose_call_count = 0; + test_vector_last_disposed_value = 0; + dn_vector_custom_clear (vector, test_vector_dispose_call_func); + if (vector->size != 0 || test_vector_dispose_call_count != 10 || test_vector_last_disposed_value != 9) + return FAILED ("vector size custom clear failed"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_clear_3 (void) +{ + dn_vector_t *vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match #1"); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_clear (vector); + + for (int32_t i = 0; i < 10; ++i) { + if (((uint32_t *)vector->data) [i] != 0) + return FAILED ("clear didn't zero memory."); + } + + dn_vector_free (vector); + + dn_vector_custom_alloc_params_t params = {0, }; + params.attributes = DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT; + vector = dn_vector_custom_alloc_t (¶ms, int32_t); + + for (int32_t i = 0; i < 10; ++i) + dn_vector_push_back (vector, i); + + dn_vector_clear (vector); + + for (int32_t i = 0; i < 10; ++i) { + if (((uint32_t *)vector->data) [i] != i) + return FAILED ("clear zeroed memory, but shouldn't."); + } + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_foreach_it (void) +{ + uint32_t count = 0; + dn_vector_t *vector = dn_vector_alloc_t (uint32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (uint32_t i = 0; i < 100; ++i) + dn_vector_push_back (vector, i); + + DN_VECTOR_FOREACH_BEGIN (uint32_t, value, vector) { + if (value != count) + return FAILED ("foreach iterator failed #1"); + count++; + } DN_VECTOR_FOREACH_END; + + if (count != dn_vector_size (vector)) + return FAILED ("foreach iterator failed #2"); + + dn_vector_free (vector); + return OK; +} + +static +RESULT +test_vector_foreach_rev_it (void) +{ + uint32_t count = 100; + dn_vector_t *vector = dn_vector_alloc_t (uint32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (uint32_t i = 0; i < 100; ++i) + dn_vector_push_back (vector, i); + + DN_VECTOR_FOREACH_RBEGIN (uint32_t, value, vector) { + if (value != count - 1) + return FAILED ("foreach reverse iterator failed #1"); + count--; + } DN_VECTOR_FOREACH_END; + + if (count != 0) + return FAILED ("foreach reverse iterator failed #2"); + + dn_vector_free (vector); + return OK; +} + +static +RESULT +test_vector_big (void) +{ + dn_vector_t *vector; + int32_t i; + + vector = dn_vector_alloc_t (int32_t); + if (vector->size != 0) + return FAILED ("vector size didn't match"); + + for (i = 0; i < 10000; i++) + dn_vector_push_back (vector, i); + + for (i = 0; i < 10000; i++) + if (*dn_vector_index_t (vector, int32_t, i) != i) + return FAILED ("vector value didn't match"); + + dn_vector_free (vector); + + return OK; +} + +static +RESULT +test_vector_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&dn_vector_memory_end_snapshot); + if ( _CrtMemDifference(&dn_vector_memory_diff_snapshot, &dn_vector_memory_start_snapshot, &dn_vector_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &dn_vector_memory_diff_snapshot ); + return FAILED ("memory leak detected!"); + } +#endif + return OK; +} + +static Test dn_vector_tests [] = { + {"test_vector_setup", test_vector_setup}, + {"test_vector_alloc", test_vector_alloc}, + {"test_vector_init", test_vector_init}, + {"test_vector_alloc_capacity", test_vector_alloc_capacity}, + {"test_vector_init_capacity", test_vector_init_capacity}, + {"test_vector_free", test_vector_free}, + {"test_vector_free_2", test_vector_free_2}, + {"test_vector_dipose", test_vector_dispose}, + {"test_vector_dipose_2", test_vector_dispose_2}, + {"test_vector_index", test_vector_index}, + {"test_vector_front", test_vector_front}, + {"test_vector_back", test_vector_back}, + {"test_vector_data", test_vector_data}, + {"test_vector_begin", test_vector_begin}, + {"test_vector_end", test_vector_end}, + {"test_vector_empty", test_vector_empty}, + {"test_vector_size", test_vector_size}, + {"test_vector_max_size", test_vector_max_size}, + {"test_vector_reserve", test_vector_reserve}, + {"test_vector_capacity", test_vector_capacity}, + {"test_vector_insert_range", test_vector_insert_range}, + {"test_vector_insert_range_end", test_vector_insert_range_end}, + {"test_vector_insert", test_vector_insert}, + {"test_vector_push_back", test_vector_push_back}, + {"test_vector_push_back_2", test_vector_push_back_2}, + {"test_vector_pop_back", test_vector_pop_back}, + {"test_vector_pop_back_2", test_vector_pop_back_2}, + {"test_vector_erase", test_vector_erase}, + {"test_vector_erase_2", test_vector_erase_2}, + {"test_vector_erase_3", test_vector_erase_3}, + {"test_vector_erase_fast", test_vector_erase_fast}, + {"test_vector_erase_fast_2", test_vector_erase_fast_2}, + {"test_vector_erase_fast_3", test_vector_erase_fast_3}, + {"test_vector_resize", test_vector_resize}, + {"test_vector_resize_2", test_vector_resize_2}, + {"test_vector_resize_3", test_vector_resize_3}, + {"test_vector_clear", test_vector_clear}, + {"test_vector_clear_2", test_vector_clear_2}, + {"test_vector_clear_3", test_vector_clear_3}, + {"test_vector_foreach_it", test_vector_foreach_it}, + {"test_vector_foreach_rev_it", test_vector_foreach_rev_it}, + {"test_vector_big", test_vector_big}, + {"test_vector_teardown", test_vector_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(dn_vector_tests_init, dn_vector_tests) diff --git a/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c b/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c index 5dbc2fc..64c7202 100644 --- a/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c +++ b/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c @@ -524,21 +524,21 @@ test_buffer_manager_perf (void) test_location = 3; while (!done) { - int64_t start = ep_perf_timestamp_get (); + int64_t start_write_events = ep_perf_timestamp_get (); write_result = write_events (buffer_manager, thread_handle, session, ep_event, 10 * 1000 * 1000, &events_written); - int64_t stop = ep_perf_timestamp_get (); + int64_t stop_write_events = ep_perf_timestamp_get (); - accumulated_buffer_manager_write_time_ticks += stop - start; + accumulated_buffer_manager_write_time_ticks += stop_write_events - start_write_events; total_events_written += events_written; if (write_result || (total_events_written > 10 * 1000 * 1000)) { done = true; } else { bool ignore_events_written; - int64_t start = ep_perf_timestamp_get (); + int64_t start_ep_buffer_manager_write_all_buffers_to_file = ep_perf_timestamp_get (); ep_buffer_manager_write_all_buffers_to_file (buffer_manager, null_file, ep_perf_timestamp_get (), &ignore_events_written); - int64_t stop = ep_perf_timestamp_get (); + int64_t stop_ep_buffer_manager_write_all_buffers_to_file = ep_perf_timestamp_get (); - accumulated_buffer_to_null_file_time_ticks += stop - start; + accumulated_buffer_to_null_file_time_ticks += stop_ep_buffer_manager_write_all_buffers_to_file - start_ep_buffer_manager_write_all_buffers_to_file; } } diff --git a/src/mono/mono/eventpipe/test/ep-tests.c b/src/mono/mono/eventpipe/test/ep-tests.c index fd13622..20e6fea 100644 --- a/src/mono/mono/eventpipe/test/ep-tests.c +++ b/src/mono/mono/eventpipe/test/ep-tests.c @@ -85,7 +85,7 @@ test_stress_create_delete_provider (void) for (uint32_t i = 0; i < 1000; ++i) { char *provider_name = g_strdup_printf (TEST_PROVIDER_NAME "_%i", i); - test_providers [i] = ep_create_provider (provider_name, NULL, NULL, NULL); + test_providers [i] = ep_create_provider (provider_name, NULL, NULL); g_free (provider_name); if (!test_providers [i]) { @@ -262,7 +262,7 @@ validate_default_provider_config (EventPipeSession *session) uint32_t test_location = 0; EventPipeSessionProviderList *provider_list = ep_session_get_providers (session); - EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (provider_list), "Microsoft-Windows-DotNETRuntime"); + EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (provider_list), "Microsoft-Windows-DotNETRuntime"); ep_raise_error_if_nok (session_provider != NULL); test_location = 1; @@ -283,7 +283,7 @@ validate_default_provider_config (EventPipeSession *session) test_location = 5; - session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (provider_list), "Microsoft-Windows-DotNETRuntimePrivate"); + session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (provider_list), "Microsoft-Windows-DotNETRuntimePrivate"); ep_raise_error_if_nok (session_provider != NULL); test_location = 6; @@ -304,7 +304,7 @@ validate_default_provider_config (EventPipeSession *session) test_location = 10; - session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (provider_list), "Microsoft-DotNETCore-SampleProfiler"); + session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (provider_list), "Microsoft-DotNETCore-SampleProfiler"); ep_raise_error_if_nok (session_provider != NULL); test_location = 11; @@ -492,7 +492,7 @@ test_enable_disable_provider_config (void) test_location = 2; EventPipeSessionProviderList *provider_list = ep_session_get_providers ((EventPipeSession *)session_id); - EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (provider_list), TEST_PROVIDER_NAME); + EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (provider_list), TEST_PROVIDER_NAME); ep_raise_error_if_nok (session_provider != NULL); test_location = 3; diff --git a/src/mono/mono/eventpipe/test/ep-tests.h b/src/mono/mono/eventpipe/test/ep-tests.h index 5fd91ce..871d0c6 100644 --- a/src/mono/mono/eventpipe/test/ep-tests.h +++ b/src/mono/mono/eventpipe/test/ep-tests.h @@ -3,6 +3,15 @@ #include +// Container type tests. +DEFINE_TEST_GROUP_INIT_H(dn_vector_tests_init); +DEFINE_TEST_GROUP_INIT_H(dn_vector_ptr_tests_init); +DEFINE_TEST_GROUP_INIT_H(dn_fwd_list_tests_init); +DEFINE_TEST_GROUP_INIT_H(dn_list_tests_init); +DEFINE_TEST_GROUP_INIT_H(dn_queue_tests_init); +DEFINE_TEST_GROUP_INIT_H(dn_umap_tests_init); + +// EventPipe tests. DEFINE_TEST_GROUP_INIT_H(ep_setup_tests_init); DEFINE_TEST_GROUP_INIT_H(ep_rt_tests_init); DEFINE_TEST_GROUP_INIT_H(ep_fastserializer_tests_init); @@ -18,6 +27,12 @@ DEFINE_TEST_GROUP_INIT_H(ep_teardown_tests_init); const static Group test_groups [] = { + {"vector", dn_vector_tests_init}, + {"ptr-vector", dn_vector_ptr_tests_init}, + {"fwd_list", dn_fwd_list_tests_init}, + {"list", dn_list_tests_init}, + {"queue", dn_queue_tests_init}, + {"umap", dn_umap_tests_init}, {"setup", ep_setup_tests_init}, {"rt", ep_rt_tests_init}, {"fastserializer", ep_fastserializer_tests_init}, diff --git a/src/native/containers/containers.cmake b/src/native/containers/containers.cmake new file mode 100644 index 0000000..dd8829e --- /dev/null +++ b/src/native/containers/containers.cmake @@ -0,0 +1,27 @@ +set (SHARED_CONTAINER_SOURCES "") +set (SHARED_CONTAINER_HEADERS "") + +list(APPEND SHARED_CONTAINER_SOURCES + dn-allocator.c + dn-fwd-list.c + dn-list.c + dn-queue.c + dn-umap.c + dn-vector.c +) + +list(APPEND SHARED_CONTAINER_HEADERS + dn-allocator.h + dn-fwd-list.h + dn-list.h + dn-queue.h + dn-sort-frag.inc + dn-umap.h + dn-umap-t.h + dn-utils.h + dn-vector.h + dn-vector-priv.h + dn-vector-ptr.h + dn-vector-t.h + dn-vector-types.h +) diff --git a/src/native/containers/dn-allocator.c b/src/native/containers/dn-allocator.c new file mode 100644 index 0000000..4e3cf56 --- /dev/null +++ b/src/native/containers/dn-allocator.c @@ -0,0 +1,324 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "dn-allocator.h" + +static void * +fixed_vtable_alloc ( + dn_allocator_t *allocator, + size_t size); + +static void * +fixed_vtable_realloc ( + dn_allocator_t *allocator, + void *block, + size_t size); + +static void +fixed_vtable_free ( + dn_allocator_t *allocator, + void *block); + +static void * +fixed_alloc ( + dn_allocator_fixed_data_t *data, + size_t size); + +static void * +fixed_realloc ( + dn_allocator_fixed_data_t *data, + void *block, + size_t size); + +static void +fixed_free ( + dn_allocator_fixed_data_t *data, + void *block); + +static bool +fixed_owns_ptr ( + dn_allocator_fixed_data_t *data, + void *ptr); + +static void * +fixed_memcpy ( + void *dst, + void *src, + size_t size); + +static void * +fixed_or_malloc_vtable_alloc ( + dn_allocator_t *allocator, + size_t size); + +static void * +fixed_or_malloc_vtable_realloc ( + dn_allocator_t *allocator, + void *block, + size_t size); + +static void +fixed_or_malloc_vtable_free ( + dn_allocator_t *allocator, + void *block); + +static void * +fixed_or_malloc_alloc ( + dn_allocator_fixed_or_malloc_data_t *data, + size_t size); + +static void * +fixed_or_malloc_realloc ( + dn_allocator_fixed_or_malloc_data_t *data, + void *block, + size_t size); + +static void +fixed_or_malloc_free ( + dn_allocator_fixed_or_malloc_data_t *data, + void *block); + +static dn_allocator_vtable_t fixed_vtable = { + fixed_vtable_alloc, + fixed_vtable_realloc, + fixed_vtable_free, +}; + +static dn_allocator_vtable_t fixed_or_malloc_vtable = { + fixed_or_malloc_vtable_alloc, + fixed_or_malloc_vtable_realloc, + fixed_or_malloc_vtable_free, +}; + +static void * +fixed_vtable_alloc ( + dn_allocator_t *allocator, + size_t size) +{ + return fixed_alloc (&((dn_allocator_fixed_t *)allocator)->_data, size); +} + +static void * +fixed_vtable_realloc ( + dn_allocator_t *allocator, + void *block, + size_t size) +{ + return fixed_realloc (&((dn_allocator_fixed_t *)allocator)->_data, block, size); +} + +static void +fixed_vtable_free ( + dn_allocator_t *allocator, + void *block) +{ + fixed_free (&((dn_allocator_fixed_t *)allocator)->_data, block); +} + +static void * +fixed_alloc ( + dn_allocator_fixed_data_t *data, + size_t size) +{ + void *ptr = data->_ptr; + void *new_ptr = (uint8_t *)ptr + DN_ALLOCATOR_ALIGN_SIZE (size + DN_ALLOCATOR_MEM_ALIGN8, DN_ALLOCATOR_MEM_ALIGN8); + + // Check if new memory address triggers OOM. + if (!fixed_owns_ptr (data, new_ptr)) + return NULL; + + data->_ptr = new_ptr; + + *((size_t *)ptr) = size; + return (uint8_t *)ptr + DN_ALLOCATOR_MEM_ALIGN8; +} + +static void * +fixed_realloc ( + dn_allocator_fixed_data_t *data, + void *block, + size_t size) +{ + if (block && !fixed_owns_ptr (data, block)) + return NULL; + + void *ptr = data->_ptr; + void *new_ptr = (uint8_t *)ptr + DN_ALLOCATOR_ALIGN_SIZE (size + DN_ALLOCATOR_MEM_ALIGN8, DN_ALLOCATOR_MEM_ALIGN8); + + // Check if new memory address triggers OOM. + if (!fixed_owns_ptr (data, new_ptr)) + return NULL; + + data->_ptr = new_ptr; + + if (block) + fixed_memcpy ((uint8_t *)ptr + DN_ALLOCATOR_MEM_ALIGN8, block, size); + + *((size_t *)ptr) = size; + return (uint8_t *)ptr + DN_ALLOCATOR_MEM_ALIGN8; +} + +static void +fixed_free ( + dn_allocator_fixed_data_t *data, + void *block) +{ + DN_UNREFERENCED_PARAMETER (data); + DN_UNREFERENCED_PARAMETER (block); + + // Fixed buffer doesn't support free. +} + +static inline bool +fixed_owns_ptr ( + dn_allocator_fixed_data_t *data, + void *ptr) +{ + return (ptr >= data->_begin && ptr < data->_end); +} + +static void * +fixed_memcpy ( + void *dst, + void *src, + size_t size) +{ + void *result = NULL; + if (dst && src) { + size_t *src_size = (size_t *)((uint8_t *)src - DN_ALLOCATOR_MEM_ALIGN8); + if (src_size && src_size < (size_t *)src) + result = memcpy (dst, src, size < *src_size ? size : *src_size); + } + + return result; +} + +static void * +fixed_or_malloc_vtable_alloc ( + dn_allocator_t *allocator, + size_t size) +{ + return fixed_or_malloc_alloc (&((dn_allocator_fixed_or_malloc_t *)allocator)->_data, size); +} + +static void * +fixed_or_malloc_vtable_realloc ( + dn_allocator_t *allocator, + void *block, + size_t size) +{ + return fixed_or_malloc_realloc (&((dn_allocator_fixed_or_malloc_t *)allocator)->_data, block, size); +} + +static void +fixed_or_malloc_vtable_free ( + dn_allocator_t *allocator, + void *block) +{ + fixed_or_malloc_free (&((dn_allocator_fixed_or_malloc_t *)allocator)->_data, block); +} + +static void * +fixed_or_malloc_alloc ( + dn_allocator_fixed_or_malloc_data_t *data, + size_t size) +{ + void *result = NULL; + + result = fixed_alloc (data, size); + if (!result) + result = malloc (size); + + return result; +} + +static void * +fixed_or_malloc_realloc ( + dn_allocator_fixed_or_malloc_data_t *data, + void *block, + size_t size) +{ + // Check if ptr is owned by fixed buffer, if not, its own by heap. + if (block && !fixed_owns_ptr (data, block)) + return realloc (block, size); + + // Try realloc using fixed buffer. + void *result = fixed_realloc (data, block, size); + if (!result) { + // Fixed buffer OOM, fallback to heap. + result = malloc (size); + + // Copy data from fixed buffer to allocated heap memory. + if (block && result) + result = fixed_memcpy (result, block, size); + } + + return result; +} + +static void +fixed_or_malloc_free ( + dn_allocator_fixed_or_malloc_data_t *data, + void *block) +{ + if (fixed_owns_ptr (data, block)) + fixed_free (data, block); + else + free (block); +} + +dn_allocator_fixed_t * +dn_allocator_fixed_init ( + dn_allocator_fixed_t *allocator, + void *block, + size_t size) +{ + void *begin = DN_ALLOCATOR_ALIGN_PTR_TO (block, DN_ALLOCATOR_MEM_ALIGN8); + void *end = (uint8_t *)begin + size - ((uint8_t *)begin - (uint8_t *)block); + + if (end < begin) + return NULL; + + allocator->_data._begin = begin; + allocator->_data._ptr = begin; + allocator->_data._end = end; + + allocator->_vtable = &fixed_vtable; + + return allocator; +} + +dn_allocator_fixed_t * +dn_allocator_fixed_reset(dn_allocator_fixed_t *allocator) +{ + allocator->_data._ptr = allocator->_data._begin; + return allocator; +} + +dn_allocator_fixed_or_malloc_t * +dn_allocator_fixed_or_malloc_reset(dn_allocator_fixed_or_malloc_t *allocator) +{ + allocator->_data._ptr = allocator->_data._begin; + return allocator; +} + +dn_allocator_fixed_or_malloc_t * +dn_allocator_fixed_or_malloc_init ( + dn_allocator_fixed_or_malloc_t *allocator, + void *block, + size_t size) +{ + void *begin = DN_ALLOCATOR_ALIGN_PTR_TO (block, DN_ALLOCATOR_MEM_ALIGN8); + void *end = (uint8_t *)begin + size - ((uint8_t *)begin - (uint8_t *)block); + + if (end < begin) + return NULL; + + allocator->_data._begin = begin; + allocator->_data._ptr = begin; + allocator->_data._end = end; + + allocator->_vtable = &fixed_or_malloc_vtable; + + return allocator; +} diff --git a/src/native/containers/dn-allocator.h b/src/native/containers/dn-allocator.h new file mode 100644 index 0000000..ef4e3d1 --- /dev/null +++ b/src/native/containers/dn-allocator.h @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_ALLOCATOR_H__ +#define __DN_ALLOCATOR_H__ + +#include "dn-utils.h" +#include +#include + +#define DN_ALLOCATOR_MEM_ALIGN8 8 +#define DN_ALLOCATOR_MEM_ALIGN16 16 +#define DN_ALLOCATOR_MAX_ALIGNMENT DN_ALLOCATOR_MEM_ALIGN16 +#define DN_ALLOCATOR_ALIGN_SIZE(size,align) (((size) + align - 1) & ~(align - 1)) +#define DN_ALLOCATOR_ALIGN_PTR_TO(ptr,align) (void *)((((ptrdiff_t)(ptr)) + (ptrdiff_t)(align - 1)) & (~((ptrdiff_t)(align - 1)))) + +typedef struct _dn_allocator_vtable_t dn_allocator_vtable_t; +typedef struct _dn_allocator_t dn_allocator_t; +typedef struct _dn_allocator_fixed_t dn_allocator_fixed_t; +typedef struct _dn_allocator_fixed_data_t dn_allocator_fixed_data_t; +typedef struct _dn_allocator_fixed_or_malloc_t dn_allocator_fixed_or_malloc_t; +typedef struct _dn_allocator_fixed_data_t dn_allocator_fixed_or_malloc_data_t; + +struct _dn_allocator_vtable_t { + void *(*_alloc)(dn_allocator_t *, size_t); + void *(*_realloc)(dn_allocator_t *, void *, size_t); + void (*_free)(dn_allocator_t *, void *); +}; + +struct _dn_allocator_t { + dn_allocator_vtable_t *_vtable; +}; + +struct _dn_allocator_fixed_data_t { + void *_begin; + void *_end; + void *_ptr; +}; + +struct _dn_allocator_fixed_t { + dn_allocator_vtable_t *_vtable; + dn_allocator_fixed_data_t _data; +}; + +struct _dn_allocator_fixed_or_malloc_t { + dn_allocator_vtable_t *_vtable; + dn_allocator_fixed_or_malloc_data_t _data; +}; + +static inline void * +dn_allocator_alloc ( + dn_allocator_t *allocator, + size_t size) +{ + return allocator ? + allocator->_vtable->_alloc (allocator, size) : + malloc (size); +} + +static inline void * +dn_allocator_realloc ( + dn_allocator_t *allocator, + void *block, + size_t size) +{ + return allocator ? + allocator->_vtable->_realloc (allocator, block, size) : + realloc (block, size); +} + +static inline void +dn_allocator_free ( + dn_allocator_t *allocator, + void *block) +{ + allocator ? + allocator->_vtable->_free (allocator, block) : + free (block); +} + +dn_allocator_fixed_t * +dn_allocator_fixed_init ( + dn_allocator_fixed_t *allocator, + void *block, + size_t size); + +dn_allocator_fixed_t * +dn_allocator_fixed_reset (dn_allocator_fixed_t *allocator); + +dn_allocator_fixed_or_malloc_t * +dn_allocator_fixed_or_malloc_init ( + dn_allocator_fixed_or_malloc_t *allocator, + void *block, + size_t size); + +dn_allocator_fixed_or_malloc_t * +dn_allocator_fixed_or_malloc_reset (dn_allocator_fixed_or_malloc_t *allocator); + +#define DN_ALLOCATOR_FIXED_OR_MALLOC(var_name, buffer_size) \ + uint8_t __buffer_##var_name [buffer_size]; \ + dn_allocator_fixed_or_malloc_t var_name; \ + dn_allocator_fixed_or_malloc_init (&var_name, __buffer_##var_name, buffer_size); + +#define DN_DEFAULT_ALLOCATOR NULL +#define DN_DEFAULT_LOCAL_ALLOCATOR(var_name, buffer_size) DN_ALLOCATOR_FIXED_OR_MALLOC (var_name, buffer_size) + +#endif /* __DN_ALLOCATOR_H__ */ diff --git a/src/native/containers/dn-fwd-list.c b/src/native/containers/dn-fwd-list.c new file mode 100644 index 0000000..34b20e8 --- /dev/null +++ b/src/native/containers/dn-fwd-list.c @@ -0,0 +1,406 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/* (C) 2006 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "dn-fwd-list.h" + +dn_fwd_list_node_t _fwd_list_before_begin_it_node = { 0 }; + +static dn_fwd_list_node_t * +fwd_list_new_node ( + dn_allocator_t *allocator, + dn_fwd_list_node_t *node, + void *data) +{ + dn_fwd_list_node_t *new_node = (dn_fwd_list_node_t *)dn_allocator_alloc (allocator, sizeof (dn_fwd_list_node_t)); + if (DN_UNLIKELY (!new_node)) + return NULL; + + new_node->data = data; + new_node->next = node; + + return new_node; +} + +static dn_fwd_list_node_t * +fwd_list_insert_node_before ( + dn_allocator_t *allocator, + dn_fwd_list_node_t *node, + void *data) +{ + return fwd_list_new_node (allocator, node, data); +} + +static dn_fwd_list_node_t * +fwd_list_insert_node_after ( + dn_allocator_t *allocator, + dn_fwd_list_node_t *node, + void *data) +{ + node->next = fwd_list_insert_node_before (allocator, node->next, data); + return node->next; +} + +static void +fwd_list_free_node ( + dn_allocator_t *allocator, + dn_fwd_list_node_t *node) +{ + dn_allocator_free (allocator, node); +} + +static void +fwd_list_dispose_node ( + dn_allocator_t *allocator, + dn_fwd_list_dispose_func_t dispose_func, + dn_fwd_list_node_t *node) +{ + if (node && dispose_func) + dispose_func (node->data); + dn_allocator_free (allocator, node); +} + +static void +fwd_list_remove_node ( + dn_fwd_list_t *list, + const void *data, + dn_fwd_list_equal_func_t equal_func, + dn_fwd_list_dispose_func_t dispose_func) +{ + dn_fwd_list_node_t *current = list->head; + dn_fwd_list_node_t *prev = current; + dn_fwd_list_node_t *next; + + while (current) { + next = current->next; + if ((equal_func && equal_func (current->data, data)) || (!equal_func && current->data == data)) { + if (current == list->head) { + list->head = next; + } else if (current == list->tail) { + prev->next = NULL; + list->tail = prev; + } else { + prev->next = next; + } + fwd_list_dispose_node (list->_internal._allocator, dispose_func, current); + } else { + prev = current; + } + + current = next; + } +} + +dn_fwd_list_t * +dn_fwd_list_custom_alloc (dn_allocator_t *allocator) +{ + dn_fwd_list_t *list = (dn_fwd_list_t *)dn_allocator_alloc (allocator, sizeof (dn_fwd_list_t)); + if (!dn_fwd_list_custom_init (list, allocator)) { + dn_allocator_free (allocator, list); + return NULL; + } + + return list; +} + +bool +dn_fwd_list_custom_init ( + dn_fwd_list_t *list, + dn_allocator_t *allocator) +{ + if (DN_UNLIKELY (!list)) + return false; + + memset (list, 0, sizeof(dn_fwd_list_t)); + list->_internal._allocator = allocator; + + return true; +} + +void +dn_fwd_list_custom_free ( + dn_fwd_list_t *list, + dn_fwd_list_dispose_func_t dispose_func) +{ + if (DN_UNLIKELY(!list)) + return; + + dn_fwd_list_custom_dispose (list, dispose_func); + dn_allocator_free (list->_internal._allocator, list); +} + +void +dn_fwd_list_custom_dispose ( + dn_fwd_list_t *list, + dn_fwd_list_dispose_func_t dispose_func) +{ + if (DN_UNLIKELY(!list)) + return; + + dn_fwd_list_node_t *current = list->head; + while (current) { + dn_fwd_list_node_t *next = current->next; + if (dispose_func) + dispose_func (current->data); + dn_allocator_free (list->_internal._allocator, current); + current = next; + } +} + +void +dn_fwd_list_custom_clear ( + dn_fwd_list_t *list, + dn_fwd_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list); + + dn_fwd_list_custom_dispose (list, dispose_func); + + list->head = NULL; + list->tail = NULL; +} + +dn_fwd_list_result_t +dn_fwd_list_insert_after ( + dn_fwd_list_it_t position, + void *data) +{ + dn_fwd_list_t *list = position._internal._list; + + DN_ASSERT (list); + + if (position.it == &_fwd_list_before_begin_it_node || !list->head) { + position.it = fwd_list_insert_node_before (list->_internal._allocator, list->head, data); + list->head = position.it; + } else if (!position.it) { + position.it = fwd_list_insert_node_after (list->_internal._allocator, list->tail, data); + } else { + position.it = fwd_list_insert_node_after (list->_internal._allocator, position.it, data); + } + + if (position.it && !position.it->next) + list->tail = position.it; + + dn_fwd_list_result_t result = { { position.it, {position._internal._list } }, position.it != NULL }; + return result; +} + +dn_fwd_list_result_t +dn_fwd_list_insert_range_after ( + dn_fwd_list_it_t position, + dn_fwd_list_it_t first, + dn_fwd_list_it_t last) +{ + dn_fwd_list_result_t result = { { position.it, {position._internal._list } }, true }; + + if (first.it == last.it) + return result; + + for (; first.it && first.it != last.it; first.it = first.it->next) + result = dn_fwd_list_insert_after (position, first.it->data); + + if (last.it) + result = dn_fwd_list_insert_after (position, last.it->data); + + return result; +} + +dn_fwd_list_it_t +dn_fwd_list_custom_erase_after ( + dn_fwd_list_it_t position, + dn_fwd_list_dispose_func_t dispose_func) +{ + dn_fwd_list_t *list = position._internal._list; + + DN_ASSERT (list && !dn_fwd_list_it_end (position)); + + if (position.it == &_fwd_list_before_begin_it_node) { + if (dispose_func) + dispose_func (*dn_fwd_list_front (list)); + dn_fwd_list_pop_front (list); + position.it = list->head; + } else if (position.it->next) { + dn_fwd_list_node_t *to_erase = position.it->next; + position.it->next = position.it->next->next; + fwd_list_dispose_node (position._internal._list->_internal._allocator, dispose_func, to_erase); + } + + if (!position.it->next) { + list->tail = position.it; + position.it = NULL; + } + + return position; +} + +void +dn_fwd_list_custom_pop_front ( + dn_fwd_list_t *list, + dn_fwd_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list && list->head); + + dn_fwd_list_node_t *next = list->head->next; + fwd_list_dispose_node (list->_internal._allocator, dispose_func, list->head); + + list->head = next; + if (!list->head) + list->tail = NULL; +} + +bool +dn_fwd_list_custom_resize ( + dn_fwd_list_t *list, + uint32_t count, + dn_fwd_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list); + + if (count == 0) { + dn_fwd_list_clear (list); + return false; + } + + dn_fwd_list_node_t *current = list->head; + uint32_t i = 0; + while (current) { + i++; + if (i == count) { + dn_fwd_list_node_t *to_dispose = current->next; + + while (to_dispose) { + dn_fwd_list_node_t *next = to_dispose->next; + fwd_list_dispose_node (list->_internal._allocator, dispose_func, to_dispose); + to_dispose = next; + } + + current->next = NULL; + list->tail = current; + break; + } + current = current->next; + } + + while (i++ < count) + dn_fwd_list_insert_after (dn_fwd_list_end (list), NULL); + + return true; +} + +void +dn_fwd_list_custom_remove ( + dn_fwd_list_t *list, + const void *data, + dn_fwd_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list); + fwd_list_remove_node (list, data, NULL, dispose_func); +} + +void +dn_fwd_list_custom_remove_if ( + dn_fwd_list_t *list, + const void *data, + dn_fwd_list_equal_func_t equal_func, + dn_fwd_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list && equal_func); + fwd_list_remove_node (list, data, equal_func, dispose_func); +} + +void +dn_fwd_list_reverse (dn_fwd_list_t *list) +{ + DN_ASSERT (list); + + dn_fwd_list_node_t *node = list->head; + dn_fwd_list_node_t *next; + dn_fwd_list_node_t *prev = NULL; + + list->tail = list->head; + + while (node) { + next = node->next; + node->next = prev; + + prev = node; + node = next; + } + + list->head = prev; +} + +void +dn_fwd_list_for_each ( + dn_fwd_list_t *list, + dn_fwd_list_for_each_func_t for_each_func, + void *user_data) +{ + DN_ASSERT (list && for_each_func); + + for (dn_fwd_list_node_t *it = list->head; it; it = it->next) + for_each_func (it->data, user_data); +} + +typedef dn_fwd_list_node_t list_node; +typedef dn_fwd_list_compare_func_t compare_func_t; +#include "dn-sort-frag.inc" + +void +dn_fwd_list_sort ( + dn_fwd_list_t *list, + dn_fwd_list_compare_func_t compare_func) +{ + DN_ASSERT (list && compare_func); + + if (DN_UNLIKELY (!list->head || !list->head->next)) + return; + + list->head = do_sort (list->head, compare_func); + + dn_fwd_list_node_t *current = list->head; + while (current->next) + current = current->next; + + list->tail = current; +} + +dn_fwd_list_it_t +dn_fwd_list_custom_find ( + dn_fwd_list_t *list, + const void *data, + dn_fwd_list_equal_func_t equal_func) +{ + DN_ASSERT (list); + + dn_fwd_list_it_t found = { NULL, { list } }; + for (dn_fwd_list_node_t *it = list->head; it; it = it->next) { + if ((equal_func && equal_func (it->data, data)) || (!equal_func && it->data == data)) { + found.it = it; + break; + } + } + + return found; +} diff --git a/src/native/containers/dn-fwd-list.h b/src/native/containers/dn-fwd-list.h new file mode 100644 index 0000000..c5c809d --- /dev/null +++ b/src/native/containers/dn-fwd-list.h @@ -0,0 +1,324 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_FWD_LIST_H__ +#define __DN_FWD_LIST_H__ + +#include "dn-utils.h" +#include "dn-allocator.h" + +typedef int32_t (DN_CALLBACK_CALLTYPE *dn_fwd_list_compare_func_t) (const void *a, const void *b); +typedef bool (DN_CALLBACK_CALLTYPE *dn_fwd_list_equal_func_t) (const void *a, const void *b); +typedef void (DN_CALLBACK_CALLTYPE *dn_fwd_list_for_each_func_t) (void *data, void *user_data); +typedef void (DN_CALLBACK_CALLTYPE *dn_fwd_list_dispose_func_t) (void *data); + +typedef struct _dn_fwd_list_node_t dn_fwd_list_node_t; +struct _dn_fwd_list_node_t { + void *data; + dn_fwd_list_node_t *next; +}; + +typedef struct _dn_fwd_list_t dn_fwd_list_t; +struct _dn_fwd_list_t { + dn_fwd_list_node_t *head; + dn_fwd_list_node_t *tail; + struct { + dn_allocator_t *_allocator; + } _internal; +}; + +typedef struct _dn_fwd_list_it_t dn_fwd_list_it_t; +struct _dn_fwd_list_it_t { + dn_fwd_list_node_t *it; + struct { + dn_fwd_list_t *_list; + } _internal; +}; + +typedef struct _dn_fwd_list_result_t dn_fwd_list_result_t; +struct _dn_fwd_list_result_t { + dn_fwd_list_it_t it; + bool result; +}; + +static inline dn_fwd_list_it_t +dn_fwd_list_begin (dn_fwd_list_t *list) +{ + DN_ASSERT (list); + dn_fwd_list_it_t it = { list->head, { list } }; + return it; +} + +static inline dn_fwd_list_it_t +dn_fwd_list_end (dn_fwd_list_t *list) +{ + DN_ASSERT (list); + dn_fwd_list_it_t it = { NULL, { list } }; + return it; +} + +static inline void +dn_fwd_list_it_advance ( + dn_fwd_list_it_t *it, + uint32_t n) +{ + DN_ASSERT (it); + + while (n > 0 && it->it) { + it->it = it->it->next; + n--; + } +} + +static inline dn_fwd_list_it_t +dn_fwd_list_it_next (dn_fwd_list_it_t it) +{ + DN_ASSERT (it.it); + it.it = it.it->next; + return it; +} + +static inline dn_fwd_list_it_t +dn_fwd_list_it_next_n ( + dn_fwd_list_it_t it, + uint32_t n) +{ + dn_fwd_list_it_advance (&it, n); + return it; +} + +static inline void ** +dn_fwd_list_it_data (dn_fwd_list_it_t it) +{ + DN_ASSERT (it.it); + return &(it.it->data); +} + +#define dn_fwd_list_it_data_t(it, type) \ + (type *)dn_fwd_list_it_data ((it)) + +static inline bool +dn_fwd_list_it_begin (dn_fwd_list_it_t it) +{ + DN_ASSERT (it._internal._list); + return !(it.it == it._internal._list->head); +} + +static inline bool +dn_fwd_list_it_end (dn_fwd_list_it_t it) +{ + return !(it.it); +} + +#define DN_FWD_LIST_FOREACH_BEGIN(var_type, var_name, list) do { \ + var_type var_name; \ + for (dn_fwd_list_node_t *__it##var_name = (list)->head; __it##var_name; __it##var_name = __it##var_name->next) { \ + var_name = (var_type)__it##var_name->data; + +#define DN_FWD_LIST_FOREACH_END \ + } \ + } while (0) + +dn_fwd_list_t * +dn_fwd_list_custom_alloc (dn_allocator_t *allocator); + +static inline dn_fwd_list_t * +dn_fwd_list_alloc (void) +{ + return dn_fwd_list_custom_alloc (DN_DEFAULT_ALLOCATOR); +} + +void +dn_fwd_list_custom_free ( + dn_fwd_list_t *list, + dn_fwd_list_dispose_func_t dispose_func); + +static inline void +dn_fwd_list_free (dn_fwd_list_t *list) +{ + dn_fwd_list_custom_free (list, NULL); +} + +bool +dn_fwd_list_custom_init ( + dn_fwd_list_t *list, + dn_allocator_t *allocator); + +static inline bool +dn_fwd_list_init (dn_fwd_list_t *list) +{ + return dn_fwd_list_custom_init (list, DN_DEFAULT_ALLOCATOR); +} + +void +dn_fwd_list_custom_dispose ( + dn_fwd_list_t *list, + dn_fwd_list_dispose_func_t dispose_func); + +static inline void +dn_fwd_list_dispose (dn_fwd_list_t *list) +{ + dn_fwd_list_custom_dispose (list, NULL); +} + +static inline void ** +dn_fwd_list_front (const dn_fwd_list_t *list) +{ + DN_ASSERT (list && list->head); + return &(list->head->data); +} + +#define dn_fwd_list_front_t(list, type) \ + (type *)dn_fwd_list_front ((list)) + +static inline dn_fwd_list_it_t +dn_fwd_list_before_begin (dn_fwd_list_t *list) +{ + DN_ASSERT (list); + + extern dn_fwd_list_node_t _fwd_list_before_begin_it_node; + dn_fwd_list_it_t it = { &_fwd_list_before_begin_it_node, { list } }; + + return it; +} + +static inline bool +dn_fwd_list_empty (const dn_fwd_list_t *list) +{ + DN_ASSERT (list); + return !list->head; +} + +static inline uint32_t +dn_fwd_list_max_size (const dn_fwd_list_t *list) +{ + DN_UNREFERENCED_PARAMETER (list); + return UINT32_MAX; +} + +void +dn_fwd_list_custom_clear ( + dn_fwd_list_t *list, + dn_fwd_list_dispose_func_t dispose_func); + +static inline void +dn_fwd_list_clear (dn_fwd_list_t *list) +{ + dn_fwd_list_custom_clear (list, NULL); +} + +dn_fwd_list_result_t +dn_fwd_list_insert_after ( + dn_fwd_list_it_t position, + void *data); + +dn_fwd_list_result_t +dn_fwd_list_insert_range_after ( + dn_fwd_list_it_t position, + dn_fwd_list_it_t first, + dn_fwd_list_it_t last); + +dn_fwd_list_it_t +dn_fwd_list_custom_erase_after ( + dn_fwd_list_it_t position, + dn_fwd_list_dispose_func_t dispose_func); + +static inline dn_fwd_list_it_t +dn_fwd_list_erase_after (dn_fwd_list_it_t position) +{ + return dn_fwd_list_custom_erase_after (position, NULL); +} + +static inline bool +dn_fwd_list_push_front ( + dn_fwd_list_t *list, + void *data) +{ + DN_ASSERT (list); + return dn_fwd_list_insert_after (dn_fwd_list_before_begin (list), data).result; +} + +void +dn_fwd_list_custom_pop_front ( + dn_fwd_list_t *list, + dn_fwd_list_dispose_func_t dispose_func); + +static inline void +dn_fwd_list_pop_front (dn_fwd_list_t *list) +{ + dn_fwd_list_custom_pop_front (list, NULL); +} + +bool +dn_fwd_list_custom_resize ( + dn_fwd_list_t *list, + uint32_t count, + dn_fwd_list_dispose_func_t dispose_func); + +static inline bool +dn_fwd_list_resize ( + dn_fwd_list_t *list, + uint32_t count) +{ + return dn_fwd_list_custom_resize (list, count, NULL); +} + +void +dn_fwd_list_custom_remove ( + dn_fwd_list_t *list, + const void *data, + dn_fwd_list_dispose_func_t disopse_func); + +static inline void +dn_fwd_list_remove ( + dn_fwd_list_t *list, + const void *data) +{ + dn_fwd_list_custom_remove (list, data, NULL); +} + +void +dn_fwd_list_custom_remove_if ( + dn_fwd_list_t *list, + const void *data, + dn_fwd_list_equal_func_t equal_func, + dn_fwd_list_dispose_func_t dispose_func); + +static inline void +dn_fwd_list_remove_if ( + dn_fwd_list_t *list, + const void *data, + dn_fwd_list_equal_func_t equal_func) +{ + dn_fwd_list_custom_remove_if (list, data, equal_func, NULL); +} + +void +dn_fwd_list_reverse (dn_fwd_list_t *list); + +void +dn_fwd_list_for_each ( + dn_fwd_list_t *list, + dn_fwd_list_for_each_func_t for_each_func, + void *user_data); + +void +dn_fwd_list_sort ( + dn_fwd_list_t *list, + dn_fwd_list_compare_func_t compare_func); + +dn_fwd_list_it_t +dn_fwd_list_custom_find ( + dn_fwd_list_t *list, + const void *data, + dn_fwd_list_equal_func_t equal_func); + +static inline dn_fwd_list_it_t +dn_fwd_list_find ( + dn_fwd_list_t *list, + const void *data) +{ + return dn_fwd_list_custom_find (list, data, NULL); +} + +#endif /* __DN_FWD_LIST_H__ */ diff --git a/src/native/containers/dn-list.c b/src/native/containers/dn-list.c new file mode 100644 index 0000000..b7ee924 --- /dev/null +++ b/src/native/containers/dn-list.c @@ -0,0 +1,447 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/* (C) 2006 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "dn-list.h" + +static dn_list_node_t * +list_new_node ( + dn_allocator_t *allocator, + dn_list_node_t *prev, + dn_list_node_t *next, + void *data) +{ + dn_list_node_t *node = (dn_list_node_t *)dn_allocator_alloc (allocator, sizeof (dn_list_node_t)); + if (DN_UNLIKELY (!node)) + return NULL; + + node->data = data; + node->prev = prev; + node->next = next; + + if (prev) + prev->next = node; + if (next) + next->prev = node; + + return node; +} + +static dn_list_node_t* +list_unlink_node (dn_list_node_t *node) +{ + if (node->next) + node->next->prev = node->prev; + if (node->prev) + node->prev->next = node->next; + + return node; +} + + +static dn_list_node_t * +list_insert_node_before ( + dn_allocator_t *allocator, + dn_list_node_t *node, + void *data) +{ + return list_new_node (allocator, node ? node->prev : NULL, node, data); +} + +static dn_list_node_t * +list_insert_node_after ( + dn_allocator_t *allocator, + dn_list_node_t *node, + void *data) +{ + return list_new_node (allocator, node, node ? node->next : NULL, data); +} + +static void +list_free_node ( + dn_allocator_t *allocator, + dn_list_node_t *node) +{ + dn_allocator_free (allocator, node); +} + +static void +list_dispose_node ( + dn_allocator_t *allocator, + dn_list_dispose_func_t dispose_func, + dn_list_node_t *node) +{ + if (node && dispose_func) + dispose_func (node->data); + list_free_node (allocator, node); +} + +static void +list_remove_node ( + dn_list_t *list, + const void * data, + dn_list_equal_func_t equal_func, + dn_list_dispose_func_t dispose_func) +{ + dn_list_node_t *current = list->head; + dn_list_node_t *next; + + while (current) { + next = current->next; + if ((equal_func && equal_func (current->data, data)) || (!equal_func && current->data == data)) { + if (current == list->head) + list->head = next; + if (current == list->tail) + list->tail = current->prev; + list_dispose_node (list->_internal._allocator, dispose_func, list_unlink_node (current)); + } + current = next; + } +} + +dn_list_t * +dn_list_custom_alloc (dn_allocator_t *allocator) +{ + dn_list_t *list = (dn_list_t *)dn_allocator_alloc (allocator, sizeof (dn_list_t)); + if (!dn_list_custom_init (list, allocator)) { + dn_allocator_free (allocator, list); + return NULL; + } + + return list; +} + +bool +dn_list_custom_init ( + dn_list_t *list, + dn_allocator_t *allocator) +{ + if (DN_UNLIKELY (!list)) + return false; + + memset (list, 0, sizeof(dn_list_t)); + list->_internal._allocator = allocator; + + return true; +} + +void +dn_list_custom_free ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func) +{ + if (list) { + dn_list_custom_dispose (list, dispose_func); + dn_allocator_free (list->_internal._allocator, list); + } +} + +void +dn_list_custom_dispose ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func) +{ + if (DN_UNLIKELY(!list)) + return; + + dn_list_node_t *current = list->head; + while (current) { + dn_list_node_t *next = current->next; + list_dispose_node (list->_internal._allocator, dispose_func, current); + current = next; + } +} + +uint32_t +dn_list_size (const dn_list_t *list) +{ + DN_ASSERT (list); + + uint32_t size = 0; + dn_list_node_t *nodes = list->head; + + while (nodes) { + size ++; + nodes = nodes->next; + } + + return size; +} + +void +dn_list_custom_clear ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list); + + dn_list_custom_dispose (list, dispose_func); + + list->head = NULL; + list->tail = NULL; +} + +dn_list_result_t +dn_list_insert ( + dn_list_it_t position, + void *data) +{ + dn_list_t *list = position._internal._list; + + DN_ASSERT (list); + + if (!list->head) + position.it = list_insert_node_before (list->_internal._allocator, list->head, data); + else if (!position.it) + position.it = list_insert_node_after (list->_internal._allocator, list->tail, data); + else + position.it = list_insert_node_before (list->_internal._allocator, position.it, data); + + if (position.it) { + if (!position.it->prev) + list->head = position.it; + if (!position.it->next) + list->tail = position.it; + } + + dn_list_result_t result = { { position.it, {position._internal._list } }, position.it != NULL }; + return result; +} + +dn_list_result_t +dn_list_insert_range ( + dn_list_it_t position, + dn_list_it_t first, + dn_list_it_t last) +{ + dn_list_result_t first_inserted = { { position.it, {position._internal._list } }, true }; + + if (first.it == last.it) + return first_inserted; + + DN_ASSERT (first.it); + + first_inserted = dn_list_insert (position, first.it->data); + + for (first.it = first.it->next; first.it && first.it != last.it; first.it = first.it->next) + dn_list_insert (position, first.it->data); + + if (last.it) + dn_list_insert (position, last.it->data); + + return first_inserted; +} + +dn_list_it_t +dn_list_custom_erase ( + dn_list_it_t position, + dn_list_dispose_func_t dispose_func) +{ + if (DN_UNLIKELY(!position.it)) + return position; + + dn_list_t *list = position._internal._list; + + DN_ASSERT (list && !dn_list_it_end (position)); + + if (position.it == list->head) { + if (dispose_func) + dispose_func (*dn_list_front (list)); + dn_list_pop_front (list); + position.it = list->head; + } else if (position.it == list->tail) { + if (dispose_func) + dispose_func (*dn_list_back (list)); + dn_list_pop_back (list); + position.it = NULL; + } else if (position.it) { + dn_list_node_t *to_remove = position.it; + position.it = position.it->next; + list_dispose_node (list->_internal._allocator, dispose_func, list_unlink_node (to_remove)); + } + + return position; +} + +void +dn_list_custom_pop_back ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list && list->tail); + + dn_list_node_t *prev = list->tail->prev; + list_dispose_node (list->_internal._allocator, dispose_func, list_unlink_node (list->tail)); + + list->tail = prev; + if (!list->tail) + list->head = NULL; +} + +void +dn_list_custom_pop_front ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list && list->head); + + dn_list_node_t *next = list->head->next; + list_dispose_node (list->_internal._allocator, dispose_func, list_unlink_node (list->head)); + + list->head = next; + if (!list->head) + list->tail = NULL; +} + +bool +dn_list_custom_resize ( + dn_list_t *list, + uint32_t count, + dn_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list); + + if (count == 0) { + dn_list_custom_clear (list, dispose_func); + return true; + } + + dn_list_node_t *current = list->head; + uint32_t i = 0; + while (current) { + i++; + if (i == count) { + dn_list_node_t *to_dispose = current->next; + while (to_dispose) { + dn_list_node_t *next = to_dispose->next; + list_dispose_node (list->_internal._allocator, dispose_func, list_unlink_node (to_dispose)); + to_dispose = next; + } + list->tail = current; + break; + } + current = current->next; + } + + while (i++ < count) + dn_list_insert (dn_list_end (list), NULL); + + return true; +} + +void +dn_list_custom_remove ( + dn_list_t *list, + const void *data, + dn_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list); + list_remove_node (list, data, NULL, dispose_func); +} + +void +dn_list_custom_remove_if ( + dn_list_t *list, + const void * data, + dn_list_equal_func_t equal_func, + dn_list_dispose_func_t dispose_func) +{ + DN_ASSERT (list && equal_func); + list_remove_node (list, data, equal_func, dispose_func); +} + +void +dn_list_reverse (dn_list_t *list) +{ + DN_ASSERT (list); + + dn_list_node_t *node = list->head; + dn_list_node_t *reverse; + + list->head = list->tail; + list->tail = node; + + while (node) { + reverse = node; + node = reverse->next; + + reverse->next = reverse->prev; + reverse->prev = node; + } +} + +void +dn_list_for_each ( + dn_list_t *list, + dn_list_for_each_func_t for_each_func, + void *user_data) +{ + DN_ASSERT (list && for_each_func); + + for (dn_list_node_t *it = list->head; it; it = it->next) + for_each_func (it->data, user_data); +} + +typedef dn_list_node_t list_node; +typedef dn_list_compare_func_t compare_func_t; +#include "dn-sort-frag.inc" + +void +dn_list_sort ( + dn_list_t *list, + dn_list_compare_func_t compare_func) +{ + DN_ASSERT (list && compare_func); + + if (DN_UNLIKELY (!list->head || !list->head->next)) + return; + + list->head = do_sort (list->head, compare_func); + list->head->prev = NULL; + + dn_list_node_t *current; + for (current = list->head; current->next; current = current->next) + current->next->prev = current; + + list->tail = current; +} + +dn_list_it_t +dn_list_custom_find ( + dn_list_t *list, + const void *data, + dn_list_equal_func_t equal_func) +{ + DN_ASSERT (list); + + dn_list_it_t found = { NULL, { list } }; + for (dn_list_node_t *it = list->head; it; it = it->next) { + if ((equal_func && equal_func (it->data, data)) || (!equal_func && it->data == data)) { + found.it = it; + break; + } + } + + return found; +} diff --git a/src/native/containers/dn-list.h b/src/native/containers/dn-list.h new file mode 100644 index 0000000..1b16c15 --- /dev/null +++ b/src/native/containers/dn-list.h @@ -0,0 +1,374 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_LIST_H__ +#define __DN_LIST_H__ + +#include "dn-utils.h" +#include "dn-allocator.h" + +typedef int32_t (DN_CALLBACK_CALLTYPE *dn_list_compare_func_t) (const void *a, const void *b); +typedef bool (DN_CALLBACK_CALLTYPE *dn_list_equal_func_t) (const void *a, const void *b); +typedef void (DN_CALLBACK_CALLTYPE *dn_list_for_each_func_t) (void *data, void *user_data); +typedef void (DN_CALLBACK_CALLTYPE *dn_list_dispose_func_t) (void *data); + +typedef struct _dn_list_node_t dn_list_node_t; +struct _dn_list_node_t { + void *data; + dn_list_node_t *next; + dn_list_node_t *prev; +}; + +typedef struct _dn_list_t dn_list_t; +struct _dn_list_t { + dn_list_node_t *head; + dn_list_node_t *tail; + struct { + dn_allocator_t *_allocator; + } _internal; +}; + +typedef struct _dn_list_it_t dn_list_it_t; +struct _dn_list_it_t { + dn_list_node_t *it; + struct { + dn_list_t *_list; + } _internal; +}; + +typedef struct _dn_list_result_t dn_list_result_t; +struct _dn_list_result_t { + dn_list_it_t it; + bool result; +}; + +static inline dn_list_it_t +dn_list_begin (dn_list_t *list) +{ + DN_ASSERT (list); + dn_list_it_t it = { list->head, { list } }; + return it; +} + +static inline dn_list_it_t +dn_list_end (dn_list_t *list) +{ + DN_ASSERT (list); + dn_list_it_t it = { NULL, { list } }; + return it; +} + +static inline void +dn_list_it_advance ( + dn_list_it_t *it, + ptrdiff_t n) +{ + DN_ASSERT (it); + + while (n > 0 && it->it) { + it->it = it->it->next; + n--; + } + + while (n < 0 && it->it) { + it->it = it->it->prev; + n++; + } +} + +static inline dn_list_it_t +dn_list_it_next (dn_list_it_t it) +{ + DN_ASSERT (it.it); + it.it = it.it->next; + return it; +} + +static inline dn_list_it_t +dn_list_it_prev (dn_list_it_t it) +{ + DN_ASSERT (it.it); + it.it = it.it->prev; + return it; +} + +static inline dn_list_it_t +dn_list_it_next_n ( + dn_list_it_t it, + uint32_t n) +{ + dn_list_it_advance (&it, n); + return it; +} + +static inline dn_list_it_t +dn_list_it_prev_n ( + dn_list_it_t it, + uint32_t n) +{ + dn_list_it_advance (&it, -(ptrdiff_t)n); + return it; +} + +static inline void ** +dn_list_it_data (dn_list_it_t it) +{ + DN_ASSERT (it.it); + return &(it.it->data); +} + +#define dn_list_it_data_t(it, type) \ + (type *)dn_list_it_data ((it)) + +static inline bool +dn_list_it_begin (dn_list_it_t it) +{ + DN_ASSERT (it._internal._list); + return !(it.it == it._internal._list->head); +} + +static inline bool +dn_list_it_end (dn_list_it_t it) +{ + return !(it.it); +} + +#define DN_LIST_FOREACH_BEGIN(var_type, var_name, list) do { \ + var_type var_name; \ + for (dn_list_node_t *__it##var_name = (list)->head; __it##var_name; __it##var_name = __it##var_name->next) { \ + var_name = (var_type)__it##var_name->data; + +#define DN_LIST_FOREACH_RBEGIN(var_type, var_name, list) do { \ + var_type var_name; \ + for (dn_list_node_t *__it##var_name = (list)->tail; __it##var_name; __it##var_name = __it##var_name->prev) { \ + var_name = (var_type)__it##var_name->data; + +#define DN_LIST_FOREACH_END \ + } \ + } while (0) + +dn_list_t * +dn_list_custom_alloc (dn_allocator_t *allocator); + +static inline dn_list_t * +dn_list_alloc (void) +{ + return dn_list_custom_alloc (DN_DEFAULT_ALLOCATOR); +} + +void +dn_list_custom_free ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func); + +static inline void +dn_list_free (dn_list_t *list) +{ + dn_list_custom_free (list, NULL); +} + +bool +dn_list_custom_init ( + dn_list_t *list, + dn_allocator_t *allocator); + +static inline bool +dn_list_init (dn_list_t *list) +{ + return dn_list_custom_init (list, DN_DEFAULT_ALLOCATOR); +} + +void +dn_list_custom_dispose ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func); + +static inline void +dn_list_dispose (dn_list_t *list) +{ + dn_list_custom_dispose (list, NULL); +} + +static inline void ** +dn_list_front (const dn_list_t *list) +{ + DN_ASSERT (list && list->head); + return &(list->head->data); +} + +#define dn_list_front_t(list, type) \ + (type *)dn_list_front ((list)) + +static inline void ** +dn_list_back (const dn_list_t *list) +{ + DN_ASSERT (list && list->tail); + return &(list->tail->data); +} + +#define dn_list_back_t(list, type) \ + (type *)dn_list_back ((list)) + +static inline bool +dn_list_empty (const dn_list_t *list) +{ + DN_ASSERT (list); + return !list->head; +} + +uint32_t +dn_list_size (const dn_list_t *list); + +static inline uint32_t +dn_list_max_size (const dn_list_t *list) +{ + DN_UNREFERENCED_PARAMETER (list); + return UINT32_MAX; +} + +void +dn_list_custom_clear ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func); + +static inline void +dn_list_clear (dn_list_t *list) +{ + dn_list_custom_clear (list, NULL); +} + +dn_list_result_t +dn_list_insert ( + dn_list_it_t position, + void *data); + +dn_list_result_t +dn_list_insert_range ( + dn_list_it_t position, + dn_list_it_t first, + dn_list_it_t list); + +dn_list_it_t +dn_list_custom_erase ( + dn_list_it_t position, + dn_list_dispose_func_t dispose_func); + +static inline dn_list_it_t +dn_list_erase (dn_list_it_t position) +{ + return dn_list_custom_erase (position, NULL); +} + +static inline bool +dn_list_push_back ( + dn_list_t *list, + void *data) +{ + DN_ASSERT (list); + return dn_list_insert (dn_list_end (list), data).result; +} + +void +dn_list_custom_pop_back ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func); + +static inline void +dn_list_pop_back (dn_list_t *list) +{ + dn_list_custom_pop_back (list, NULL); +} + +static inline bool +dn_list_push_front ( + dn_list_t *list, + void *data) +{ + DN_ASSERT (list); + return dn_list_insert (dn_list_begin (list), data).result; +} + +void +dn_list_custom_pop_front ( + dn_list_t *list, + dn_list_dispose_func_t dispose_func); + +static inline void +dn_list_pop_front (dn_list_t *list) +{ + dn_list_custom_pop_front (list, NULL); +} + +bool +dn_list_custom_resize ( + dn_list_t *list, + uint32_t count, + dn_list_dispose_func_t dispose_func); + +static inline bool +dn_list_resize ( + dn_list_t *list, + uint32_t count) +{ + return dn_list_custom_resize (list, count, NULL); +} + +void +dn_list_custom_remove ( + dn_list_t *list, + const void *data, + dn_list_dispose_func_t dispose_func); + +static inline void +dn_list_remove ( + dn_list_t *list, + const void *data) +{ + dn_list_custom_remove (list, data, NULL); +} + +void +dn_list_custom_remove_if ( + dn_list_t *list, + const void *data, + dn_list_equal_func_t equal_func, + dn_list_dispose_func_t dispose_func); + +static inline void +dn_list_remove_if ( + dn_list_t *list, + const void *data, + dn_list_equal_func_t equal_func) +{ + dn_list_custom_remove_if (list, data, equal_func, NULL); +} + +void +dn_list_reverse (dn_list_t *list); + +void +dn_list_for_each ( + dn_list_t *list, + dn_list_for_each_func_t for_each_func, + void *user_data); + +void +dn_list_sort ( + dn_list_t *list, + dn_list_compare_func_t compare_func); + +dn_list_it_t +dn_list_custom_find ( + dn_list_t *list, + const void *data, + dn_list_equal_func_t equal_func); + +static inline dn_list_it_t +dn_list_find ( + dn_list_t *list, + const void *data) +{ + return dn_list_custom_find (list, data, NULL); +} + +#endif /* __DN_LIST_H__ */ diff --git a/src/native/containers/dn-queue.c b/src/native/containers/dn-queue.c new file mode 100644 index 0000000..713e2c1 --- /dev/null +++ b/src/native/containers/dn-queue.c @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/* Copyright (c) 2006-2009 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "dn-queue.h" + +dn_queue_t * +dn_queue_custom_alloc (dn_allocator_t *allocator) +{ + dn_queue_t *queue = (dn_queue_t *)dn_allocator_alloc (allocator, sizeof (dn_queue_t)); + if (!dn_queue_custom_init (queue, allocator)) { + dn_allocator_free (allocator, queue); + return NULL; + } + + return queue; +} + +bool +dn_queue_custom_init ( + dn_queue_t *queue, + dn_allocator_t *allocator) +{ + if (DN_UNLIKELY (!queue)) + return false; + + memset (queue, 0, sizeof(dn_queue_t)); + dn_list_custom_init (&queue->_internal.list, allocator); + + return true; +} + +void +dn_queue_custom_free ( + dn_queue_t *queue, + dn_queue_dispose_func_t dispose_func) +{ + if (DN_UNLIKELY (!queue)) + return; + + dn_allocator_t *allocator = queue->_internal.list._internal._allocator; + dn_list_custom_dispose (&queue->_internal.list, dispose_func); + dn_allocator_free (allocator, queue); +} + +void +dn_queue_custom_dispose ( + dn_queue_t *queue, + dn_queue_dispose_func_t dispose_func) +{ + if (DN_UNLIKELY(!queue)) + return; + + dn_list_custom_dispose (&queue->_internal.list, dispose_func); +} diff --git a/src/native/containers/dn-queue.h b/src/native/containers/dn-queue.h new file mode 100644 index 0000000..93e886b --- /dev/null +++ b/src/native/containers/dn-queue.h @@ -0,0 +1,147 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_QUEUE_H__ +#define __DN_QUEUE_H__ + +#include "dn-utils.h" +#include "dn-allocator.h" +#include "dn-list.h" + +typedef void (DN_CALLBACK_CALLTYPE *dn_queue_dispose_func_t) (void *data); + +typedef struct _dn_queue_t dn_queue_t; +struct _dn_queue_t { + struct { + dn_list_t list; + } _internal; + uint32_t size; +}; + +dn_queue_t * +dn_queue_custom_alloc (dn_allocator_t *allocator); + +static inline dn_queue_t * +dn_queue_alloc (void) +{ + return dn_queue_custom_alloc (DN_DEFAULT_ALLOCATOR); +} + +void +dn_queue_custom_free ( + dn_queue_t *queue, + dn_queue_dispose_func_t dispose_func); + +static inline void +dn_queue_free (dn_queue_t *queue) +{ + dn_queue_custom_free (queue, NULL); +} + +bool +dn_queue_custom_init ( + dn_queue_t *queue, + dn_allocator_t *allocator); + +static inline bool +dn_queue_init (dn_queue_t *queue) +{ + return dn_queue_custom_init (queue, DN_DEFAULT_ALLOCATOR); +} + +void +dn_queue_custom_dispose ( + dn_queue_t *queue, + dn_queue_dispose_func_t dispose_func); + +static inline void +dn_queue_dispose (dn_queue_t *queue) +{ + dn_queue_custom_dispose (queue, NULL); +} + +static inline void ** +dn_queue_front (dn_queue_t *queue) +{ + DN_ASSERT (queue && queue->size != 0); + return dn_list_front (&queue->_internal.list); +} + +#define dn_queue_front_t(queue, type) \ + (type *)dn_queue_front ((queue)) + +static inline void ** +dn_queue_back (dn_queue_t *queue) +{ + DN_ASSERT (queue && queue->size != 0); + return dn_list_back (&queue->_internal.list); +} + +#define dn_queue_back_t(queue, type) \ + (type *)dn_queue_back ((queue)) + +static inline bool +dn_queue_empty (dn_queue_t *queue) +{ + DN_ASSERT (queue); + return queue->size == 0; +} + +static inline uint32_t +dn_queue_size (dn_queue_t *queue) +{ + DN_ASSERT (queue); + return queue->size; +} + +static inline bool +dn_queue_push ( + dn_queue_t *queue, + void *data) +{ + DN_ASSERT (queue); + + bool result = dn_list_push_back (&queue->_internal.list, data); + if (result) + queue->size ++; + + return result; +} + +#define dn_queue_push_t(queue, type, data) \ + dn_queue_push ((queue),((void *)(ptrdiff_t)(data))) + +static inline void +dn_queue_custom_pop ( + dn_queue_t *queue, + dn_queue_dispose_func_t dispose_func) +{ + DN_ASSERT (queue); + dn_list_custom_pop_front (&queue->_internal.list, dispose_func); + queue->size --; +} +static inline void +dn_queue_pop (dn_queue_t *queue) +{ + DN_ASSERT (queue); + dn_list_pop_front (&queue->_internal.list); + queue->size --; +} + +static inline void +dn_queue_custom_clear ( + dn_queue_t *queue, + dn_queue_dispose_func_t dispose_func) +{ + DN_ASSERT (queue); + dn_list_custom_clear (&queue->_internal.list, dispose_func); + queue->size = 0; +} + +static inline void +dn_queue_clear (dn_queue_t *queue) +{ + dn_queue_custom_clear (queue, NULL); +} + +#endif /* __DN_QUEUE_H__ */ diff --git a/src/native/containers/dn-sort-frag.inc b/src/native/containers/dn-sort-frag.inc new file mode 100644 index 0000000..f192e07 --- /dev/null +++ b/src/native/containers/dn-sort-frag.inc @@ -0,0 +1,201 @@ +/* (C) 2006 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * This code requires a typedef named 'list_node' for the list node. It + * is assumed that the list type is the type of a pointer to a list + * node, and that the node has a field named 'next' that implements to + * the linked list. No additional invariant is maintained (e.g. the + * 'prev' pointer of a doubly-linked list node is _not_ updated). Any + * invariant would require a post-processing pass to fix matters if + * necessary. + */ +typedef list_node *digit; + +/* + * The maximum possible depth of the merge tree + * = ceiling (log2 (maximum number of list nodes)) + * = ceiling (log2 (maximum possible memory size/size of each list node)) + * = number of bits in 'size_t' - floor (log2 (sizeof digit)) + * Also, each list in sort_info is at least 2 nodes long: we can reduce the depth by 1 + */ +#define FLOOR_LOG2(x) (((x)>=2) + ((x)>=4) + ((x)>=8) + ((x)>=16) + ((x)>=32) + ((x)>=64) + ((x)>=128)) +#define MAX_RANKS ((sizeof (size_t) * 8) - FLOOR_LOG2(sizeof (list_node)) - 1) + +struct sort_info +{ + int32_t min_rank, n_ranks; + compare_func_t func; + + /* Invariant: ranks[i] == NULL || length(ranks[i]) >= 2**(i+1) */ + list_node *ranks [MAX_RANKS]; /* ~ 128 bytes on 32bit, ~ 512 bytes on 64bit */ +}; + +static inline void +init_sort_info (struct sort_info *si, compare_func_t func) +{ + si->min_rank = si->n_ranks = 0; + si->func = func; + /* we don't need to initialize si->ranks, since we never lookup past si->n_ranks. */ +} + +static inline list_node * +merge_lists (list_node *first, list_node *second, compare_func_t func) +{ + /* merge the two lists */ + list_node *list = NULL; + list_node **pos = &list; + while (first && second) { + if (func (first->data, second->data) > 0) { + *pos = second; + second = second->next; + } else { + *pos = first; + first = first->next; + } + pos = &((*pos)->next); + } + *pos = first ? first : second; + return list; +} + +/* Pre-condition: upto <= si->n_ranks, list == NULL || length(list) == 1 */ +static inline list_node * +sweep_up (struct sort_info *si, list_node *list, int32_t upto) +{ +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) + /* + * GCC incorrectly thinks we're writing below si->ranks array bounds. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif + + int32_t i; + for (i = si->min_rank; i < upto; ++i) { + list = merge_lists (si->ranks [i], list, si->func); + si->ranks [i] = NULL; + } + return list; + +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) +#pragma GCC diagnostic pop +#endif +} + +/* + * The 'ranks' array essentially captures the recursion stack of a mergesort. + * The merge tree is built in a bottom-up manner. The control loop for + * updating the 'ranks' array is analogous to incrementing a binary integer, + * and the O(n) time for counting upto n translates to O(n) merges when + * inserting rank-0 lists. When we plug in the sizes of the lists involved in + * those merges, we get the O(n log n) time for the sort. + * + * Inserting higher-ranked lists reduce the height of the merge tree, and also + * eliminate a lot of redundant comparisons when merging two lists that would've + * been part of the same run. Adding a rank-i list is analogous to incrementing + * a binary integer by 2**i in one operation, thus sharing a similar speedup. + * + * When inserting higher-ranked lists, we choose to clear out the lower ranks + * in the interests of keeping the sort stable, but this makes analysis harder. + * Note that clearing the lower-ranked lists is O(length(list))-- thus it + * shouldn't affect the O(n log n) behaviour. IOW, inserting one rank-i list + * is equivalent to inserting 2**i rank-0 lists, thus even if we do i additional + * merges in the clearing-out (taking at most 2**i time) we are still fine. + */ + +#define stringify2(x) #x +#define stringify(x) stringify2(x) + +/* Pre-condition: 2**(rank+1) <= length(list) < 2**(rank+2) (therefore: length(list) >= 2) */ +static inline void +insert_list (struct sort_info *si, list_node* list, int32_t rank) +{ +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) + /* + * GCC incorrectly thinks we're writing below si->ranks array bounds. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif + + int32_t i; + + if (rank > si->n_ranks) { + if (rank > (int32_t)MAX_RANKS) { + rank = (int32_t)MAX_RANKS; + } + list = merge_lists (sweep_up (si, NULL, si->n_ranks), list, si->func); + for (i = si->n_ranks; i < rank; ++i) + si->ranks [i] = NULL; + } else { + if (rank) + list = merge_lists (sweep_up (si, NULL, rank), list, si->func); + for (i = rank; i < si->n_ranks && si->ranks [i]; ++i) { + list = merge_lists (si->ranks [i], list, si->func); + si->ranks [i] = NULL; + } + } + + if (i == (int32_t)MAX_RANKS) /* Will _never_ happen: so we can just devolve into quadratic ;-) */ + --i; + if (i >= si->n_ranks) + si->n_ranks = i + 1; + si->min_rank = i; + si->ranks [i] = list; + +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) +#pragma GCC diagnostic pop +#endif +} + +#undef stringify2 +#undef stringify +#undef MAX_RANKS +#undef FLOOR_LOG2 + +/* A non-recursive mergesort */ +static inline digit +do_sort (list_node* list, compare_func_t func) +{ + struct sort_info si; + + init_sort_info (&si, func); + + while (list && list->next) { + list_node* next = list->next; + list_node* tail = next->next; + + if (func (list->data, next->data) > 0) { + next->next = list; + next = list; + list = list->next; + } + next->next = NULL; + + insert_list (&si, list, 0); + + list = tail; + } + + return sweep_up (&si, list, si.n_ranks); +} diff --git a/src/native/containers/dn-umap-t.h b/src/native/containers/dn-umap-t.h new file mode 100644 index 0000000..9c22938 --- /dev/null +++ b/src/native/containers/dn-umap-t.h @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_UMAP_T_H__ +#define __DN_UMAP_T_H__ + +#include "dn-umap.h" + +#define DN_UMAP_IT_KEY_T(key_type_name, key_type) \ +_DN_STATIC_ASSERT(sizeof(key_type) <= sizeof(uintptr_t)); \ +static inline key_type \ +dn_umap_it_key_ ## key_type_name (dn_umap_it_t it) \ +{ \ + return (key_type)(uintptr_t)(it._internal._node->key); \ +} + +#define DN_UMAP_IT_VALUE_T(value_type_name, value_type) \ +_DN_STATIC_ASSERT(sizeof(value_type) <= sizeof(uintptr_t)); \ +static inline value_type \ +dn_umap_it_value_ ## value_type_name (dn_umap_it_t it) \ +{ \ + return (value_type)(uintptr_t)(it._internal._node->value); \ +} + +#define DN_UMAP_T(key_type_name, key_type, value_type_name, value_type) \ +_DN_STATIC_ASSERT(sizeof(key_type) <= sizeof(uintptr_t) && sizeof(value_type) <= sizeof(uintptr_t)); \ +static inline dn_umap_result_t \ +dn_umap_ ## key_type_name ## _ ## value_type_name ## _insert (dn_umap_t *map, key_type key, value_type value) \ +{ \ + return dn_umap_insert (map, ((void *)(uintptr_t)key), ((void *)(uintptr_t)value)); \ +} \ +static inline dn_umap_result_t \ +dn_umap_ ## key_type_name ## _ ## value_type_name ## _insert_or_assign (dn_umap_t *map, key_type key, value_type value) \ +{ \ + return dn_umap_insert_or_assign (map, ((void *)(uintptr_t)key), ((void *)(uintptr_t)value)); \ +} \ +static inline uint32_t \ +dn_umap_ ## key_type_name ## _ ## value_type_name ## _erase_key (dn_umap_t *map, key_type key) \ +{ \ + return dn_umap_erase_key (map, ((const void *)(uintptr_t)key)); \ +} \ +static inline bool \ +dn_umap_ ## key_type_name ## _ ## value_type_name ## _extract_key (dn_umap_t *map, key_type key, key_type *out_key, value_type *out_value) \ +{ \ + return dn_umap_extract_key (map, ((const void *)(uintptr_t)key), (void **)out_key, (void **)out_value); \ +} \ +static inline dn_umap_it_t \ +dn_umap_ ## key_type_name ## _ ## value_type_name ## _custom_find (dn_umap_t *map, key_type key, dn_umap_equal_func_t equal_func) \ +{ \ + return dn_umap_custom_find (map, ((const void *)(uintptr_t)key), equal_func); \ +} \ +static inline dn_umap_it_t \ +dn_umap_ ## key_type_name ## _ ## value_type_name ## _find (dn_umap_t *map, key_type key) \ +{ \ + return dn_umap_find (map, ((const void *)(uintptr_t)key)); \ +} + +DN_UMAP_IT_KEY_T (ptr, void *) + +DN_UMAP_IT_VALUE_T (bool, bool) +DN_UMAP_IT_VALUE_T (int8_t, int8_t) +DN_UMAP_IT_VALUE_T (uint8_t, uint8_t) +DN_UMAP_IT_VALUE_T (int16_t, int16_t) +DN_UMAP_IT_VALUE_T (uint16_t, uint16_t) +DN_UMAP_IT_VALUE_T (int32_t, int32_t) +DN_UMAP_IT_VALUE_T (uint32_t, uint32_t) + +DN_UMAP_T (ptr, void *, bool, bool) +DN_UMAP_T (ptr, void *, int8, int8_t) +DN_UMAP_T (ptr, void *, uint8, uint8_t) +DN_UMAP_T (ptr, void *, int16, int16_t) +DN_UMAP_T (ptr, void *, uint16, uint16_t) +DN_UMAP_T (ptr, void *, int32, int32_t) +DN_UMAP_T (ptr, void *, uint32, uint32_t) + +#endif /* __DN_UMAP_T_H__ */ diff --git a/src/native/containers/dn-umap.c b/src/native/containers/dn-umap.c new file mode 100644 index 0000000..0a86274 --- /dev/null +++ b/src/native/containers/dn-umap.c @@ -0,0 +1,620 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/* (C) 2006 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "dn-umap.h" +#include +#include +#include + +static void * KEYMARKER_REMOVED = &KEYMARKER_REMOVED; + +static const uint32_t prime_tbl [] = { + 11, 19, 37, 73, 109, 163, 251, 367, 557, 823, 1237, + 1861, 2777, 4177, 6247, 9371, 14057, 21089, 31627, + 47431, 71143, 106721, 160073, 240101, 360163, + 540217, 810343, 1215497, 1823231, 2734867, 4102283, + 6153409, 9230113, 13845163 +}; + +static bool +umap_test_prime (uint32_t x) +{ + if ((x & 1) != 0) { + uint32_t n; + for (n = 3; n < (uint32_t)sqrt (x); n += 2) { + if ((x % n) == 0) + return false; + } + return true; + } + return (x == 2); +} + +static uint32_t +umap_calc_prime (uint32_t x) +{ + uint32_t i; + + for (i = (x & (~1))-1; i < UINT32_MAX - 2; i += 2) { + if (umap_test_prime (i)) + return i; + } + return x; +} + +static uint32_t +umap_spaced_primes_closest (uint32_t x) +{ + for (size_t i = 0; i < ARRAY_SIZE (prime_tbl); i++) { + if (x <= prime_tbl [i]) + return prime_tbl [i]; + } + return umap_calc_prime (x); +} + +#ifdef DN_UMAP_SANITY_CHECK +#include +static void +umap_dump (dn_umap_t *map) +{ + for (uint32_t i = 0; i < map->_internal._bucket_count; i++) { + for (dn_umap_node_t *node = map->_internal._buckets [i]; node; node = node->next){ + uint32_t hashcode = map->_internal._hash_func (node->key); + uint32_t bucket = (hashcode) % map->_internal._bucket_count; + printf ("key %p hash %x on bucket %d correct bucket %d bucket count %d\n", node->key, hashcode, i, bucket, map->_internal._bucket_count); + } + } +} + +static void +umap_sanity_check (dn_umap_t *map) +{ + for (uint32_t i = 0; i < map->_internal._bucket_count; i++) { + for (dn_umap_node_t *node = map->_internal._buckets [i]; node; node = node->next){ + uint32_t hashcode = map->_internal._hash_func (node->key); + uint32_t bucket = (hashcode) % map->_internal._bucket_count; + if (bucket != i) { + printf ("Key %p (bucket %d) on invalid bucket %d (hashcode %x) (bucket count %d)", node->key, bucket, i, hashcode, map->_internal._bucket_count); + abort(); + } + } + } +} +#else + +#define umap_dump(map) do {}while(0) +#define umap_sanity_check(map) do {}while(0) + +#endif + +static void +umap_do_rehash ( + dn_umap_t *map, + uint32_t new_bucket_count) +{ + dn_umap_node_t **buckets = map->_internal._buckets; + uint32_t current_bucket_count = map->_internal._bucket_count; + + map->_internal._buckets = (dn_umap_node_t **)dn_allocator_alloc (map->_internal._allocator, sizeof (dn_umap_node_t *) * new_bucket_count); + if (!map->_internal._buckets) + return; + + memset (map->_internal._buckets, 0, sizeof (dn_umap_node_t *) * new_bucket_count); + + map->_internal._last_rehash = map->_internal._bucket_count; + map->_internal._bucket_count = new_bucket_count; + + for (uint32_t i = 0; i < current_bucket_count; i++){ + dn_umap_node_t *node, *next_node; + for (node = buckets [i]; node; node = next_node){ + uint32_t hashcode = map->_internal._hash_func (node->key) % map->_internal._bucket_count; + next_node = node->next; + + node->next = map->_internal._buckets [hashcode]; + map->_internal._buckets [hashcode] = node; + } + } + + dn_allocator_free (map->_internal._allocator, buckets); +} + +static void +umap_rehash (dn_umap_t *map) +{ + uint32_t diff; + + if (map->_internal._last_rehash > map->_internal._node_count) + diff = map->_internal._last_rehash - map->_internal._node_count; + else + diff = map->_internal._node_count - map->_internal._last_rehash; + + if (!((double)diff * 0.75 > (double)map->_internal._bucket_count * 2)) + return; + + umap_do_rehash (map, umap_spaced_primes_closest (map->_internal._node_count)); + umap_sanity_check (map); +} + +static void +umap_dispose_node ( + dn_umap_t *map, + dn_umap_node_t *node) +{ + if (DN_UNLIKELY (!map)) + return; + + if (map->_internal._key_dispose_func) + map->_internal._key_dispose_func (node->key); + + if (map->_internal._value_dispose_func) + map->_internal._value_dispose_func (node->value); +} + +static void +umap_free_node ( + dn_umap_t *map, + dn_umap_node_t *node) +{ + umap_dispose_node (map, node); + dn_allocator_free (map->_internal._allocator, node); +} + +static void +umap_erase_node ( + dn_umap_t *map, + uint32_t bucket, + dn_umap_node_t *node, + dn_umap_node_t *prev_node) +{ + umap_dispose_node (map, node); + + if (!prev_node) + map->_internal._buckets [bucket] = node->next; + else + prev_node->next = node->next; + + dn_allocator_free (map->_internal._allocator, node); + + map->_internal._node_count --; + + umap_sanity_check (map); +} + +static dn_umap_result_t +umap_insert ( + dn_umap_t *map, + void *key, + void *value, + bool assign) +{ + umap_sanity_check (map); + + dn_umap_result_t result = { { map, NULL, 0 }, false }; + dn_umap_equal_func_t equal_func = map->_internal._key_equal_func; + + if (map->_internal._node_count == dn_umap_max_size (map)) + return result; + + if (map->_internal._node_count >= map->_internal._threshold) + umap_rehash (map); + + uint32_t hashcode = map->_internal._hash_func (key) % map->_internal._bucket_count; + for (dn_umap_node_t *node = map->_internal._buckets [hashcode]; node; node = node->next) { + if (equal_func (node->key, key)) { + if (!assign) { + result.it._internal._node = node; + result.it._internal._index = hashcode; + return result; + } + + if (map->_internal._value_dispose_func) + map->_internal._value_dispose_func (node->value); + + node->value = value; + + umap_sanity_check (map); + + result.it._internal._index = hashcode; + result.it._internal._node = node; + result.result = true; + + return result; + } + } + + dn_umap_node_t *node = (dn_umap_node_t *)dn_allocator_alloc (map->_internal._allocator, sizeof (dn_umap_node_t)); + if (node) { + node->key = key; + node->value = value; + node->next = map->_internal._buckets [hashcode]; + map->_internal._buckets [hashcode] = node; + map->_internal._node_count ++; + + umap_sanity_check (map); + + result.it._internal._index = hashcode; + result.it._internal._node = node; + result.result = true; + } + + return result; +} + +static bool +umap_it_next (dn_umap_it_t *it) +{ + if (DN_UNLIKELY(dn_umap_it_end (*it))) + return false; + + dn_umap_t *map = it->_internal._map; + + DN_ASSERT (map); + + if (!it->_internal._node->next) { + while (true) { + it->_internal._index ++; + if (it->_internal._index >= map->_internal._bucket_count) { + *it = dn_umap_end (it->_internal._map); + return false; + } + if (map->_internal._buckets [it->_internal._index]) + break; + } + it->_internal._node = map->_internal._buckets [it->_internal._index]; + } else { + it->_internal._node = it->_internal._node->next; + } + + return it->_internal._node; +} + +dn_umap_it_t +dn_umap_begin (dn_umap_t *map) +{ + DN_ASSERT (map); + + dn_umap_it_t it = dn_umap_end (map); + uint32_t index = 0; + + while (true) { + if (index >= map->_internal._bucket_count) + return it; + + if (map->_internal._buckets [index]) + break; + + index ++; + } + + it._internal._node = map->_internal._buckets [index]; + it._internal._index = index; + + return it; +} + +void +dn_umap_it_advance ( + dn_umap_it_t *it, + uint32_t n) +{ + while (n && umap_it_next (it)) + n--; +} + +dn_umap_t * +dn_umap_custom_alloc (const dn_umap_custom_alloc_params_t *params) +{ + dn_allocator_t *allocator = params ? params->allocator : DN_DEFAULT_ALLOCATOR; + + dn_umap_t *map = (dn_umap_t *)dn_allocator_alloc (allocator, sizeof (dn_umap_t)); + if (!dn_umap_custom_init (map, params)) { + dn_allocator_free (allocator, map); + return NULL; + } + + return map; +} + +bool +dn_umap_custom_init ( + dn_umap_t *map, + const dn_umap_custom_alloc_params_t *params) +{ + if (DN_UNLIKELY (!map)) + return false; + + dn_allocator_t *allocator = params ? params->allocator : DN_DEFAULT_ALLOCATOR; + + memset (map, 0, sizeof(dn_umap_t)); + + map->_internal._allocator = allocator; + + map->_internal._bucket_count = umap_spaced_primes_closest (1); + + map->_internal._last_rehash = map->_internal._bucket_count; + + if (params) { + map->_internal._hash_func = params->hash_func ? params->hash_func : dn_direct_hash; + map->_internal._key_equal_func = params->equal_func ? params->equal_func : dn_direct_equal; + map->_internal._key_dispose_func = params->key_dispose_func; + map->_internal._value_dispose_func = params->value_dispose_func; + } else { + map->_internal._hash_func = dn_direct_hash; + map->_internal._key_equal_func = dn_direct_equal; + } + + map->_internal._buckets = (dn_umap_node_t **)dn_allocator_alloc (allocator, sizeof (dn_umap_node_t *) * map->_internal._bucket_count); + if (map->_internal._buckets) + memset (map->_internal._buckets, 0, sizeof (dn_umap_node_t *) * map->_internal._bucket_count); + + return map->_internal._buckets; +} + +void +dn_umap_free (dn_umap_t *map) +{ + if (DN_UNLIKELY(!map)) + return; + + dn_umap_dispose (map); + dn_allocator_free (map->_internal._allocator, map); +} + +void +dn_umap_dispose (dn_umap_t *map) +{ + if (DN_UNLIKELY(!map)) + return; + + for (uint32_t i = 0; i < map->_internal._bucket_count; i++) { + dn_umap_node_t *node, *next_node; + for (node = map->_internal._buckets [i]; node; node = next_node){ + next_node = node->next; + umap_free_node (map, node); + } + } + dn_allocator_free (map->_internal._allocator, map->_internal._buckets); +} + +void +dn_umap_clear (dn_umap_t *map) +{ + DN_ASSERT (map); + + for (uint32_t i = 0; i < map->_internal._bucket_count; i++) { + dn_umap_node_t *node, *next_node; + for (node = map->_internal._buckets [i]; node; node = next_node){ + next_node = node->next; + umap_free_node (map, node); + } + map->_internal._buckets [i] = NULL; + } + + map->_internal._node_count = 0; +} + +dn_umap_result_t +dn_umap_insert ( + dn_umap_t *map, + void *key, + void *value) +{ + DN_ASSERT (map); + return umap_insert (map, key, value, false); +} + +dn_umap_result_t +dn_umap_insert_or_assign ( + dn_umap_t *map, + void *key, + void *value) +{ + DN_ASSERT (map); + return umap_insert (map, key, value, true); +} + +dn_umap_it_t +dn_umap_erase (dn_umap_it_t position) +{ + if (dn_umap_it_end (position)) + return position; + + DN_ASSERT (position._internal._map); + + dn_umap_it_t result = dn_umap_it_next (position); + dn_umap_erase_key (position._internal._map, position._internal._node->key); + + return result; +} + +uint32_t +dn_umap_erase_key ( + dn_umap_t *map, + const void *key) +{ + DN_ASSERT (map); + + umap_sanity_check (map); + + dn_umap_equal_func_t equal_func = map->_internal._key_equal_func; + uint32_t hashcode = map->_internal._hash_func (key) % map->_internal._bucket_count; + + dn_umap_node_t *prev_node = NULL; + for (dn_umap_node_t *node = map->_internal._buckets [hashcode]; node; node = node->next){ + if (equal_func (node->key, key)){ + umap_erase_node (map, hashcode, node, prev_node); + return 1; + } + prev_node = node; + } + + umap_sanity_check (map); + return 0; +} + +bool +dn_umap_extract_key ( + dn_umap_t *map, + const void *key, + void **out_key, + void **out_value) +{ + DN_ASSERT (map); + + dn_umap_equal_func_t equal_func = map->_internal._key_equal_func; + uint32_t hashcode = map->_internal._hash_func (key) % map->_internal._bucket_count; + + dn_umap_node_t *prev_node = NULL; + for (dn_umap_node_t *node = map->_internal._buckets [hashcode]; node; node = node->next){ + if (equal_func (node->key, key)){ + if (!prev_node) + map->_internal._buckets [hashcode] = node->next; + else + prev_node->next = node->next; + + if (out_key) + *out_key = node->key; + if (out_value) + *out_value = node->value; + + dn_allocator_free (map->_internal._allocator, node); + map->_internal._node_count --; + + umap_sanity_check (map); + return true; + } + prev_node = node; + } + + umap_sanity_check (map); + return false; +} + +dn_umap_it_t +dn_umap_custom_find ( + dn_umap_t *map, + const void *data, + dn_umap_equal_func_t equal_func) +{ + DN_ASSERT (map); + + dn_umap_it_t found = dn_umap_end (map); + equal_func = equal_func ? equal_func : map->_internal._key_equal_func; + + for (uint32_t i = 0; i < map->_internal._bucket_count; i++) { + for (dn_umap_node_t *node = map->_internal._buckets [i]; node; node = node->next) + if (equal_func (node->key, data)) { + found._internal._index = i; + found._internal._node = node; + return found; + } + } + + return found; +} + +void +dn_umap_for_each ( + dn_umap_t *map, + dn_umap_key_value_func_t for_each_func, + void *user_data) +{ + DN_ASSERT (map && for_each_func); + + DN_UMAP_FOREACH_BEGIN (void *, key, void *, value, map) { + for_each_func (key, value, user_data); + } DN_UMAP_FOREACH_END; +} + +void +dn_umap_rehash ( + dn_umap_t *map, + uint32_t count) +{ + DN_ASSERT (map); + + if (count < map->_internal._node_count) + count = map->_internal._node_count; + + umap_do_rehash (map, count); +} + +void +dn_umap_reserve ( + dn_umap_t *map, + uint32_t count) +{ + DN_ASSERT (map); + + umap_do_rehash (map, count); +} + +bool +DN_CALLBACK_CALLTYPE +dn_direct_equal (const void *v1, const void *v2) +{ + return v1 == v2; +} + +uint32_t +DN_CALLBACK_CALLTYPE +dn_direct_hash (const void *v1) +{ + return ((uint32_t)(size_t)(v1)); +} + +bool +DN_CALLBACK_CALLTYPE +dn_int_equal (const void *v1, const void *v2) +{ + return *(int32_t *)v1 == *(int32_t *)v2; +} + +uint32_t +DN_CALLBACK_CALLTYPE +dn_int_hash (const void *v1) +{ + return *(uint32_t *)v1; +} + +bool +DN_CALLBACK_CALLTYPE +dn_str_equal (const void *v1, const void *v2) +{ + return v1 == v2 || strcmp ((const char*)v1, (const char*)v2) == 0; +} + +uint32_t +DN_CALLBACK_CALLTYPE +dn_str_hash (const void *v1) +{ + uint32_t hash = 0; + char *p = (char *) v1; + + while (*p++) + hash = (hash << 5) - (hash + *p); + + return hash; +} diff --git a/src/native/containers/dn-umap.h b/src/native/containers/dn-umap.h new file mode 100644 index 0000000..140d9bf --- /dev/null +++ b/src/native/containers/dn-umap.h @@ -0,0 +1,277 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_UMAP_H__ +#define __DN_UMAP_H__ + +#include "dn-utils.h" +#include "dn-allocator.h" + +typedef uint32_t (DN_CALLBACK_CALLTYPE *dn_umap_hash_func_t) (const void *key); +typedef bool (DN_CALLBACK_CALLTYPE *dn_umap_equal_func_t) (const void *a, const void *b); +typedef void (DN_CALLBACK_CALLTYPE *dn_umap_key_dispose_func_t) (void *key); +typedef void (DN_CALLBACK_CALLTYPE *dn_umap_value_dispose_func_t) (void *value); +typedef void (DN_CALLBACK_CALLTYPE *dn_umap_key_value_func_t) (void *key, void *value, void *user_data); + +typedef struct _dn_umap_node_t dn_umap_node_t; +struct _dn_umap_node_t { + void *key; + void *value; + dn_umap_node_t *next; +}; + +typedef struct _dn_umap_t dn_umap_t; +struct _dn_umap_t { + struct { + dn_umap_node_t **_buckets; + dn_umap_hash_func_t _hash_func; + dn_umap_equal_func_t _key_equal_func; + dn_umap_key_dispose_func_t _key_dispose_func; + dn_umap_value_dispose_func_t _value_dispose_func; + dn_allocator_t *_allocator; + uint32_t _bucket_count; + uint32_t _node_count; + uint32_t _threshold; + uint32_t _last_rehash; + } _internal; +}; + +typedef struct _dn_umap_it_t dn_umap_it_t; +struct _dn_umap_it_t +{ + struct { + dn_umap_t *_map; + dn_umap_node_t *_node; + uint32_t _index; + } _internal; +}; + +typedef struct _dn_umap_result_t dn_umap_result_t; +struct _dn_umap_result_t { + dn_umap_it_t it; + bool result; +}; + +typedef struct _dn_umap_custom_params_t dn_umap_custom_alloc_params_t; +typedef struct _dn_umap_custom_params_t dn_umap_custom_init_params_t; +struct _dn_umap_custom_params_t { + dn_allocator_t *allocator; + dn_umap_hash_func_t hash_func; + dn_umap_equal_func_t equal_func; + dn_umap_key_dispose_func_t key_dispose_func; + dn_umap_value_dispose_func_t value_dispose_func; +}; + +dn_umap_it_t +dn_umap_begin (dn_umap_t *map); + +static inline dn_umap_it_t +dn_umap_end (dn_umap_t *map) +{ + DN_ASSERT (map); + dn_umap_it_t it = { { map, NULL, 0 } }; + return it; +} + +void +dn_umap_it_advance ( + dn_umap_it_t *it, + uint32_t n); + +static inline dn_umap_it_t +dn_umap_it_next (dn_umap_it_t it) +{ + dn_umap_it_advance (&it, 1); + return it; +} + +static inline void * +dn_umap_it_key (dn_umap_it_t it) +{ + DN_ASSERT (it._internal._node); + return it._internal._node->key; +} + +#define dn_umap_it_key_t(it, type) \ + (type)(uintptr_t)(dn_umap_it_key (it)) + +static inline void * +dn_umap_it_value (dn_umap_it_t it) +{ + DN_ASSERT (it._internal._node); + return it._internal._node->value; +} + +#define dn_umap_it_value_t(it, type) \ + (type)(uintptr_t)(dn_umap_it_value ((it))) + +static inline bool +dn_umap_it_begin (dn_umap_it_t it) +{ + dn_umap_it_t begin = dn_umap_begin (it._internal._map); + return (begin._internal._node == it._internal._node && begin._internal._index == it._internal._index); +} + +static inline bool +dn_umap_it_end (dn_umap_it_t it) +{ + return !(it._internal._node); +} + +#define DN_UMAP_FOREACH_BEGIN(key_type, key_name, value_type, value_name, map) do { \ + key_type key_name; \ + value_type value_name; \ + for (dn_umap_it_t __it##key_name = dn_umap_begin (map); !dn_umap_it_end (__it##key_name); __it##key_name = dn_umap_it_next (__it##key_name)) { \ + key_name = ((key_type)(uintptr_t)dn_umap_it_key (__it##key_name)); \ + value_name = ((value_type)(uintptr_t)dn_umap_it_value (__it##key_name)); + +#define DN_UMAP_FOREACH_KEY_BEGIN(key_type, key_name, map) do { \ + key_type key_name; \ + for (dn_umap_it_t __it##key_name = dn_umap_begin (map); !dn_umap_it_end (__it##key_name); __it##key_name = dn_umap_it_next (__it##key_name)) { \ + key_name = ((key_type)(uintptr_t)dn_umap_it_key (__it##key_name)); + +#define DN_UMAP_FOREACH_END \ + } \ + } while (0) + +dn_umap_t * +dn_umap_custom_alloc (const dn_umap_custom_alloc_params_t *params); + +static inline dn_umap_t * +dn_umap_alloc (void) +{ + return dn_umap_custom_alloc (NULL); +} + +void +dn_umap_free (dn_umap_t *map); + +bool +dn_umap_custom_init ( + dn_umap_t *map, + const dn_umap_custom_init_params_t *params); + +static inline bool +dn_umap_init (dn_umap_t *map) +{ + return dn_umap_custom_init (map, NULL); +} + +void +dn_umap_dispose (dn_umap_t *map); + +static inline bool +dn_umap_empty (const dn_umap_t *map) +{ + DN_ASSERT (map); + return map->_internal._node_count == 0; +} + +static inline uint32_t +dn_umap_size (const dn_umap_t *map) +{ + DN_ASSERT (map); + return map->_internal._node_count; +} + +static inline uint32_t +dn_umap_max_size (const dn_umap_t *map) +{ + DN_UNREFERENCED_PARAMETER (map); + return UINT32_MAX; +} + +void +dn_umap_clear (dn_umap_t *map); + +dn_umap_result_t +dn_umap_insert ( + dn_umap_t *map, + void *key, + void *value); + +dn_umap_result_t +dn_umap_insert_or_assign ( + dn_umap_t *map, + void *key, + void *value); + +dn_umap_it_t +dn_umap_erase (dn_umap_it_t position); + +uint32_t +dn_umap_erase_key ( + dn_umap_t *map, + const void *key); + +bool +dn_umap_extract_key ( + dn_umap_t *map, + const void *key, + void **out_key, + void **out_value); + +dn_umap_it_t +dn_umap_custom_find ( + dn_umap_t *map, + const void *key, + dn_umap_equal_func_t equal_func); + +static inline dn_umap_it_t +dn_umap_find ( + dn_umap_t *map, + const void *key) +{ + return dn_umap_custom_find (map, key, NULL); +} + +static inline bool +dn_umap_contains ( + dn_umap_t *map, + const void *key) +{ + dn_umap_it_t it = dn_umap_find (map, key); + return !dn_umap_it_end (it); +} + +void +dn_umap_for_each ( + dn_umap_t *map, + dn_umap_key_value_func_t for_each_func, + void *user_data); + +void +dn_umap_rehash ( + dn_umap_t *map, + uint32_t count); + +void +dn_umap_reserve ( + dn_umap_t *map, + uint32_t count); + +bool +DN_CALLBACK_CALLTYPE +dn_direct_equal (const void *v1, const void *v2); + +uint32_t +DN_CALLBACK_CALLTYPE +dn_direct_hash (const void *v1); + +bool +DN_CALLBACK_CALLTYPE +dn_int_equal (const void *v1, const void *v2); + +uint32_t +DN_CALLBACK_CALLTYPE +dn_int_hash (const void *v1); + +bool +DN_CALLBACK_CALLTYPE +dn_str_equal (const void *v1, const void *v2); + +uint32_t +DN_CALLBACK_CALLTYPE +dn_str_hash (const void *v1); + +#endif /* __DN_UMAP_H__ */ diff --git a/src/native/containers/dn-utils.h b/src/native/containers/dn-utils.h new file mode 100644 index 0000000..7c07f5f --- /dev/null +++ b/src/native/containers/dn-utils.h @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_UTILS_H__ +#define __DN_UTILS_H__ + +#ifdef __cplusplus +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif +#else +#include +#endif + +#include +#include + +#if defined(_DEBUG) +#include +#define DN_ASSERT(x) assert(x) +#else +#define DN_ASSERT(x) +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX ((uint32_t)0xffffffff) +#endif + +#ifndef INT32_MAX +#define INT32_MAX ((int32_t)2147483647) +#endif + +#if defined(_WIN32) +#define DN_CALLBACK_CALLTYPE __cdecl +#else +#define DN_CALLBACK_CALLTYPE +#endif + +#if defined(__GNUC__) && (__GNUC__ > 2) +#define DN_LIKELY(expr) (__builtin_expect ((expr) != 0, 1)) +#define DN_UNLIKELY(expr) (__builtin_expect ((expr) != 0, 0)) +#else +#define DN_LIKELY(x) (x) +#define DN_UNLIKELY(x) (x) +#endif + +#define DN_UNREFERENCED_PARAMETER(expr) (void)(expr) + +// Until C11 support, use typedef expression for static assertion. +#define _DN_STATIC_ASSERT_UNQIUE_TYPEDEF0(line) __dn_static_assert_ ## line ## _t +#define _DN_STATIC_ASSERT_UNQIUE_TYPEDEF(line) _DN_STATIC_ASSERT_UNQIUE_TYPEDEF0(line) +#define _DN_STATIC_ASSERT(expr) typedef char _DN_STATIC_ASSERT_UNQIUE_TYPEDEF(__LINE__)[(expr) != 0] + +static inline bool +dn_safe_size_t_multiply (size_t lhs, size_t rhs, size_t *result) +{ + if (lhs == 0 || rhs == 0) { + *result = 0; + return true; + } + + if (((size_t)(~(size_t)0) / lhs) < rhs) + return false; + + *result = lhs * rhs; + return true; +} + +static inline bool +dn_safe_uint32_t_add (uint32_t lhs, uint32_t rhs, uint32_t *result) +{ + if((UINT32_MAX - lhs) < rhs) + return false; + + *result = lhs + rhs; + return true; +} + +#endif /* __DN_UTILS_H__ */ diff --git a/src/native/containers/dn-vector-priv.h b/src/native/containers/dn-vector-priv.h new file mode 100644 index 0000000..df6bb25 --- /dev/null +++ b/src/native/containers/dn-vector-priv.h @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_VECTOR_PRIV_H__ +#define __DN_VECTOR_PRIV_H__ + +#include "dn-utils.h" +#include "dn-allocator.h" +#include "dn-vector-types.h" + +bool +_dn_vector_insert_range ( + dn_vector_it_t *position, + const uint8_t *elements, + uint32_t element_count); + +bool +_dn_vector_append_range ( + dn_vector_t *vector, + const uint8_t *elements, + uint32_t element_count); + +bool +_dn_vector_erase ( + dn_vector_it_t *position, + dn_vector_dispose_func_t dispose_func); + +bool +_dn_vector_erase_fast ( + dn_vector_it_t *position, + dn_vector_dispose_func_t dispose_func); + +uint32_t +_dn_vector_buffer_capacity ( + size_t buffer_size, + uint32_t element_size); + +dn_vector_it_t +_dn_vector_custom_find ( + dn_vector_t *vector, + const uint8_t *value, + dn_vector_equal_func_t equal_func); + +static inline dn_vector_result_t +_dn_vector_insert_range_adapter ( + dn_vector_it_t position, + const uint8_t *elements, + uint32_t element_count) +{ + dn_vector_result_t result; + + if (position.it == position._internal._vector->size) + result.result = _dn_vector_append_range (position._internal._vector, elements, element_count); + else + result.result = _dn_vector_insert_range (&position, elements, element_count); + + result.it = position; + return result; +} + +static inline dn_vector_result_t +_dn_vector_erase_adapter ( + dn_vector_it_t position, + dn_vector_dispose_func_t dispose_func) +{ + dn_vector_result_t result; + result.result = _dn_vector_erase (&position, dispose_func); + result.it = position; + return result; +} + +static inline dn_vector_result_t +_dn_vector_erase_fast_adapter ( + dn_vector_it_t position, + dn_vector_dispose_func_t dispose_func) +{ + dn_vector_result_t result; + result.result = _dn_vector_erase_fast (&position, dispose_func); + result.it = position; + return result; +} + +static inline void +_dn_vector_find_adapter ( + dn_vector_t *vector, + const uint8_t *data, + dn_vector_equal_func_t equal_func, + dn_vector_it_t *found) +{ + DN_ASSERT (found); + *found = _dn_vector_custom_find (vector, data, equal_func); +} + +#endif /* __DN_VECTOR_PRIV_H__ */ diff --git a/src/native/containers/dn-vector-ptr.h b/src/native/containers/dn-vector-ptr.h new file mode 100644 index 0000000..ca5be73 --- /dev/null +++ b/src/native/containers/dn-vector-ptr.h @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_VECTOR_PTR_H__ +#define __DN_VECTOR_PTR_H__ + +#include "dn-vector-t.h" + +DN_DEFINE_VECTOR_T (ptr, void *) + +#define DN_VECTOR_PTR_FOREACH_BEGIN(var_type, var_name, vector) do { \ + var_type var_name; \ + DN_ASSERT (sizeof (var_type) == (vector)->_internal._element_size); \ + for (uint32_t __i_ ## var_name = 0; __i_ ## var_name < (vector)->size; ++__i_ ## var_name) { \ + var_name = (var_type)*dn_vector_ptr_index (vector, __i_##var_name); + +#define DN_VECTOR_PTR_FOREACH_RBEGIN(var_type, var_name, vector) do { \ + var_type var_name; \ + DN_ASSERT (sizeof (var_type) == (vector)->_internal._element_size); \ + for (uint32_t __i_ ## var_name = (vector)->size; __i_ ## var_name > 0; --__i_ ## var_name) { \ + var_name = (var_type)*dn_vector_ptr_index (vector, __i_ ## var_name - 1); + +#define DN_VECTOR_PTR_FOREACH_END \ + } \ + } while (0) + +#endif /* __DN_VECTOR_PTR_H__ */ diff --git a/src/native/containers/dn-vector-t.h b/src/native/containers/dn-vector-t.h new file mode 100644 index 0000000..91ee8ce --- /dev/null +++ b/src/native/containers/dn-vector-t.h @@ -0,0 +1,288 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_VECTOR_T_H__ +#define __DN_VECTOR_T_H__ + +#include "dn-vector.h" + +#define DN_DEFINE_VECTOR_T_NAME(name) \ + dn_vector_ ## name ## _t + +#define DN_DEFINE_VECTOR_RESULT_T_NAME(name) \ + dn_vector_ ## name ## _result_t + +#define DN_DEFINE_VECTOR_IT_T_NAME(name) \ + dn_vector_ ## name ## _it_t + +#define DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, symbol) \ + dn_vector_ ## name ## _ ## symbol + +#define DN_DEFINE_VECTOR_IT_T_SYMBOL_NAME(name, symbol) \ + dn_vector_ ## name ## _it_ ## symbol + +#define DN_DEFINE_VECTOR_CUSTOM_ALLOC_PARAMS_T_SYMBOL_NAME(name) \ + dn_vector_ ## name ## _custom_alloc_params_t + +#define DN_DEFINE_VECTOR_CUSTOM_ALLOC_INIT_T_SYMBOL_NAME(name) \ + dn_vector_ ## name ## _custom_init_params_t + +#define DN_DEFINE_VECTOR_T(name, type) \ +DN_DEFINE_VECTOR_T_STRUCT(dn_vector_ ## name, type); \ +typedef enum { \ + DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, element_size) = sizeof (type), \ + DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, default_local_allocator_capacity_size) = 192, \ + DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, default_local_allocator_byte_size) = ((sizeof (type) * DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, default_local_allocator_capacity_size)) + DN_ALLOCATOR_ALIGN_SIZE (sizeof (dn_vector_t), DN_ALLOCATOR_MEM_ALIGN8) + 32) \ +} DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, sizes); \ +static inline void \ +DN_DEFINE_VECTOR_IT_T_SYMBOL_NAME(name, advance) (DN_DEFINE_VECTOR_IT_T_NAME(name) *it, ptrdiff_t n) \ +{ \ + dn_vector_it_advance ((dn_vector_it_t *)it, n); \ +} \ +static inline DN_DEFINE_VECTOR_IT_T_NAME(name) \ +DN_DEFINE_VECTOR_IT_T_SYMBOL_NAME(name, next) (DN_DEFINE_VECTOR_IT_T_NAME(name) it) \ +{ \ + DN_ASSERT ((it.it + 1) < UINT32_MAX); \ + it.it++; \ + return it; \ +} \ +static inline DN_DEFINE_VECTOR_IT_T_NAME(name) \ +DN_DEFINE_VECTOR_IT_T_SYMBOL_NAME(name, prev) (DN_DEFINE_VECTOR_IT_T_NAME(name) it) \ +{ \ + DN_ASSERT (it.it > 0); \ + it.it--; \ + return it; \ +} \ +static inline DN_DEFINE_VECTOR_IT_T_NAME(name) \ +DN_DEFINE_VECTOR_IT_T_SYMBOL_NAME(name, next_n) (DN_DEFINE_VECTOR_IT_T_NAME(name) it, uint32_t n) \ +{ \ + DN_ASSERT ((it.it + n) < UINT32_MAX); \ + it.it += n; \ + return it; \ +} \ +static inline DN_DEFINE_VECTOR_IT_T_NAME(name) \ +DN_DEFINE_VECTOR_IT_T_SYMBOL_NAME(name, prev_n) (DN_DEFINE_VECTOR_IT_T_NAME(name) it, uint32_t n) \ +{ \ + DN_ASSERT (it.it >= n); \ + it.it -= n; \ + return it; \ +} \ +static inline type * \ +DN_DEFINE_VECTOR_IT_T_SYMBOL_NAME(name, data) (DN_DEFINE_VECTOR_IT_T_NAME(name) it, uint32_t n) \ +{ \ + DN_ASSERT (it._internal._vector && it._internal._vector->data); \ + return (type *)(it._internal._vector->data + n);\ +} \ +static inline DN_DEFINE_VECTOR_T_NAME(name) * \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_alloc) (const DN_DEFINE_VECTOR_CUSTOM_ALLOC_PARAMS_T_SYMBOL_NAME(name) *params) \ +{ \ + return (DN_DEFINE_VECTOR_T_NAME(name) *)dn_vector_custom_alloc ((dn_vector_custom_alloc_params_t *)params, sizeof (type)); \ +} \ +static inline DN_DEFINE_VECTOR_T_NAME(name) * \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, alloc) (void) \ +{ \ + return (DN_DEFINE_VECTOR_T_NAME(name) *)dn_vector_alloc (sizeof (type)); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, free) (DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + dn_vector_free ((dn_vector_t *)vector); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_free) (DN_DEFINE_VECTOR_T_NAME(name) *vector, dn_vector_dispose_func_t dispose_func) \ +{ \ + dn_vector_custom_free ((dn_vector_t *)vector, dispose_func); \ +} \ +static inline bool \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_init) (DN_DEFINE_VECTOR_T_NAME(name) *vector, DN_DEFINE_VECTOR_CUSTOM_ALLOC_PARAMS_T_SYMBOL_NAME (name) *params) \ +{ \ + return dn_vector_custom_init ((dn_vector_t *)vector, (dn_vector_custom_alloc_params_t *)params, sizeof(type)); \ +} \ +static inline bool \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, init) (DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + return dn_vector_init ((dn_vector_t *)vector, sizeof (type)); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_dispose) (DN_DEFINE_VECTOR_T_NAME(name) *vector, dn_vector_dispose_func_t dispose_func) \ +{ \ + dn_vector_custom_dispose ((dn_vector_t *)vector, dispose_func); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, dispose) (DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + dn_vector_custom_dispose ((dn_vector_t *)vector, NULL); \ +} \ +static inline type * \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, index) (const DN_DEFINE_VECTOR_T_NAME(name) *vector, uint32_t index) \ +{ \ + return dn_vector_index_t ((dn_vector_t *)vector, type, index); \ +}\ +static inline type * \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, at) (const DN_DEFINE_VECTOR_T_NAME(name) *vector, uint32_t index) \ +{ \ + return dn_vector_at_t ((dn_vector_t *)vector, type, index); \ +}\ +static inline type * \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, front) (const DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + return dn_vector_front_t ((dn_vector_t *)vector, type); \ +}\ +static inline type * \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, back) (const DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + return dn_vector_back_t ((dn_vector_t *)vector, type); \ +}\ +static inline type * \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, data) (const DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + return dn_vector_data_t ((dn_vector_t *)vector, type); \ +} \ +static inline DN_DEFINE_VECTOR_IT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, begin) (DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + DN_ASSERT (vector); \ + DN_DEFINE_VECTOR_IT_T_NAME(name) it = { 0, { vector } }; \ + return it; \ +} \ +static inline DN_DEFINE_VECTOR_IT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, end) (DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + DN_ASSERT (vector); \ + DN_DEFINE_VECTOR_IT_T_NAME(name) it = { vector->size, { vector } }; \ + return it; \ +} \ +static inline bool \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, empty) (const DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + return dn_vector_empty ((dn_vector_t *)vector); \ +} \ +static inline uint32_t \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, size) (const DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + return dn_vector_size ((dn_vector_t *)vector); \ +} \ +static inline uint32_t \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, max_size) (const DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + return dn_vector_max_size ((dn_vector_t *)vector); \ +} \ +static inline bool \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, reserve) (DN_DEFINE_VECTOR_T_NAME(name) *vector, uint32_t capacity) \ +{ \ + return dn_vector_reserve ((dn_vector_t *)vector, capacity); \ +} \ +static inline uint32_t \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, capacity) (const DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + return dn_vector_capacity ((dn_vector_t *)vector); \ +} \ +static inline DN_DEFINE_VECTOR_RESULT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, insert) (DN_DEFINE_VECTOR_IT_T_NAME(name) position, type element) \ +{ \ + DN_DEFINE_VECTOR_RESULT_T_NAME(name) result; \ + result.result = _dn_vector_insert_range ((dn_vector_it_t *)&position, (const uint8_t *)&element, 1); \ + result.it = position; \ + return result; \ +} \ +static inline DN_DEFINE_VECTOR_RESULT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, insert_range) (DN_DEFINE_VECTOR_IT_T_NAME(name) position, type *elements, uint32_t element_count) \ +{ \ + DN_DEFINE_VECTOR_RESULT_T_NAME(name) result; \ + result.result = _dn_vector_insert_range ((dn_vector_it_t *)&position, (const uint8_t *)(elements), element_count); \ + result.it = position; \ + return result; \ +} \ +static inline DN_DEFINE_VECTOR_RESULT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_erase) (DN_DEFINE_VECTOR_IT_T_NAME(name) position, dn_vector_dispose_func_t dispose_func) \ +{ \ + DN_DEFINE_VECTOR_RESULT_T_NAME(name) result; \ + result.result = _dn_vector_erase ((dn_vector_it_t *)&position, dispose_func); \ + result.it = position; \ + return result; \ +} \ +static inline DN_DEFINE_VECTOR_RESULT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, erase) (DN_DEFINE_VECTOR_IT_T_NAME(name) position) \ +{ \ + return DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_erase) (position, NULL); \ +} \ +static inline DN_DEFINE_VECTOR_RESULT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_erase_fast) (DN_DEFINE_VECTOR_IT_T_NAME(name) position, dn_vector_dispose_func_t dispose_func) \ +{ \ + DN_DEFINE_VECTOR_RESULT_T_NAME(name) result; \ + result.result = _dn_vector_erase_fast ((dn_vector_it_t *)&position, dispose_func); \ + result.it = position; \ + return result; \ +} \ +static inline DN_DEFINE_VECTOR_RESULT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, erase_fast) (DN_DEFINE_VECTOR_IT_T_NAME(name) position) \ +{ \ + return DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_erase_fast) (position, NULL); \ +} \ +static inline bool \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_resize) (DN_DEFINE_VECTOR_T_NAME(name) *vector, uint32_t size, dn_vector_dispose_func_t dispose_func) \ +{ \ + return dn_vector_custom_resize ((dn_vector_t *)vector, size, dispose_func); \ +} \ +static inline bool \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, resize) (DN_DEFINE_VECTOR_T_NAME(name) *vector, uint32_t size) \ +{ \ + return dn_vector_custom_resize ((dn_vector_t *)vector, size, NULL); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_clear) (DN_DEFINE_VECTOR_T_NAME(name) *vector, dn_vector_dispose_func_t dispose_func) \ +{ \ + dn_vector_custom_clear ((dn_vector_t *)vector, dispose_func); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, clear) (DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + dn_vector_custom_clear ((dn_vector_t *)vector, NULL); \ +} \ +static inline bool \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, push_back) (DN_DEFINE_VECTOR_T_NAME(name) *vector, type element) \ +{ \ + DN_ASSERT (vector); \ + return dn_vector_push_back ((dn_vector_t *)vector, element); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_pop_back) (DN_DEFINE_VECTOR_T_NAME(name) *vector, dn_vector_dispose_func_t dispose_func) \ +{ \ + dn_vector_custom_pop_back ((dn_vector_t*)vector, dispose_func); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, pop_back) (DN_DEFINE_VECTOR_T_NAME(name) *vector) \ +{ \ + dn_vector_pop_back ((dn_vector_t*)vector); \ +} \ +static inline uint32_t \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, buffer_capacity) (size_t buffer_byte_size) \ +{ \ + return dn_vector_buffer_capacity_t (buffer_byte_size, type); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, for_each) (const DN_DEFINE_VECTOR_T_NAME(name) *vector, dn_vector_for_each_func_t for_each_func, void *user_data) \ +{ \ + dn_vector_for_each ((dn_vector_t*)vector, for_each_func, user_data); \ +} \ +static inline void \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, sort) (DN_DEFINE_VECTOR_T_NAME(name) *vector, dn_vector_compare_func_t compare_func) \ +{ \ + dn_vector_sort ((dn_vector_t*)vector, compare_func); \ +} \ +static inline DN_DEFINE_VECTOR_IT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, custom_find) (const DN_DEFINE_VECTOR_T_NAME(name) *vector, const type value, dn_vector_equal_func_t equal_func) \ +{ \ + DN_DEFINE_VECTOR_IT_T_NAME(name) found; \ + _dn_vector_find_adapter ((dn_vector_t*)vector, (const uint8_t *)&value, equal_func, (dn_vector_it_t *)&found); \ + return found; \ +} \ +static inline DN_DEFINE_VECTOR_IT_T_NAME(name) \ +DN_DEFINE_VECTOR_T_SYMBOL_NAME(name, find) (const DN_DEFINE_VECTOR_T_NAME(name) *vector, const type value) \ +{ \ + DN_DEFINE_VECTOR_IT_T_NAME(name) found; \ + _dn_vector_find_adapter ((dn_vector_t*)vector, (const uint8_t *)&value, NULL, (dn_vector_it_t *)&found); \ + return found; \ +} + +#endif /* __DN_VECTOR_T_H__ */ diff --git a/src/native/containers/dn-vector-types.h b/src/native/containers/dn-vector-types.h new file mode 100644 index 0000000..d67f28c --- /dev/null +++ b/src/native/containers/dn-vector-types.h @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_VECTOR_TYPES_H__ +#define __DN_VECTOR_TYPES_H__ + +#include "dn-utils.h" +#include "dn-allocator.h" + +typedef int32_t (DN_CALLBACK_CALLTYPE *dn_vector_compare_func_t) (const void *a, const void *b); +typedef bool (DN_CALLBACK_CALLTYPE *dn_vector_equal_func_t) (const void *a, const void *b); +typedef void (DN_CALLBACK_CALLTYPE *dn_vector_for_each_func_t) (void *data, void *user_data); +typedef void (DN_CALLBACK_CALLTYPE *dn_vector_dispose_func_t) (void *data); + +#define DN_DEFINE_VECTOR_T_STRUCT(name, type) \ +typedef struct _ ## name ## _t name ## _t; \ +struct _ ## name ## _t { \ + type* data; \ + uint32_t size; \ + struct { \ + uint32_t _element_size; \ + uint32_t _capacity; \ + uint32_t _attributes; \ + dn_allocator_t *_allocator; \ + } _internal; \ +}; \ +typedef struct _ ## name ## _it_t name ## _it_t; \ +struct _ ## name ## _it_t { \ + uint32_t it; \ + struct { \ + name ## _t *_vector; \ + } _internal; \ +}; \ +typedef struct _ ## name ## _result_t name ## _result_t; \ +struct _ ## name ## _result_t { \ + bool result; \ + name ## _it_t it; \ +}; \ +typedef struct _ ## name ## _custom_params_t name ## _custom_alloc_params_t; \ +typedef struct _ ## name ## _custom_params_t name ## _custom_init_params_t; \ +struct _ ## name ## _custom_params_t { \ + dn_allocator_t *allocator; \ + uint32_t capacity; \ + uint32_t attributes; \ +}; + +DN_DEFINE_VECTOR_T_STRUCT (dn_vector, uint8_t); + +typedef enum { + DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT = 0x1 +} dn_vector_attribute; + +#endif /* __DN_VECTOR_TYPES_H__ */ diff --git a/src/native/containers/dn-vector.c b/src/native/containers/dn-vector.c new file mode 100644 index 0000000..280d695 --- /dev/null +++ b/src/native/containers/dn-vector.c @@ -0,0 +1,397 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/* (C) 2006 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "dn-vector.h" + +#define INITIAL_CAPACITY 16 +#define CALC_NEW_CAPACITY(capacity) ((capacity + (capacity >> 1) + 63) & ~63) + +#define element_offset(p,i) \ + ((p)->data + (i) * (p)->_internal._element_size) + +#define element_length(p,i) \ + ((i) * (p)->_internal._element_size) + +#define check_attribute(vector, value) ((vector->_internal._attributes & (uint32_t)value) == value) + +static bool +ensure_capacity ( + dn_vector_t *vector, + uint32_t capacity) +{ + uint64_t new_capacity; + + if (capacity != 0 && capacity <= (uint64_t)(vector->_internal._capacity)) + return true; + + new_capacity = CALC_NEW_CAPACITY (capacity); + + if (DN_UNLIKELY (new_capacity > (uint64_t)(UINT32_MAX))) + return false; + + size_t realloc_size; + if (DN_UNLIKELY (!dn_safe_size_t_multiply (element_length (vector, 1), (size_t)new_capacity, &realloc_size))) + return false; + + uint8_t *data = (uint8_t *)dn_allocator_realloc (vector->_internal._allocator, vector->data, realloc_size); + + if (DN_UNLIKELY (!data && realloc_size != 0)) + return false; + + vector->data = data; + + if (vector->data && !check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT)) { + // Checks already verified that element_offset won't overflow. + // new_capacity > vector capacity, so new_capacity - vector capacity won't underflow. + // dn_safe_size_t_multiply already verified element_length won't overflow. + memset (element_offset (vector, vector->_internal._capacity), 0, element_length (vector, (uint32_t)new_capacity - vector->_internal._capacity)); + } + + // Overflow already checked. + vector->_internal._capacity = (uint32_t)new_capacity; + + return vector->data != NULL; +} + +bool +_dn_vector_insert_range ( + dn_vector_it_t *position, + const uint8_t *elements, + uint32_t element_count) +{ + DN_ASSERT (elements && element_count != 0); + + dn_vector_t *vector = position->_internal._vector; + + uint64_t new_capacity = (uint64_t)vector->size + (uint64_t)element_count; + if (DN_UNLIKELY (new_capacity > (uint64_t)(UINT32_MAX))) + return false; + + if (DN_UNLIKELY (!ensure_capacity (vector, (uint32_t)new_capacity))) + return false; + + uint64_t insert_offset = (uint64_t)position->it + (uint64_t)element_count; + uint64_t size_to_move = (uint64_t)vector->size - (uint64_t)position->it; + if (DN_UNLIKELY (insert_offset > new_capacity || size_to_move > vector->size)) + return false; + + /* first move the existing elements out of the way */ + /* element_offset won't overflow since insert_offset and position is smaller than new_capacity already checked in ensure_capacity */ + /* element_length won't overflow since size_to_move is smaller than new_capacity already checked in ensure_capacity */ + /* element_length won't underflow since size_to_move is already verfied to be smaller or equal to vector->size */ + memmove (element_offset (vector, (uint32_t)insert_offset), element_offset (vector, position->it), element_length (vector, (uint32_t)size_to_move)); + + /* then copy the new elements into the array */ + /* element_offset won't overflow since position is smaller than new_capacity already checked in encure_capacity */ + /* element_length won't overflow since element_count is included in new_capacity already checked in encure_capacity */ + memmove (element_offset (vector, position->it), elements, element_length (vector, element_count)); + + // Overflow already checked. + vector->size += element_count; + + position->it = (uint32_t)insert_offset; + + return true; +} + +bool +_dn_vector_append_range ( + dn_vector_t *vector, + const uint8_t *elements, + uint32_t element_count) +{ + DN_ASSERT (vector && elements && element_count != 0); + + uint64_t new_capacity = (uint64_t)vector->size + (uint64_t)element_count; + if (DN_UNLIKELY (new_capacity > (uint64_t)(UINT32_MAX))) + return false; + + if (DN_UNLIKELY (!ensure_capacity (vector, (uint32_t)new_capacity))) + return false; + + /* ensure_capacity already verified element_offset and element_length won't overflow. */ + memmove (element_offset (vector, vector->size), elements, element_length (vector, element_count)); + + // Overflowed already checked. + vector->size += element_count; + + return true; +} + +bool +_dn_vector_erase ( + dn_vector_it_t *position, + dn_vector_dispose_func_t dispose_func) +{ + DN_ASSERT (position && !dn_vector_it_end (*position)); + + dn_vector_t *vector = position->_internal._vector; + + DN_ASSERT (vector && vector->size != 0); + + uint64_t insert_offset = (uint64_t)position->it + 1; + int64_t size_to_move = (int64_t)vector->size - (int64_t)position->it; + if (DN_UNLIKELY (insert_offset > vector->_internal._capacity || size_to_move < 0)) + return false; + + if (dispose_func) + dispose_func (element_offset (vector, position->it)); + + /* element_offset won't overflow since insert_offset and position is smaller than current capacity */ + /* element_length won't overflow since size_to_move is smaller than current capacity */ + /* element_length won't underflow since size_to_move is already verfied to be 0 or larger */ + memmove (element_offset (vector, position->it), element_offset (vector, (uint32_t)insert_offset), element_length (vector, (uint32_t)size_to_move)); + + vector->size --; + + if (!check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT)) + memset (element_offset(vector, vector->size), 0, element_length (vector, 1)); + + return true; +} + +bool +_dn_vector_erase_fast ( + dn_vector_it_t *position, + dn_vector_dispose_func_t dispose_func) +{ + DN_ASSERT (position && !dn_vector_it_end (*position)); + + dn_vector_t *vector = position->_internal._vector; + + DN_ASSERT (vector && vector->size != 0); + + if (dispose_func) + dispose_func (element_offset (vector, position->it)); + + /* element_offset won't overflow since position is smaller than current capacity */ + /* element_offset won't overflow since vector->size - 1 is smaller than current capacity */ + /* vector->size - 1 won't underflow since vector->size > 0 */ + memmove (element_offset (vector, position->it), element_offset (vector, vector->size - 1), element_length (vector, 1)); + + vector->size --; + + if (!check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT)) + memset (element_offset(vector, vector->size), 0, element_length (vector, 1)); + + return true; +} + +uint32_t +_dn_vector_buffer_capacity ( + size_t buffer_byte_size, + uint32_t element_size) +{ + // Estimate maximum array capacity for buffer size. + size_t max_capacity = (buffer_byte_size - DN_ALLOCATOR_ALIGN_SIZE (sizeof (dn_vector_t), DN_ALLOCATOR_MEM_ALIGN8) - 32 /* padding */) / element_size; + if (DN_UNLIKELY (max_capacity > buffer_byte_size || max_capacity > (size_t)UINT32_MAX)) + return 0; + + // Adjust to heuristics in ensure_capacity. + uint32_t capacity = 1; + while(CALC_NEW_CAPACITY (capacity) <= (uint32_t)max_capacity) + capacity <<= 1; + + return (uint32_t)(capacity >> 1); +} + +dn_vector_it_t +_dn_vector_custom_find ( + dn_vector_t *vector, + const uint8_t *value, + dn_vector_equal_func_t equal_func) +{ + DN_ASSERT (vector); + + dn_vector_it_t found = dn_vector_end (vector); + for (uint32_t i = 0; i < vector->size; i++) { + if ((equal_func && equal_func (element_offset (vector, i), value)) || (!equal_func && !memcmp (element_offset (vector, i), value, element_length (vector, 1)))) { + found.it = i; + break; + } + } + + return found; +} + +dn_vector_t * +dn_vector_custom_alloc ( + const dn_vector_custom_alloc_params_t *params, + uint32_t element_size) +{ + dn_allocator_t *allocator = params ? params->allocator : DN_DEFAULT_ALLOCATOR; + + dn_vector_t *vector = (dn_vector_t *)dn_allocator_alloc (allocator, sizeof (dn_vector_t)); + if (!dn_vector_custom_init (vector, params, element_size)) { + dn_allocator_free (allocator, vector); + return NULL; + } + + return vector; +} + +bool +dn_vector_custom_init ( + dn_vector_t *vector, + const dn_vector_custom_alloc_params_t *params, + uint32_t element_size) +{ + uint32_t capacity = INITIAL_CAPACITY; + + if (DN_UNLIKELY (!vector)) + return false; + + DN_ASSERT (element_size != 0); + + memset (vector, 0, sizeof(dn_vector_t)); + + vector->_internal._element_size = element_size; + + if (params) { + vector->_internal._allocator = params->allocator; + vector->_internal._attributes = params->attributes; + if (params->capacity != 0) + capacity = params->capacity; + } + + if (DN_UNLIKELY (!ensure_capacity (vector, capacity))) { + dn_vector_dispose (vector); + return false; + } + + return true; +} + +void +dn_vector_custom_free ( + dn_vector_t *vector, + dn_vector_dispose_func_t dispose_func) +{ + dn_vector_custom_dispose (vector, dispose_func); + dn_allocator_free (vector->_internal._allocator, vector); +} + +void +dn_vector_custom_dispose ( + dn_vector_t *vector, + dn_vector_dispose_func_t dispose_func) +{ + if (DN_UNLIKELY (!vector)) + return; + + if (dispose_func) { + for(uint32_t i = 0; i < vector->size; i++) + dispose_func ((element_offset (vector, i))); + } + + dn_allocator_free (vector->_internal._allocator, vector->data); +} + +bool +dn_vector_reserve ( + dn_vector_t *vector, + uint32_t capacity) +{ + DN_ASSERT (vector); + return ensure_capacity (vector, capacity); +} + +uint32_t +dn_vector_capacity (const dn_vector_t *vector) +{ + DN_ASSERT (vector); + return vector->_internal._capacity; +} + +bool +dn_vector_custom_resize ( + dn_vector_t *vector, + uint32_t size, + dn_vector_dispose_func_t dispose_func) +{ + DN_ASSERT (vector); + + if (size == vector->_internal._capacity) + return true; + + if (size > vector->_internal._capacity) + if (DN_UNLIKELY (!ensure_capacity (vector, size))) + return false; + + if (size < vector->size) { + if (dispose_func) { + for (uint32_t i = size; i < vector->size; i++) + dispose_func (element_offset (vector, i)); + } + + if (!check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT)) + memset (element_offset(vector, size), 0, element_length (vector, vector->size - size)); + + } + + vector->size = size; + return true; +} + +void +dn_vector_custom_pop_back ( + dn_vector_t* vector, + dn_vector_dispose_func_t dispose_func) +{ + DN_ASSERT (vector && vector->size != 0); + + vector->size --; + + if (dispose_func) + dispose_func (element_offset (vector, vector->size)); + + if (!check_attribute (vector, DN_VECTOR_ATTRIBUTE_DISABLE_MEMORY_INIT)) + memset (element_offset (vector, vector->size), 0, vector->_internal._element_size); +} + +void +dn_vector_for_each ( + const dn_vector_t *vector, + dn_vector_for_each_func_t for_each_func, + void *user_data) +{ + DN_ASSERT (vector && for_each_func); + + for(uint32_t i = 0; i < vector->size; i++) + for_each_func ((void *)(element_offset (vector, i)), user_data); +} + +void +dn_vector_sort ( + dn_vector_t *vector, + dn_vector_compare_func_t compare_func) +{ + DN_ASSERT (vector); + + if (DN_UNLIKELY (vector->size < 2)) + return; + + qsort ((void *)vector->data, vector->size, element_length (vector, 1), (int (DN_CALLBACK_CALLTYPE *)(const void *, const void *))compare_func); +} diff --git a/src/native/containers/dn-vector.h b/src/native/containers/dn-vector.h new file mode 100644 index 0000000..f08c5db --- /dev/null +++ b/src/native/containers/dn-vector.h @@ -0,0 +1,331 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_VECTOR_H__ +#define __DN_VECTOR_H__ + +#include "dn-utils.h" +#include "dn-allocator.h" +#include "dn-vector-types.h" +#include "dn-vector-priv.h" + +static inline dn_vector_it_t +dn_vector_begin (dn_vector_t *vector) +{ + DN_ASSERT (vector); + dn_vector_it_t it = { 0, { vector } }; + return it; +} + +static inline dn_vector_it_t +dn_vector_end (dn_vector_t *vector) +{ + DN_ASSERT (vector); + dn_vector_it_t it = { vector->size, { vector } }; + return it; +} + +static inline void +dn_vector_it_advance ( + dn_vector_it_t *it, + ptrdiff_t n) +{ + DN_ASSERT (it && ((it->it + n) < UINT32_MAX)); + it->it = it->it + (int32_t)n; +} + +static inline dn_vector_it_t +dn_vector_it_next (dn_vector_it_t it) +{ + DN_ASSERT ((it.it + 1) < UINT32_MAX); + it.it++; + return it; +} + +static inline dn_vector_it_t +dn_vector_it_prev (dn_vector_it_t it) +{ + DN_ASSERT (it.it > 0); + it.it--; + return it; +} + +static inline dn_vector_it_t +dn_vector_it_next_n ( + dn_vector_it_t it, + uint32_t n) +{ + DN_ASSERT ((it.it + n) < UINT32_MAX); + it.it += n; + return it; +} + +static inline dn_vector_it_t +dn_vector_it_prev_n ( + dn_vector_it_t it, + uint32_t n) +{ + DN_ASSERT (it.it >= n); + it.it -= n; + return it; +} + +static inline uint8_t * +dn_vector_it_data (dn_vector_it_t it) +{ + DN_ASSERT (it._internal._vector && it._internal._vector->data); + return it._internal._vector->data + (it._internal._vector->_internal._element_size * it.it); +} + +#define dn_vector_it_data_t(it, type) \ + (type *)dn_vector_it_data ((it)) + +static inline bool +dn_vector_it_begin (dn_vector_it_t it) +{ + DN_ASSERT (it._internal._vector); + return it.it == 0; +} + +static inline bool +dn_vector_it_end (dn_vector_it_t it) +{ + DN_ASSERT (it._internal._vector); + return it.it == it._internal._vector->size; +} + +#define DN_VECTOR_FOREACH_BEGIN(var_type, var_name, vector) do { \ + var_type var_name; \ + DN_ASSERT (sizeof (var_type) == (vector)->_internal._element_size); \ + for (uint32_t __i_ ## var_name = 0; __i_ ## var_name < (vector)->size; ++__i_ ## var_name) { \ + var_name = *dn_vector_index_t (vector, var_type, __i_##var_name); + +#define DN_VECTOR_FOREACH_RBEGIN(var_type, var_name, vector) do { \ + var_type var_name; \ + DN_ASSERT (sizeof (var_type) == (vector)->_internal._element_size); \ + for (uint32_t __i_ ## var_name = (vector)->size; __i_ ## var_name > 0; --__i_ ## var_name) { \ + var_name = *dn_vector_index_t (vector, var_type, __i_ ## var_name - 1); + +#define DN_VECTOR_FOREACH_END \ + } \ + } while (0) + +dn_vector_t * +dn_vector_custom_alloc ( + const dn_vector_custom_alloc_params_t *params, + uint32_t element_size); + +#define dn_vector_custom_alloc_t(params, element_type) \ + dn_vector_custom_alloc (params, sizeof (element_type)) + +static inline dn_vector_t * +dn_vector_alloc (uint32_t element_size) +{ + return dn_vector_custom_alloc (NULL, element_size); +} + +#define dn_vector_alloc_t(element_type) \ + dn_vector_alloc (sizeof (element_type)) + +void +dn_vector_custom_free ( + dn_vector_t *vector, + dn_vector_dispose_func_t dispose_func); + +static inline void +dn_vector_free (dn_vector_t *vector) +{ + dn_vector_custom_free (vector, NULL); +} + +bool +dn_vector_custom_init ( + dn_vector_t *vector, + const dn_vector_custom_alloc_params_t *params, + uint32_t element_size); + +#define dn_vector_custom_init_t(vector, params, element_type) \ + dn_vector_custom_init ((vector), (params), sizeof (element_type)) + +static inline bool +dn_vector_init ( + dn_vector_t *vector, + uint32_t element_size) +{ + return dn_vector_custom_init (vector, NULL, element_size); +} + +#define dn_vector_init_t(vector, element_type) \ + dn_vector_init (vector, sizeof (element_type)) + +void +dn_vector_custom_dispose ( + dn_vector_t *vector, + dn_vector_dispose_func_t dispose_func); + +static inline void +dn_vector_dispose (dn_vector_t *vector) +{ + dn_vector_custom_dispose (vector, NULL); +} + +static inline uint8_t * +dn_vector_index (dn_vector_t *vector, uint32_t size, uint32_t index) +{ + DN_ASSERT (vector && index < vector ->size); + return ((uint8_t *)(vector->data) + (size * index)); +} + +#define dn_vector_index_t(vector, type, index) \ + ((type*)(dn_vector_index ((vector), sizeof (type), (index)))) + +static inline uint8_t * +dn_vector_at (dn_vector_t *vector, uint32_t size, uint32_t index) +{ + DN_ASSERT (vector); + if (index >= vector->size) + return NULL; + return dn_vector_index (vector, size, index); +} + +#define dn_vector_at_t(vector, type, index) \ + ((type *)dn_vector_at(vector, sizeof (type), index)) + +#define dn_vector_front_t(vector, type) \ + dn_vector_index_t(vector, type, 0) + +#define dn_vector_back_t(vector, type) \ + dn_vector_index_t(vector, type, (vector)->size != 0 ? (vector)->size - 1 : 0) + +static inline uint8_t * +dn_vector_data (dn_vector_t *vector) +{ + DN_ASSERT (vector); + return vector->data; +} + +#define dn_vector_data_t(vector,type) \ + ((type *)dn_vector_data (vector)) + +static inline bool +dn_vector_empty (const dn_vector_t *vector) +{ + DN_ASSERT (vector); + return vector->size == 0; +} + +static inline uint32_t +dn_vector_size (const dn_vector_t *vector) +{ + DN_ASSERT (vector); + return vector->size; +} + +static inline uint32_t +dn_vector_max_size (const dn_vector_t *vector) +{ + DN_UNREFERENCED_PARAMETER (vector); + return UINT32_MAX; +} + +bool +dn_vector_reserve ( + dn_vector_t *vector, + uint32_t capacity); + +uint32_t +dn_vector_capacity (const dn_vector_t *vector); + +#define dn_vector_insert(position, element) \ + _dn_vector_insert_range_adapter ((position), (const uint8_t *)&(element), 1) + +#define dn_vector_insert_range(position, elements, element_count) \ + _dn_vector_insert_range_adapter ((position), (const uint8_t *)(elements), (element_count)) + +#define dn_vector_custom_erase(position, dispose_func) \ + _dn_vector_erase_adapter ((position), (dispose_func)) + +#define dn_vector_erase(position) \ + _dn_vector_erase_adapter ((position), NULL) + +#define dn_vector_custom_erase_fast(position, dispose_func) \ + _dn_vector_erase_fast_adapter ((position), (dispose_func)) + +#define dn_vector_erase_fast(position) \ + _dn_vector_erase_fast_adapter ((position), NULL) + +bool +dn_vector_custom_resize ( + dn_vector_t *vector, + uint32_t size, + dn_vector_dispose_func_t dispose_func); + +static inline bool +dn_vector_resize ( + dn_vector_t *vector, + uint32_t size) +{ + return dn_vector_custom_resize (vector, size, NULL); +} + +static inline void +dn_vector_custom_clear ( + dn_vector_t *vector, + dn_vector_dispose_func_t dispose_func) +{ + dn_vector_custom_resize (vector, 0, dispose_func); +} + +static inline void +dn_vector_clear (dn_vector_t *vector) +{ + dn_vector_resize (vector, 0); +} + +#define dn_vector_push_back(vector, element) \ + _dn_vector_append_range ((vector), (const uint8_t *)&(element), 1) + +void +dn_vector_custom_pop_back ( + dn_vector_t* vector, + dn_vector_dispose_func_t dispose_func); + +static inline void +dn_vector_pop_back (dn_vector_t *vector) +{ + dn_vector_custom_pop_back (vector, NULL); +} + +#define dn_vector_buffer_capacity_t(buffer_byte_size, type) \ + _dn_vector_buffer_capacity ((buffer_byte_size), sizeof (type)) + +void +dn_vector_for_each ( + const dn_vector_t *vector, + dn_vector_for_each_func_t for_each_func, + void *user_data); + +void +dn_vector_sort ( + dn_vector_t *vector, + dn_vector_compare_func_t compare_func); + +static inline dn_vector_it_t +dn_vector_custom_find ( + dn_vector_t *vector, + const uint8_t *value, + dn_vector_equal_func_t equal_func) +{ + return _dn_vector_custom_find (vector, value, equal_func); +} + +static inline dn_vector_it_t +dn_vector_find ( + dn_vector_t *vector, + const uint8_t *value, + dn_vector_equal_func_t equal_func) +{ + return dn_vector_custom_find (vector, value, equal_func); +} + +#endif /* __DN_VECTOR_H__ */ diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 8f28a00..75e4b3d 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -51,7 +51,7 @@ bool eventpipe_collect_tracing_command_try_parse_config ( uint8_t **buffer, uint32_t *buffer_len, - ep_rt_provider_config_array_t *result); + dn_vector_t **result); static uint8_t * @@ -148,7 +148,7 @@ bool eventpipe_collect_tracing_command_try_parse_config ( uint8_t **buffer, uint32_t *buffer_len, - ep_rt_provider_config_array_t *result) + dn_vector_t **result) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); @@ -166,10 +166,15 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_char8_t *provider_name_utf8 = NULL; ep_char8_t *filter_data_utf8 = NULL; + dn_vector_custom_alloc_params_t params = {0, }; + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &count_configs)); ep_raise_error_if_nok (count_configs <= max_count_configs); - ep_rt_provider_config_array_alloc_capacity (result, count_configs); + params.capacity = count_configs; + + *result = dn_vector_custom_alloc_t (¶ms, EventPipeProviderConfiguration); + ep_raise_error_if_nok (*result); for (uint32_t i = 0; i < count_configs; ++i) { uint64_t keywords = 0; @@ -204,7 +209,7 @@ eventpipe_collect_tracing_command_try_parse_config ( EventPipeProviderConfiguration provider_config; if (ep_provider_config_init (&provider_config, provider_name_utf8, keywords, (EventPipeEventLevel)log_level, filter_data_utf8)) { - if (ep_rt_provider_config_array_append (result, provider_config)) { + if (dn_vector_push_back (*result, provider_config)) { // Ownership transferred. provider_name_utf8 = NULL; filter_data_utf8 = NULL; @@ -268,12 +273,10 @@ ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingComman ep_return_void_if_nok (payload != NULL); ep_rt_byte_array_free (payload->incoming_buffer); - EventPipeProviderConfiguration *config = ep_rt_provider_config_array_data (&payload->provider_configs); - size_t config_len = ep_rt_provider_config_array_size (&payload->provider_configs); - for (size_t i = 0; i < config_len; ++i) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config [i])); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config [i])); - } + DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); + } DN_VECTOR_FOREACH_END; ep_rt_object_free (payload); } @@ -325,12 +328,10 @@ ds_eventpipe_collect_tracing2_command_payload_free (EventPipeCollectTracing2Comm ep_return_void_if_nok (payload != NULL); ep_rt_byte_array_free (payload->incoming_buffer); - EventPipeProviderConfiguration *config = ep_rt_provider_config_array_data (&payload->provider_configs); - size_t config_len = ep_rt_provider_config_array_size (&payload->provider_configs); - for (size_t i = 0; i < config_len; ++i) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config [i])); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config [i])); - } + DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); + } DN_VECTOR_FOREACH_END; ep_rt_object_free (payload); } @@ -432,8 +433,8 @@ eventpipe_protocol_helper_collect_tracing ( session_id = ep_enable ( NULL, payload->circular_buffer_size_in_mb, - ep_rt_provider_config_array_data (&payload->provider_configs), - (uint32_t)ep_rt_provider_config_array_size (&payload->provider_configs), + dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), + dn_vector_size (payload->provider_configs), EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, true, @@ -482,8 +483,8 @@ eventpipe_protocol_helper_collect_tracing_2 ( session_id = ep_enable ( NULL, payload->circular_buffer_size_in_mb, - ep_rt_provider_config_array_data (&payload->provider_configs), - (uint32_t)ep_rt_provider_config_array_size (&payload->provider_configs), + dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), + dn_vector_size (payload->provider_configs), EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, payload->rundown_requested, diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index 6698584..b8cbe95 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -33,7 +33,7 @@ struct _EventPipeCollectTracingCommandPayload_Internal { // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data uint8_t *incoming_buffer; - ep_rt_provider_config_array_t provider_configs; + dn_vector_t *provider_configs; uint32_t circular_buffer_size_in_mb; EventPipeSerializationFormat serialization_format; }; @@ -70,7 +70,7 @@ struct _EventPipeCollectTracing2CommandPayload_Internal { // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data uint8_t *incoming_buffer; - ep_rt_provider_config_array_t provider_configs; + dn_vector_t *provider_configs; uint32_t circular_buffer_size_in_mb; EventPipeSerializationFormat serialization_format; bool rundown_requested; diff --git a/src/native/eventpipe/ds-ipc.c b/src/native/eventpipe/ds-ipc.c index 0d87c3c..5ba83d3 100644 --- a/src/native/eventpipe/ds-ipc.c +++ b/src/native/eventpipe/ds-ipc.c @@ -15,7 +15,7 @@ */ static volatile uint32_t _ds_shutting_down_state = 0; -static ds_rt_port_array_t _ds_port_array = { 0 }; +static dn_vector_ptr_t *_ds_port_array = NULL; // set this in get_next_available_stream, and then expose a callback that // allows us to track which connections have sent their ResumeRuntime commands @@ -54,7 +54,7 @@ void ipc_stream_factory_split_port_config ( ep_char8_t *config, const ep_char8_t *delimiters, - ds_rt_port_config_array_t *config_array); + dn_vector_ptr_t *config_array); static bool @@ -65,7 +65,7 @@ ipc_stream_factory_build_and_add_port ( static void -ipc_log_poll_handles (ds_rt_ipc_poll_handle_array_t *ipc_poll_handles); +ipc_log_poll_handles (dn_vector_t *ipc_poll_handles); static void @@ -135,7 +135,7 @@ void ipc_stream_factory_split_port_config ( ep_char8_t *config, const ep_char8_t *delimiters, - ds_rt_port_config_array_t *config_array) + dn_vector_ptr_t *config_array) { ep_char8_t *part = NULL; ep_char8_t *context = NULL; @@ -147,7 +147,7 @@ ipc_stream_factory_split_port_config ( part = ep_rt_utf8_string_strtok (cursor, delimiters, &context); while (part) { - ds_rt_port_config_array_append (config_array, part); + dn_vector_ptr_push_back (config_array, part); part = ep_rt_utf8_string_strtok (NULL, delimiters, &context); } } @@ -178,7 +178,7 @@ ipc_stream_factory_build_and_add_port ( ipc = ds_ipc_alloc (builder->path, DS_IPC_CONNECTION_MODE_LISTEN, callback); ep_raise_error_if_nok (ipc != NULL); ep_raise_error_if_nok (ds_ipc_listen (ipc, callback)); - ep_raise_error_if_nok (ds_rt_port_array_append (&_ds_port_array, (DiagnosticsPort *)ds_listen_port_alloc (ipc, builder))); + ep_raise_error_if_nok (dn_vector_ptr_push_back (_ds_port_array, (DiagnosticsPort *)ds_listen_port_alloc (ipc, builder))); #else DS_LOG_INFO_0 ("ipc_stream_factory_build_and_add_port - LISTEN ports disabled"); ep_raise_error (); @@ -187,7 +187,7 @@ ipc_stream_factory_build_and_add_port ( #ifndef DS_IPC_DISABLE_CONNECT_PORTS ipc = ds_ipc_alloc (builder->path, DS_IPC_CONNECTION_MODE_CONNECT, callback); ep_raise_error_if_nok (ipc != NULL); - ep_raise_error_if_nok (ds_rt_port_array_append (&_ds_port_array, (DiagnosticsPort *)ds_connect_port_alloc (ipc, builder))); + ep_raise_error_if_nok (dn_vector_ptr_push_back (_ds_port_array, (DiagnosticsPort *)ds_connect_port_alloc (ipc, builder))); #else DS_LOG_INFO_0 ("ipc_stream_factory_build_and_add_port - CONNECT ports disabled"); ep_raise_error (); @@ -207,16 +207,15 @@ ep_on_error: static void -ipc_log_poll_handles (ds_rt_ipc_poll_handle_array_t *ipc_poll_handles) +ipc_log_poll_handles (dn_vector_t *ipc_poll_handles) { // TODO: Should this be debug only? - DiagnosticsIpcPollHandle ipc_poll_handle; ep_char8_t buffer [DS_IPC_MAX_TO_STRING_LEN]; uint32_t connection_id = 0; - ds_rt_ipc_poll_handle_array_iterator_t ipc_poll_handles_iterator = ds_rt_ipc_poll_handle_array_iterator_begin (ipc_poll_handles); - while (!ds_rt_ipc_poll_handle_array_iterator_end (ipc_poll_handles, &ipc_poll_handles_iterator)) { - ipc_poll_handle = ds_rt_ipc_poll_handle_array_iterator_value (&ipc_poll_handles_iterator); + EP_ASSERT (ipc_poll_handles != NULL); + + DN_VECTOR_FOREACH_BEGIN (DiagnosticsIpcPollHandle, ipc_poll_handle, ipc_poll_handles) { if (ipc_poll_handle.ipc) { if (!(ds_ipc_to_string (ipc_poll_handle.ipc, buffer, (uint32_t)ARRAY_SIZE (buffer)) > 0)) buffer [0] = '\0'; @@ -226,18 +225,16 @@ ipc_log_poll_handles (ds_rt_ipc_poll_handle_array_t *ipc_poll_handles) buffer [0] = '\0'; DS_LOG_DEBUG_2 ("\tCLIENT IpcPollHandle[%d] = %s", connection_id, buffer); } - ds_rt_ipc_poll_handle_array_iterator_next (&ipc_poll_handles_iterator); connection_id++; - } + } DN_VECTOR_FOREACH_END; } bool ds_ipc_stream_factory_init (void) { ep_ipc_stream_factory_callback_set (ds_ipc_stream_factory_any_suspended_ports); - - ds_rt_port_array_alloc (&_ds_port_array); - return ds_rt_port_array_is_valid (&_ds_port_array); + _ds_port_array = dn_vector_ptr_alloc (); + return _ds_port_array != NULL; } void @@ -246,13 +243,12 @@ ds_ipc_stream_factory_fini (void) // TODO: Race between server thread and shutdown, _ds_port_array and ports can not be freed without resolving // that race first. Diagnostic server thread is currently designed to not break waits on // shutdown unless clients activity wakes server thread. - /*ds_rt_port_array_iterator_t iterator = ds_rt_port_array_iterator_begin (&_ds_port_array); - while (!ds_rt_port_array_iterator_end (&_ds_port_array, &iterator)) { - ds_port_free_vcall (ds_rt_port_array_iterator_value (&iterator)); - ds_rt_port_array_iterator_next (&iterator); - } + /*DN_VECTOR_FOREACH_BEGIN (DiagnosticsPort *, port, _ds_port_array) { + ds_port_free_vcall (port); + } DN_PTR_ARRAY_EX_FOREACH_END; - ds_rt_port_array_free (&_ds_port_array);*/ + dn_vector_ptr_free (_ds_port_array); + _ds_port_array = NULL;*/ ep_ipc_stream_factory_callback_set (NULL); } @@ -264,35 +260,35 @@ ds_ipc_stream_factory_configure (ds_ipc_error_callback_func callback) ep_char8_t *ports = ds_rt_config_value_get_ports (); if (ports) { - DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY (port_configs); - DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY (port_config_parts); - ds_rt_port_config_array_init (&port_configs); - ds_rt_port_config_array_init (&port_config_parts); + DN_DEFAULT_LOCAL_ALLOCATOR (allocator, dn_vector_ptr_default_local_allocator_byte_size * 2); - if (ds_rt_port_config_array_is_valid (&port_configs) && ds_rt_port_config_array_is_valid (&port_config_parts)) { - ipc_stream_factory_split_port_config (ports, ";", &port_configs); - ds_rt_port_config_array_reverse_iterator_t port_configs_iterator = ds_rt_port_config_array_reverse_iterator_begin (&port_configs); - while (!ds_rt_port_config_array_reverse_iterator_end(&port_configs, &port_configs_iterator)) { - ep_char8_t *port_config = ds_rt_port_config_array_reverse_iterator_value (&port_configs_iterator); + dn_vector_ptr_custom_alloc_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_t *port_configs = dn_vector_ptr_custom_alloc (¶ms); + dn_vector_ptr_t *port_config_parts = dn_vector_ptr_custom_alloc (¶ms); + + if (port_configs && port_config_parts) { + ipc_stream_factory_split_port_config (ports, ";", port_configs); + DN_VECTOR_PTR_FOREACH_RBEGIN (ep_char8_t *, port_config, port_configs) { DS_LOG_INFO_1 ("ds_ipc_stream_factory_configure - Attempted to create Diagnostic Port from \"%s\".", port_config ? port_config : ""); if (port_config) { - ds_rt_port_config_array_clear (&port_config_parts); - ipc_stream_factory_split_port_config (port_config, ",", &port_config_parts); + dn_vector_ptr_clear (port_config_parts); + ipc_stream_factory_split_port_config (port_config, ",", port_config_parts); - size_t port_config_parts_index = ds_rt_port_config_array_size (&port_config_parts); + uint32_t port_config_parts_index = dn_vector_ptr_size (port_config_parts); if (port_config_parts_index != 0) { DiagnosticsPortBuilder port_builder; if (ds_port_builder_init (&port_builder)) { - ds_rt_port_config_array_reverse_iterator_t port_config_parts_iterator = ds_rt_port_config_array_reverse_iterator_begin (&port_config_parts); - while (!ds_rt_port_config_array_reverse_iterator_end(&port_config_parts, &port_config_parts_iterator)) { + DN_VECTOR_PTR_FOREACH_RBEGIN (ep_char8_t *, port_config_part, port_config_parts) { if (port_config_parts_index == 1) - port_builder.path = ds_rt_port_config_array_reverse_iterator_value (&port_config_parts_iterator); + port_builder.path = port_config_part; else - ds_port_builder_set_tag (&port_builder, ds_rt_port_config_array_reverse_iterator_value (&port_config_parts_iterator)); - ds_rt_port_config_array_reverse_iterator_next (&port_config_parts_iterator); + ds_port_builder_set_tag (&port_builder, port_config_part); port_config_parts_index--; - } + } DN_VECTOR_PTR_FOREACH_END; if (!ep_rt_utf8_string_is_null_or_empty (port_builder.path)) { const bool build_success = ipc_stream_factory_build_and_add_port (&port_builder, callback, false); DS_LOG_INFO_1 ("ds_ipc_stream_factory_configure - Diagnostic Port creation %s", build_success ? "succeeded" : "failed"); @@ -308,14 +304,13 @@ ds_ipc_stream_factory_configure (ds_ipc_error_callback_func callback) result &= false; } } - ds_rt_port_config_array_reverse_iterator_next (&port_configs_iterator); - } + } DN_VECTOR_PTR_FOREACH_END; } else { result &= false; } - ds_rt_port_config_array_fini (&port_config_parts); - ds_rt_port_config_array_fini (&port_configs); + dn_vector_ptr_free (port_config_parts); + dn_vector_ptr_free (port_configs); ep_rt_utf8_string_free (ports); } @@ -357,42 +352,37 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call DS_LOG_DEBUG_0 ("ds_ipc_stream_factory_get_next_available_stream - ENTER"); DiagnosticsIpcStream *stream = NULL; - DiagnosticsIpcPollHandle ipc_poll_handle; - ds_rt_port_array_t *ports = &_ds_port_array; - DiagnosticsPort *port = NULL; uint32_t poll_timeout_ms = DS_IPC_TIMEOUT_INFINITE; bool connect_success = true; uint32_t poll_attempts = 0; - DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY (ipc_poll_handles); + dn_vector_custom_alloc_params_t params = {0, }; + params.capacity = _ds_default_poll_handle_array_size; - ds_rt_ipc_poll_handle_array_init_capacity (&ipc_poll_handles, _ds_default_poll_handle_array_size); - ep_raise_error_if_nok (ds_rt_ipc_poll_handle_array_is_valid (&ipc_poll_handles)); + dn_vector_t ipc_poll_handles; + ep_raise_error_if_nok (dn_vector_custom_init_t (&ipc_poll_handles, ¶ms, DiagnosticsIpcPollHandle)); while (!stream) { connect_success = true; - ds_rt_port_array_iterator_t ports_iterator = ds_rt_port_array_iterator_begin (ports); - while (!ds_rt_port_array_iterator_end (ports, &ports_iterator)) { - port = ds_rt_port_array_iterator_value (&ports_iterator); + DN_VECTOR_PTR_FOREACH_BEGIN (DiagnosticsPort *, port, _ds_port_array) { + DiagnosticsIpcPollHandle ipc_poll_handle; if (ds_port_get_ipc_poll_handle_vcall (port, &ipc_poll_handle, callback)) - ep_raise_error_if_nok (ds_rt_ipc_poll_handle_array_append (&ipc_poll_handles, ipc_poll_handle)); + ep_raise_error_if_nok (dn_vector_push_back (&ipc_poll_handles, ipc_poll_handle)); else connect_success = false; - - ds_rt_port_array_iterator_next (&ports_iterator); - } + } DN_VECTOR_PTR_FOREACH_END; poll_timeout_ms = connect_success ? DS_IPC_TIMEOUT_INFINITE : ipc_stream_factory_get_next_timeout (poll_timeout_ms); int32_t ret_val; - if ( ds_rt_ipc_poll_handle_array_size (&ipc_poll_handles) > 0) { + if (dn_vector_size (&ipc_poll_handles) > 0) { poll_attempts++; DS_LOG_DEBUG_2 ("ds_ipc_stream_factory_get_next_available_stream - Poll attempt: %d, timeout: %dms.", poll_attempts, poll_timeout_ms); ipc_log_poll_handles (&ipc_poll_handles); - ret_val = ds_ipc_poll (ds_rt_ipc_poll_handle_array_data (&ipc_poll_handles), ds_rt_ipc_poll_handle_array_size (&ipc_poll_handles), poll_timeout_ms, callback); + ret_val = ds_ipc_poll (dn_vector_data_t (&ipc_poll_handles, DiagnosticsIpcPollHandle), dn_vector_size (&ipc_poll_handles), poll_timeout_ms, callback); } else { if (poll_timeout_ms == DS_IPC_TIMEOUT_INFINITE) poll_timeout_ms = DS_IPC_POLL_TIMEOUT_MAX_MS; @@ -405,10 +395,8 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call if (ret_val != 0) { uint32_t connection_id = 0; - ds_rt_ipc_poll_handle_array_iterator_t ipc_poll_handles_iterator = ds_rt_ipc_poll_handle_array_iterator_begin (&ipc_poll_handles); - while (!ds_rt_ipc_poll_handle_array_iterator_end (&ipc_poll_handles, &ipc_poll_handles_iterator)) { - ipc_poll_handle = ds_rt_ipc_poll_handle_array_iterator_value (&ipc_poll_handles_iterator); - port = (DiagnosticsPort *)ipc_poll_handle.user_data; + DN_VECTOR_FOREACH_BEGIN (DiagnosticsIpcPollHandle, ipc_poll_handle, &ipc_poll_handles) { + DiagnosticsPort *port = (DiagnosticsPort *)ipc_poll_handle.user_data; switch (ipc_poll_handle.events) { case DS_IPC_POLL_EVENTS_HANGUP: EP_ASSERT (port != NULL); @@ -440,9 +428,8 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call break; } - ds_rt_ipc_poll_handle_array_iterator_next (&ipc_poll_handles_iterator); connection_id++; - } + } DN_VECTOR_FOREACH_END; } if (!stream && saw_error) { @@ -451,12 +438,12 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call } // clear the view. - ds_rt_ipc_poll_handle_array_clear (&ipc_poll_handles); + dn_vector_clear (&ipc_poll_handles); } ep_on_exit: DS_LOG_DEBUG_2 ("ds_ipc_stream_factory_get_next_available_stream - EXIT :: Poll attempt: %d, stream using handle %d.", poll_attempts, stream ? ds_ipc_stream_get_handle_int32_t (stream) : -1); - ds_rt_ipc_poll_handle_array_fini (&ipc_poll_handles); + dn_vector_dispose (&ipc_poll_handles); return stream; ep_on_error: @@ -475,12 +462,10 @@ bool ds_ipc_stream_factory_any_suspended_ports (void) { bool any_suspended_ports = false; - ds_rt_port_array_iterator_t iterator = ds_rt_port_array_iterator_begin (&_ds_port_array); - while (!ds_rt_port_array_iterator_end (&_ds_port_array, &iterator)) { - DiagnosticsPort *port = ds_rt_port_array_iterator_value (&iterator); + DN_VECTOR_PTR_FOREACH_BEGIN (DiagnosticsPort *, port, _ds_port_array) { any_suspended_ports |= !(port->suspend_mode == DS_PORT_SUSPEND_MODE_NOSUSPEND || port->has_resumed_runtime); - ds_rt_port_array_iterator_next (&iterator); - } + } DN_VECTOR_PTR_FOREACH_END; + return any_suspended_ports; } @@ -488,17 +473,15 @@ bool ds_ipc_stream_factory_has_active_ports (void) { return !load_shutting_down_state () && - ds_rt_port_array_size (&_ds_port_array) > 0; + dn_vector_ptr_size (_ds_port_array) > 0; } void ds_ipc_stream_factory_close_ports (ds_ipc_error_callback_func callback) { - ds_rt_port_array_iterator_t iterator = ds_rt_port_array_iterator_begin (&_ds_port_array); - while (!ds_rt_port_array_iterator_end (&_ds_port_array, &iterator)) { - ds_port_close (ds_rt_port_array_iterator_value (&iterator), false, callback); - ds_rt_port_array_iterator_next (&iterator); - } + DN_VECTOR_PTR_FOREACH_BEGIN (DiagnosticsPort *, port, _ds_port_array) { + ds_port_close (port, false, callback); + } DN_VECTOR_PTR_FOREACH_END; } bool @@ -509,11 +492,9 @@ ds_ipc_stream_factory_shutdown (ds_ipc_error_callback_func callback) store_shutting_down_state (true); - ds_rt_port_array_iterator_t iterator = ds_rt_port_array_iterator_begin (&_ds_port_array); - while (!ds_rt_port_array_iterator_end (&_ds_port_array, &iterator)) { - ds_port_close (ds_rt_port_array_iterator_value (&iterator), true, callback); - ds_rt_port_array_iterator_next (&iterator); - } + DN_VECTOR_PTR_FOREACH_BEGIN (DiagnosticsPort *, port, _ds_port_array) { + ds_port_close (port, true, callback); + } DN_VECTOR_PTR_FOREACH_END; _ds_current_port = NULL; return true; diff --git a/src/native/eventpipe/ds-process-protocol.c b/src/native/eventpipe/ds-process-protocol.c index e7cc72d..c395743 100644 --- a/src/native/eventpipe/ds-process-protocol.c +++ b/src/native/eventpipe/ds-process-protocol.c @@ -361,13 +361,11 @@ env_info_env_block_get_size (DiagnosticsEnvironmentInfoPayload *payload) size_t size = 0; size += sizeof (uint32_t); - size += (sizeof (uint32_t) * ep_rt_env_array_utf16_size (&payload->env_array)); + size += (sizeof (uint32_t) * dn_vector_ptr_size (payload->env_array)); - ep_rt_env_array_utf16_iterator_t iterator = ep_rt_env_array_utf16_iterator_begin (&payload->env_array); - while (!ep_rt_env_array_utf16_iterator_end (&payload->env_array, &iterator)) { - size += ((ep_rt_utf16_string_len (ep_rt_env_array_utf16_iterator_value (&iterator)) + 1) * sizeof (ep_char16_t)); - ep_rt_env_array_utf16_iterator_next (&iterator); - } + DN_VECTOR_PTR_FOREACH_BEGIN (ep_char16_t *, env_value, payload->env_array) { + size += ((ep_rt_utf16_string_len (env_value) + 1) * sizeof (ep_char16_t)); + } DN_VECTOR_PTR_FOREACH_END; EP_ASSERT (size <= UINT32_MAX); return (uint32_t)size; @@ -427,15 +425,13 @@ env_info_stream_env_block ( uint32_t bytes_written = 0; // Array> - uint32_t env_len = (uint32_t)ep_rt_env_array_utf16_size (&env_info->env_array); + uint32_t env_len = dn_vector_ptr_size (env_info->env_array); env_len = ep_rt_val_uint32_t (env_len); success &= ds_ipc_stream_write (stream, (const uint8_t *)&env_len, sizeof (env_len), &bytes_written, EP_INFINITE_WAIT); - ep_rt_env_array_utf16_iterator_t iterator = ep_rt_env_array_utf16_iterator_begin (&env_info->env_array); - while (!ep_rt_env_array_utf16_iterator_end (&env_info->env_array, &iterator)) { - success &= ds_ipc_message_try_write_string_utf16_t_to_stream (stream, ep_rt_env_array_utf16_iterator_value (&iterator)); - ep_rt_env_array_utf16_iterator_next (&iterator); - } + DN_VECTOR_PTR_FOREACH_BEGIN (ep_char16_t *, env_value, env_info->env_array) { + success &= ds_ipc_message_try_write_string_utf16_t_to_stream (stream, env_value); + } DN_VECTOR_PTR_FOREACH_END; return success; } @@ -445,8 +441,10 @@ ds_env_info_payload_init (DiagnosticsEnvironmentInfoPayload *payload) { ep_return_null_if_nok (payload != NULL); - ep_rt_env_array_utf16_alloc (&payload->env_array); - ep_rt_os_environment_get_utf16 (&payload->env_array); + payload->env_array = dn_vector_ptr_alloc (); + ep_return_null_if_nok (payload->env_array); + + ep_rt_os_environment_get_utf16 (payload->env_array); payload->incoming_bytes = env_info_env_block_get_size (payload); payload->future = 0; @@ -457,13 +455,12 @@ ds_env_info_payload_init (DiagnosticsEnvironmentInfoPayload *payload) void ds_env_info_payload_fini (DiagnosticsEnvironmentInfoPayload *payload) { - ep_rt_env_array_utf16_iterator_t iterator = ep_rt_env_array_utf16_iterator_begin (&payload->env_array); - while (!ep_rt_env_array_utf16_iterator_end (&payload->env_array, &iterator)) { - ep_rt_utf16_string_free (ep_rt_env_array_utf16_iterator_value (&iterator)); - ep_rt_env_array_utf16_iterator_next (&iterator); - } + DN_VECTOR_PTR_FOREACH_BEGIN (ep_char16_t *, env_value, payload->env_array) { + ep_rt_utf16_string_free (env_value); + } DN_VECTOR_PTR_FOREACH_END; - ep_rt_env_array_utf16_free (&payload->env_array); + dn_vector_ptr_free (payload->env_array); + payload->env_array = NULL; } /* @@ -720,8 +717,8 @@ process_protocol_helper_set_environment_variable ( if (!stream) return false; - bool result = false; - DiagnosticsSetEnvironmentVariablePayload *payload = (DiagnosticsSetEnvironmentVariablePayload *)ds_ipc_message_try_parse_payload (message, set_environment_variable_command_try_parse_payload); + bool result = false; + DiagnosticsSetEnvironmentVariablePayload *payload = (DiagnosticsSetEnvironmentVariablePayload *)ds_ipc_message_try_parse_payload (message, set_environment_variable_command_try_parse_payload); if (!payload) { ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING); ep_raise_error (); @@ -740,7 +737,7 @@ process_protocol_helper_set_environment_variable ( ep_on_exit: ds_set_environment_variable_payload_free (payload); - ds_ipc_stream_free (stream); + ds_ipc_stream_free (stream); return result; ep_on_error: @@ -782,7 +779,7 @@ ds_process_protocol_helper_handle_ipc_message ( break; case DS_PROCESS_COMMANDID_SET_ENV_VAR: result = process_protocol_helper_set_environment_variable (message, stream); - break; + break; case DS_PROCESS_COMMANDID_GET_PROCESS_INFO_2: result = process_protocol_helper_get_process_info_2 (message, stream); break; diff --git a/src/native/eventpipe/ds-process-protocol.h b/src/native/eventpipe/ds-process-protocol.h index d159dbb..db43e7f 100644 --- a/src/native/eventpipe/ds-process-protocol.h +++ b/src/native/eventpipe/ds-process-protocol.h @@ -122,7 +122,7 @@ struct _DiagnosticsEnvironmentInfoPayload_Internal { // the Diagnostics IPC Spec: https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md uint32_t incoming_bytes; uint16_t future; - ep_rt_env_array_utf16_t env_array; + dn_vector_ptr_t *env_array; }; #if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_PROCESS_PROTOCOL_GETTER_SETTER) diff --git a/src/native/eventpipe/ds-rt-types.h b/src/native/eventpipe/ds-rt-types.h index 9eae292..31b9a4f 100644 --- a/src/native/eventpipe/ds-rt-types.h +++ b/src/native/eventpipe/ds-rt-types.h @@ -3,24 +3,6 @@ #ifdef ENABLE_PERFTRACING -/* - * DiagnosticsIpcPollHandle. - */ - -#define ds_rt_ipc_poll_handle_array_t ds_rt_redefine -#define ds_rt_ipc_poll_handle_array_iterator_t ds_rt_redefine - -/* - * DiagnosticsPort. - */ - -#define ds_rt_port_array_t ds_rt_redefine -#define ds_rt_port_array_iterator_t ds_rt_redefine - -#define ds_rt_port_config_array_t ds_rt_redefine -#define ds_rt_port_config_array_iterator_t ds_rt_redefine -#define ds_rt_port_config_array_reverse_iterator_t ds_rt_redefine - #ifndef EP_NO_RT_DEPENDENCY #include DS_RT_TYPES_H #endif diff --git a/src/native/eventpipe/ds-rt.h b/src/native/eventpipe/ds-rt.h index d2e96ff..ad30346 100644 --- a/src/native/eventpipe/ds-rt.h +++ b/src/native/eventpipe/ds-rt.h @@ -25,26 +25,6 @@ #define DS_ENTER_BLOCKING_PAL_SECTION ds_rt_redefine #define DS_EXIT_BLOCKING_PAL_SECTION ds_rt_redefine -#define DS_RT_DECLARE_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DECLARE_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#define DS_RT_DEFINE_ARRAY ds_rt_redefine - -#define DS_RT_DECLARE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DECLARE_LOCAL_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#define DS_RT_DEFINE_LOCAL_ARRAY ds_rt_redefine - -#define DS_RT_DECLARE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DECLARE_ARRAY_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#define DS_RT_DEFINE_ARRAY_ITERATOR ds_rt_redefine - -#define DS_RT_DECLARE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DECLARE_ARRAY_REVERSE_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type) - -#define DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR ds_rt_redefine - /* * AutoTrace. */ @@ -104,30 +84,6 @@ ds_rt_transport_get_default_name ( const ep_char8_t *suffix); /* - * DiagnosticsIpcPollHandle. - */ - -DS_RT_DECLARE_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) -DS_RT_DECLARE_LOCAL_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) -DS_RT_DECLARE_ARRAY_ITERATOR (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle) - -#define DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY(var_name) ds_rt_redefine - -/* - * DiagnosticsPort. - */ - -DS_RT_DECLARE_ARRAY (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *) -DS_RT_DECLARE_ARRAY_ITERATOR (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *) - -DS_RT_DECLARE_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DECLARE_LOCAL_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DECLARE_ARRAY_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *) -DS_RT_DECLARE_ARRAY_REVERSE_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_reverse_iterator_t, ep_char8_t *) - -#define DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY(var_name) ds_rt_redefine - -/* * DiagnosticsProfiler. */ diff --git a/src/native/eventpipe/ep-block.c b/src/native/eventpipe/ep-block.c index bda7d9a..1d7d707 100644 --- a/src/native/eventpipe/ep-block.c +++ b/src/native/eventpipe/ep-block.c @@ -4,6 +4,7 @@ #if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) #define EP_IMPL_BLOCK_GETTER_SETTER +#include "ep.h" #include "ep-block.h" #include "ep-event-instance.h" #include "ep-file.h" @@ -828,7 +829,7 @@ sequence_point_get_block_size (EventPipeSequencePoint *sequence_point) sizeof (uint64_t) + //thread id sizeof (uint32_t); //sequence number - const uint32_t thread_count = ep_rt_thread_sequence_number_map_count (ep_sequence_point_get_thread_sequence_numbers_cref (sequence_point)); + const uint32_t thread_count = dn_umap_size (ep_sequence_point_get_thread_sequence_numbers (sequence_point)); return (int32_t)(ep_sequence_point_sizeof_timestamp (sequence_point) + sizeof (uint32_t) + //thread count @@ -897,24 +898,23 @@ ep_sequence_point_block_init ( sequence_point_get_block_size (sequence_point), EP_SERIALIZATION_FORMAT_NETTRACE_V4) != NULL); + dn_umap_t *map = ep_sequence_point_get_thread_sequence_numbers (sequence_point); + const ep_timestamp_t timestamp = ep_sequence_point_get_timestamp (sequence_point); ep_write_buffer_timestamp (&sequence_point_block->block.write_pointer, timestamp); - const uint32_t thread_count = ep_rt_thread_sequence_number_map_count (ep_sequence_point_get_thread_sequence_numbers_cref (sequence_point)); + const uint32_t thread_count = dn_umap_size (map); ep_write_buffer_uint32_t (&sequence_point_block->block.write_pointer, thread_count); - for (ep_rt_thread_sequence_number_hash_map_iterator_t iterator = ep_rt_thread_sequence_number_map_iterator_begin (ep_sequence_point_get_thread_sequence_numbers_cref (sequence_point)); - !ep_rt_thread_sequence_number_map_iterator_end (ep_sequence_point_get_thread_sequence_numbers_cref (sequence_point), &iterator); - ep_rt_thread_sequence_number_map_iterator_next (&iterator)) { - - const EventPipeThreadSessionState *key = ep_rt_thread_sequence_number_map_iterator_key (&iterator); + DN_UMAP_FOREACH_BEGIN (const EventPipeThreadSessionState *, key, uint32_t, sequence_number, map) { + ep_write_buffer_uint64_t ( + &sequence_point_block->block.write_pointer, + ep_thread_get_os_thread_id (ep_thread_session_state_get_thread (key))); - const uint64_t thread_id = ep_thread_get_os_thread_id (ep_thread_session_state_get_thread (key)); - ep_write_buffer_uint64_t (&sequence_point_block->block.write_pointer, thread_id); - - const uint32_t sequence_number = ep_rt_thread_sequence_number_map_iterator_value (&iterator); - ep_write_buffer_uint32_t (&sequence_point_block->block.write_pointer, sequence_number); - } + ep_write_buffer_uint32_t ( + &sequence_point_block->block.write_pointer, + sequence_number); + } DN_UMAP_FOREACH_END; return sequence_point_block; } diff --git a/src/native/eventpipe/ep-buffer-manager.c b/src/native/eventpipe/ep-buffer-manager.c index 5b54da1..1c9a1ef 100644 --- a/src/native/eventpipe/ep-buffer-manager.c +++ b/src/native/eventpipe/ep-buffer-manager.c @@ -374,7 +374,7 @@ buffer_manager_enqueue_sequence_point ( ep_buffer_manager_requires_lock_held (buffer_manager); - return ep_rt_sequence_point_list_append (&buffer_manager->sequence_points, sequence_point); + return dn_list_push_back (buffer_manager->sequence_points, sequence_point); } static @@ -388,11 +388,7 @@ buffer_manager_init_sequence_point_thread_list ( ep_buffer_manager_requires_lock_held (buffer_manager); - ep_rt_thread_session_state_list_iterator_t iterator = ep_rt_thread_session_state_list_iterator_begin (&buffer_manager->thread_session_state_list); - while (!ep_rt_thread_session_state_list_iterator_end (&buffer_manager->thread_session_state_list, &iterator)) { - - EventPipeThreadSessionState *thread_session_state = ep_rt_thread_session_state_list_iterator_value (&iterator); - + DN_LIST_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, buffer_manager->thread_session_state_list) { // The sequence number captured here is not guaranteed to be the most recent sequence number, nor // is it guaranteed to match the number of events we would observe in the thread's write buffer // memory. This is only used as a lower bound on the number of events the thread has attempted to @@ -403,11 +399,9 @@ buffer_manager_init_sequence_point_thread_list ( // underflow. uint32_t sequence_number = ep_thread_session_state_get_volatile_sequence_number (thread_session_state) - 1; - ep_rt_thread_sequence_number_map_add (ep_sequence_point_get_thread_sequence_numbers_ref (sequence_point), thread_session_state, sequence_number); + dn_umap_ptr_uint32_insert (ep_sequence_point_get_thread_sequence_numbers (sequence_point), thread_session_state, sequence_number); ep_thread_addref (ep_thread_holder_get_thread (ep_thread_session_state_get_thread_holder_ref (thread_session_state))); - - ep_rt_thread_session_state_list_iterator_next (&iterator); - } + } DN_LIST_FOREACH_END; // This needs to come after querying the thread sequence numbers to ensure that any recorded // sequence number is <= the actual sequence number at this timestamp @@ -423,12 +417,10 @@ buffer_manager_dequeue_sequence_point (EventPipeBufferManager *buffer_manager) ep_buffer_manager_requires_lock_held (buffer_manager); - ep_return_void_if_nok (!ep_rt_sequence_point_list_is_empty (&buffer_manager->sequence_points)); - - ep_rt_sequence_point_list_iterator_t iterator = ep_rt_sequence_point_list_iterator_begin (&buffer_manager->sequence_points); + ep_return_void_if_nok (!dn_list_empty (buffer_manager->sequence_points)); - EventPipeSequencePoint *value = ep_rt_sequence_point_list_iterator_value (&iterator); - ep_rt_sequence_point_list_remove (&buffer_manager->sequence_points, value); + EventPipeSequencePoint *value = *dn_list_front_t (buffer_manager->sequence_points, EventPipeSequencePoint *); + dn_list_pop_front (buffer_manager->sequence_points); ep_sequence_point_free (value); } @@ -444,11 +436,9 @@ buffer_manager_try_peek_sequence_point ( ep_buffer_manager_requires_lock_held (buffer_manager); - ep_return_false_if_nok (!ep_rt_sequence_point_list_is_empty (&buffer_manager->sequence_points)); - - ep_rt_sequence_point_list_iterator_t iterator = ep_rt_sequence_point_list_iterator_begin (&buffer_manager->sequence_points); + ep_return_false_if_nok (!dn_list_empty (buffer_manager->sequence_points)); - *sequence_point = ep_rt_sequence_point_list_iterator_value (&iterator); + *sequence_point = *dn_list_front_t (buffer_manager->sequence_points, EventPipeSequencePoint *); return *sequence_point != NULL; } @@ -513,7 +503,7 @@ buffer_manager_allocate_buffer_for_thread ( thread_buffer_list = ep_buffer_list_alloc (buffer_manager, ep_thread_session_state_get_thread (thread_session_state)); ep_raise_error_if_nok_holding_spin_lock (thread_buffer_list != NULL, section1); - ep_raise_error_if_nok_holding_spin_lock (ep_rt_thread_session_state_list_append (&buffer_manager->thread_session_state_list, thread_session_state), section1); + ep_raise_error_if_nok_holding_spin_lock (dn_list_push_back (buffer_manager->thread_session_state_list, thread_session_state), section1); ep_thread_session_state_set_buffer_list (thread_session_state, thread_buffer_list); thread_buffer_list = NULL; } @@ -599,24 +589,29 @@ buffer_manager_move_next_event_any_thread ( // at the same time. // Step 1 - while holding m_lock get the oldest buffer from each thread - EP_RT_DECLARE_LOCAL_BUFFER_ARRAY (buffer_array); - EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY (buffer_list_array); - ep_rt_buffer_array_init (&buffer_array); - ep_rt_buffer_list_array_init (&buffer_list_array); + DN_DEFAULT_LOCAL_ALLOCATOR (allocator, dn_vector_ptr_default_local_allocator_byte_size * 2); + + dn_vector_ptr_t buffer_array; + dn_vector_ptr_t buffer_list_array; + + dn_vector_ptr_custom_init_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + ep_raise_error_if_nok (dn_vector_ptr_custom_init (&buffer_array, ¶ms)); + ep_raise_error_if_nok (dn_vector_ptr_custom_init (&buffer_list_array, ¶ms)); EP_SPIN_LOCK_ENTER (&buffer_manager->rt_lock, section1) EventPipeBufferList *buffer_list; EventPipeBuffer *buffer; - ep_rt_thread_session_state_list_iterator_t iterator = ep_rt_thread_session_state_list_iterator_begin (&buffer_manager->thread_session_state_list); - while (!ep_rt_thread_session_state_list_iterator_end (&buffer_manager->thread_session_state_list, &iterator)) { - buffer_list = ep_thread_session_state_get_buffer_list (ep_rt_thread_session_state_list_iterator_value (&iterator)); + DN_LIST_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, buffer_manager->thread_session_state_list) { + buffer_list = ep_thread_session_state_get_buffer_list (thread_session_state); buffer = buffer_list->head_buffer; if (buffer && ep_buffer_get_creation_timestamp (buffer) < stop_timestamp) { - ep_rt_buffer_list_array_append (&buffer_list_array, buffer_list); - ep_rt_buffer_array_append (&buffer_array, buffer); + dn_vector_ptr_push_back (&buffer_list_array, buffer_list); + dn_vector_ptr_push_back (&buffer_array, buffer); } - ep_rt_thread_session_state_list_iterator_next (&iterator); - } + } DN_LIST_FOREACH_END; EP_SPIN_LOCK_EXIT (&buffer_manager->rt_lock, section1) // Step 2 - iterate the cached list to find the one with the oldest event. This may require @@ -630,16 +625,9 @@ buffer_manager_move_next_event_any_thread ( EventPipeBuffer *buffer; EventPipeEventInstance *next_event; - ep_rt_buffer_list_array_iterator_t buffer_list_array_iterator; - buffer_list_array_iterator = ep_rt_buffer_list_array_iterator_begin (&buffer_list_array); - - ep_rt_buffer_array_iterator_t buffer_array_iterator; - buffer_array_iterator = ep_rt_buffer_array_iterator_begin (&buffer_array); - - while (!ep_rt_buffer_array_iterator_end (&buffer_array, &buffer_array_iterator) && !ep_rt_buffer_list_array_iterator_end (&buffer_list_array, &buffer_list_array_iterator)) { - - buffer_list = ep_rt_buffer_list_array_iterator_value (&buffer_list_array_iterator); - head_buffer = ep_rt_buffer_array_iterator_value (&buffer_array_iterator); + for (uint32_t i = 0; i < dn_vector_ptr_size (&buffer_array) && i < dn_vector_ptr_size (&buffer_list_array); ++i) { + buffer_list = (EventPipeBufferList *)*dn_vector_ptr_index (&buffer_list_array, i); + head_buffer = (EventPipeBuffer *)*dn_vector_ptr_index (&buffer_array, i); buffer = buffer_manager_advance_to_non_empty_buffer (buffer_manager, buffer_list, head_buffer, stop_timestamp); if (buffer) { // Peek the next event out of the buffer. @@ -652,15 +640,12 @@ buffer_manager_move_next_event_any_thread ( oldest_timestamp = ep_event_instance_get_timestamp (buffer_manager->current_event); } } - - ep_rt_buffer_list_array_iterator_next (&buffer_list_array_iterator); - ep_rt_buffer_array_iterator_next (&buffer_array_iterator); } ep_on_exit: ep_buffer_manager_requires_lock_not_held (buffer_manager); - ep_rt_buffer_list_array_fini (&buffer_list_array); - ep_rt_buffer_array_fini (&buffer_array); + dn_vector_ptr_dispose (&buffer_list_array); + dn_vector_ptr_dispose (&buffer_array); return; ep_on_error: @@ -825,11 +810,11 @@ ep_buffer_manager_alloc ( EventPipeBufferManager *instance = ep_rt_object_alloc (EventPipeBufferManager); ep_raise_error_if_nok (instance != NULL); - ep_rt_thread_session_state_list_alloc (&instance->thread_session_state_list); - ep_raise_error_if_nok (ep_rt_thread_session_state_list_is_valid (&instance->thread_session_state_list)); + instance->thread_session_state_list = dn_list_alloc (); + ep_raise_error_if_nok (instance->thread_session_state_list != NULL); - ep_rt_sequence_point_list_alloc (&instance->sequence_points); - ep_raise_error_if_nok (ep_rt_sequence_point_list_is_valid (&instance->sequence_points)); + instance->sequence_points = dn_list_alloc (); + ep_raise_error_if_nok (instance->sequence_points != NULL); ep_rt_spin_lock_alloc (&instance->rt_lock); ep_raise_error_if_nok (ep_rt_spin_lock_is_valid (&instance->rt_lock)); @@ -881,6 +866,10 @@ ep_buffer_manager_free (EventPipeBufferManager * buffer_manager) ep_buffer_manager_deallocate_buffers (buffer_manager); + dn_list_free (buffer_manager->sequence_points); + + dn_list_free (buffer_manager->thread_session_state_list); + ep_rt_wait_event_free (&buffer_manager->rt_wait_event); ep_rt_spin_lock_free (&buffer_manager->rt_lock); @@ -1068,37 +1057,35 @@ ep_buffer_manager_suspend_write_event ( // All calls to this method must be synchronized by our caller ep_requires_lock_held (); - EP_RT_DECLARE_LOCAL_THREAD_ARRAY (thread_array); - ep_rt_thread_array_init (&thread_array); + DN_DEFAULT_LOCAL_ALLOCATOR (allocator, dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_init_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_t thread_vector; + ep_raise_error_if_nok (dn_vector_ptr_custom_init (&thread_vector, ¶ms)); EP_SPIN_LOCK_ENTER (&buffer_manager->rt_lock, section1); EP_ASSERT (ep_buffer_manager_ensure_consistency (buffer_manager)); // Find all threads that have used this buffer manager. - ep_rt_thread_session_state_list_iterator_t thread_session_state_list_iterator = ep_rt_thread_session_state_list_iterator_begin (&buffer_manager->thread_session_state_list); - while (!ep_rt_thread_session_state_list_iterator_end (&buffer_manager->thread_session_state_list, &thread_session_state_list_iterator)) { - EventPipeThread *thread = ep_thread_session_state_get_thread (ep_rt_thread_session_state_list_iterator_value (&thread_session_state_list_iterator)); - ep_rt_thread_array_append (&thread_array, thread); - ep_rt_thread_session_state_list_iterator_next (&thread_session_state_list_iterator); - } + DN_LIST_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, buffer_manager->thread_session_state_list) { + dn_vector_ptr_push_back (&thread_vector, ep_thread_session_state_get_thread (thread_session_state)); + } DN_LIST_FOREACH_END; EP_SPIN_LOCK_EXIT (&buffer_manager->rt_lock, section1); // Iterate through all the threads, forcing them to relinquish any buffers stored in // EventPipeThread's write buffer and prevent storing new ones. - ep_rt_thread_array_iterator_t thread_array_iterator; - thread_array_iterator = ep_rt_thread_array_iterator_begin (&thread_array); - - while (!ep_rt_thread_array_iterator_end (&thread_array, &thread_array_iterator)) { - EventPipeThread *thread = ep_rt_thread_array_iterator_value (&thread_array_iterator); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeThread *, thread, &thread_vector) { EP_SPIN_LOCK_ENTER (ep_thread_get_rt_lock_ref (thread), section2) EventPipeThreadSessionState *thread_session_state = ep_thread_get_session_state (thread, buffer_manager->session); ep_thread_session_state_set_write_buffer (thread_session_state, NULL); EP_SPIN_LOCK_EXIT (ep_thread_get_rt_lock_ref (thread), section2) - ep_rt_thread_array_iterator_next (&thread_array_iterator); - } + } DN_VECTOR_PTR_FOREACH_END; ep_on_exit: ep_requires_lock_held (); - ep_rt_thread_array_fini (&thread_array); + dn_vector_ptr_dispose (&thread_vector); return; ep_on_error: @@ -1211,11 +1198,18 @@ ep_buffer_manager_write_all_buffers_to_file_v4 ( *events_written = false; - EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY(session_states_to_delete); - ep_rt_thread_session_state_array_init(&session_states_to_delete); EventPipeSequencePoint *sequence_point = NULL; ep_timestamp_t current_timestamp_boundary = stop_timestamp; + DN_DEFAULT_LOCAL_ALLOCATOR (allocator, dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_init_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_t session_states_to_delete; + ep_raise_error_if_nok (dn_vector_ptr_custom_init (&session_states_to_delete, ¶ms)); + EP_SPIN_LOCK_ENTER (&buffer_manager->rt_lock, section1) if (buffer_manager_try_peek_sequence_point (buffer_manager, &sequence_point)) current_timestamp_boundary = EP_MIN (current_timestamp_boundary, ep_sequence_point_get_timestamp (sequence_point)); @@ -1267,26 +1261,25 @@ ep_buffer_manager_write_all_buffers_to_file_v4 ( // through the events we may have observed that a higher numbered event was recorded. If so we // should adjust the sequence numbers upwards to ensure the data in the stream is consistent. EP_SPIN_LOCK_ENTER (&buffer_manager->rt_lock, section2) - ep_rt_thread_session_state_list_iterator_t thread_session_state_list_iterator = ep_rt_thread_session_state_list_iterator_begin (&buffer_manager->thread_session_state_list); - while (!ep_rt_thread_session_state_list_iterator_end (&buffer_manager->thread_session_state_list, &thread_session_state_list_iterator)) { - EventPipeThreadSessionState * session_state = ep_rt_thread_session_state_list_iterator_value (&thread_session_state_list_iterator); - uint32_t thread_sequence_number = 0; - bool exists = ep_rt_thread_sequence_number_map_lookup (ep_sequence_point_get_thread_sequence_numbers_cref (sequence_point), session_state, &thread_sequence_number); + for (dn_list_it_t it = dn_list_begin (buffer_manager->thread_session_state_list); !dn_list_it_end (it); ) { + EventPipeThreadSessionState *session_state = *dn_list_it_data_t (it, EventPipeThreadSessionState *); + dn_umap_it_t found = dn_umap_ptr_uint32_find (ep_sequence_point_get_thread_sequence_numbers (sequence_point), session_state); + uint32_t thread_sequence_number = !dn_umap_it_end (found) ? dn_umap_it_value_uint32_t (found) : 0; uint32_t last_read_sequence_number = ep_thread_session_state_get_buffer_list (session_state)->last_read_sequence_number; // Sequence numbers can overflow so we can't use a direct last_read > sequence_number comparison // If a thread is able to drop more than 0x80000000 events in between sequence points then we will // miscategorize it, but that seems unlikely. uint32_t last_read_delta = last_read_sequence_number - thread_sequence_number; if (0 < last_read_delta && last_read_delta < 0x80000000) { - if (exists) { - ep_rt_thread_sequence_number_map_remove (ep_sequence_point_get_thread_sequence_numbers_ref (sequence_point), session_state); + if (!dn_umap_it_end (found)) { + dn_umap_erase (found); } else { ep_thread_addref (ep_thread_holder_get_thread (ep_thread_session_state_get_thread_holder_ref (session_state))); } - ep_rt_thread_sequence_number_map_add (ep_sequence_point_get_thread_sequence_numbers_ref (sequence_point), session_state, last_read_sequence_number); + dn_umap_ptr_uint32_insert (ep_sequence_point_get_thread_sequence_numbers (sequence_point), session_state, last_read_sequence_number); } - ep_rt_thread_session_state_list_iterator_next (&thread_session_state_list_iterator); + it = dn_list_it_next (it); // if a session_state was exhausted during this sequence point, mark it for deletion if (ep_thread_session_state_get_buffer_list (session_state)->head_buffer == NULL) { @@ -1295,9 +1288,8 @@ ep_buffer_manager_write_all_buffers_to_file_v4 ( // because we will either not have passed the above if statement (there were events still in the buffers) or we // will catch it at the next sequence point. if (ep_rt_volatile_load_uint32_t_without_barrier (ep_thread_get_unregistered_ref (ep_thread_session_state_get_thread (session_state))) > 0) { - - ep_rt_thread_session_state_array_append (&session_states_to_delete, session_state); - ep_rt_thread_session_state_list_remove (&buffer_manager->thread_session_state_list, session_state); + dn_vector_ptr_push_back (&session_states_to_delete, session_state); + dn_list_remove (buffer_manager->thread_session_state_list, session_state); } } } @@ -1319,59 +1311,43 @@ ep_buffer_manager_write_all_buffers_to_file_v4 ( // There are sequence points created during this flush and we've marked session states for deletion. // We need to remove these from the internal maps of the subsequent Sequence Points - if (ep_rt_thread_session_state_array_size (&session_states_to_delete) > 0) { + if (dn_vector_ptr_size (&session_states_to_delete) > 0) { EP_SPIN_LOCK_ENTER (&buffer_manager->rt_lock, section4) if (buffer_manager_try_peek_sequence_point (buffer_manager, &sequence_point)) { - // foreach (sequence_point in buffer_manager->sequence_point_list) - for (ep_rt_sequence_point_list_iterator_t sequence_point_list_iterator = ep_rt_sequence_point_list_iterator_begin (&buffer_manager->sequence_points); - !ep_rt_sequence_point_list_iterator_end (&buffer_manager->sequence_points, &sequence_point_list_iterator); - ep_rt_sequence_point_list_iterator_next (&sequence_point_list_iterator)) { - - sequence_point = ep_rt_sequence_point_list_iterator_value (&sequence_point_list_iterator); - + DN_LIST_FOREACH_BEGIN (EventPipeSequencePoint *, current_sequence_point, buffer_manager->sequence_points) { // foreach (session_state in session_states_to_delete) - for (ep_rt_thread_session_state_array_iterator_t thread_session_state_array_iterator = ep_rt_thread_session_state_array_iterator_begin (&session_states_to_delete); - !ep_rt_thread_session_state_array_iterator_end (&session_states_to_delete, &thread_session_state_array_iterator); - ep_rt_thread_session_state_array_iterator_next (&thread_session_state_array_iterator)) { - - EventPipeThreadSessionState * thread_session_state = ep_rt_thread_session_state_array_iterator_value (&thread_session_state_array_iterator); - uint32_t unused_thread_sequence_number = 0; - bool exists = ep_rt_thread_sequence_number_map_lookup (ep_sequence_point_get_thread_sequence_numbers_cref (sequence_point), thread_session_state, &unused_thread_sequence_number); - if (exists) { - ep_rt_thread_sequence_number_map_remove (ep_sequence_point_get_thread_sequence_numbers_ref (sequence_point), thread_session_state); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, &session_states_to_delete) { + dn_umap_it_t found = dn_umap_ptr_uint32_find (ep_sequence_point_get_thread_sequence_numbers (current_sequence_point), thread_session_state); + if (!dn_umap_it_end (found)) { + dn_umap_erase (found); // every entry of this map was holding an extra ref to the thread (see: ep-event-instance.{h|c}) ep_thread_release (ep_thread_session_state_get_thread (thread_session_state)); } - } - } + } DN_VECTOR_PTR_FOREACH_END; + } DN_LIST_FOREACH_END; } EP_SPIN_LOCK_EXIT (&buffer_manager->rt_lock, section4) } // foreach (session_state in session_states_to_delete) - for (ep_rt_thread_session_state_array_iterator_t thread_session_state_array_iterator = ep_rt_thread_session_state_array_iterator_begin (&session_states_to_delete); - !ep_rt_thread_session_state_array_iterator_end (&session_states_to_delete, &thread_session_state_array_iterator); - ep_rt_thread_session_state_array_iterator_next (&thread_session_state_array_iterator)) { - - EventPipeThreadSessionState * thread_session_state = ep_rt_thread_session_state_array_iterator_value (&thread_session_state_array_iterator); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, &session_states_to_delete) { EP_ASSERT (thread_session_state != NULL); + // This may be the last reference to a given EventPipeThread, so make a ref to keep it around till we're done EventPipeThreadHolder thread_holder; if (ep_thread_holder_init (&thread_holder, ep_thread_session_state_get_thread (thread_session_state))) { - ep_rt_spin_lock_handle_t *thread_lock = ep_thread_get_rt_lock_ref (ep_thread_holder_get_thread (&thread_holder)); EP_SPIN_LOCK_ENTER (thread_lock, section5) - EP_ASSERT(ep_rt_volatile_load_uint32_t_without_barrier (ep_thread_get_unregistered_ref (ep_thread_session_state_get_thread (thread_session_state))) > 0); ep_thread_delete_session_state (ep_thread_session_state_get_thread (thread_session_state), ep_thread_session_state_get_session (thread_session_state)); EP_SPIN_LOCK_EXIT (thread_lock, section5) ep_thread_holder_fini (&thread_holder); } - } + } DN_VECTOR_PTR_FOREACH_END; ep_on_exit: - ep_rt_thread_session_state_array_fini(&session_states_to_delete); + dn_vector_ptr_dispose (&session_states_to_delete); return; ep_on_error: ep_exit_error_handler (); @@ -1403,17 +1379,21 @@ ep_buffer_manager_deallocate_buffers (EventPipeBufferManager *buffer_manager) { EP_ASSERT (buffer_manager != NULL); - EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY(thread_session_states_to_remove); - ep_rt_thread_session_state_array_init (&thread_session_states_to_remove); + DN_DEFAULT_LOCAL_ALLOCATOR (allocator, dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_custom_init_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); + + dn_vector_ptr_t thread_session_states_to_remove; + ep_raise_error_if_nok (dn_vector_ptr_custom_init (&thread_session_states_to_remove, ¶ms)); // Take the buffer manager manipulation lock EP_SPIN_LOCK_ENTER (&buffer_manager->rt_lock, section1) EP_ASSERT (ep_buffer_manager_ensure_consistency (buffer_manager)); - ep_rt_thread_session_state_list_iterator_t thread_session_state_list_iterator = ep_rt_thread_session_state_list_iterator_begin (&buffer_manager->thread_session_state_list); - while (!ep_rt_thread_session_state_list_iterator_end (&buffer_manager->thread_session_state_list, &thread_session_state_list_iterator)) { + DN_LIST_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, buffer_manager->thread_session_state_list) { // Get the list and determine if we can free it. - EventPipeThreadSessionState *thread_session_state = ep_rt_thread_session_state_list_iterator_value (&thread_session_state_list_iterator); EventPipeBufferList *buffer_list = ep_thread_session_state_get_buffer_list (thread_session_state); ep_thread_session_state_set_buffer_list (thread_session_state, NULL); @@ -1429,23 +1409,16 @@ ep_buffer_manager_deallocate_buffers (EventPipeBufferManager *buffer_manager) buffer_list = NULL; // And finally queue the removal of the SessionState from the thread - ep_rt_thread_session_state_array_append (&thread_session_states_to_remove, thread_session_state); - - ep_rt_thread_session_state_list_iterator_next (&thread_session_state_list_iterator); - } + dn_vector_ptr_push_back (&thread_session_states_to_remove, thread_session_state); + } DN_LIST_FOREACH_END; // Clear thread session state list. - ep_rt_thread_session_state_list_free (&buffer_manager->thread_session_state_list, NULL); + dn_list_clear (buffer_manager->thread_session_state_list); EP_SPIN_LOCK_EXIT (&buffer_manager->rt_lock, section1) // remove and delete the session state - ep_rt_thread_session_state_array_iterator_t thread_session_states_to_remove_iterator; - thread_session_states_to_remove_iterator = ep_rt_thread_session_state_array_iterator_begin (&thread_session_states_to_remove); - - while (!ep_rt_thread_session_state_array_iterator_end (&thread_session_states_to_remove, &thread_session_states_to_remove_iterator)) { - EventPipeThreadSessionState *thread_session_state = ep_rt_thread_session_state_array_iterator_value (&thread_session_states_to_remove_iterator); - + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, &thread_session_states_to_remove) { // The strong reference from session state -> thread might be the very last reference // We need to ensure the thread doesn't die until we can release the lock EP_ASSERT (thread_session_state != NULL); @@ -1457,12 +1430,10 @@ ep_buffer_manager_deallocate_buffers (EventPipeBufferManager *buffer_manager) EP_SPIN_LOCK_EXIT (thread_lock, section2) ep_thread_holder_fini (&thread_holder); } - - ep_rt_thread_session_state_array_iterator_next (&thread_session_states_to_remove_iterator); - } + } DN_VECTOR_PTR_FOREACH_END; ep_on_exit: - ep_rt_thread_session_state_array_fini (&thread_session_states_to_remove); + dn_vector_ptr_dispose (&thread_session_states_to_remove); return; ep_on_error: @@ -1475,12 +1446,9 @@ ep_buffer_manager_ensure_consistency (EventPipeBufferManager *buffer_manager) { EP_ASSERT (buffer_manager != NULL); - ep_rt_thread_session_state_list_iterator_t iterator = ep_rt_thread_session_state_list_iterator_begin (&buffer_manager->thread_session_state_list); - while (!ep_rt_thread_session_state_list_iterator_end (&buffer_manager->thread_session_state_list, &iterator)) { - EventPipeThreadSessionState *thread_session_state = ep_rt_thread_session_state_list_iterator_value (&iterator); + DN_LIST_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, buffer_manager->thread_session_state_list) { EP_ASSERT (ep_buffer_list_ensure_consistency (ep_thread_session_state_get_buffer_list (thread_session_state))); - ep_rt_thread_session_state_list_iterator_next (&iterator); - } + } DN_LIST_FOREACH_END; return true; } diff --git a/src/native/eventpipe/ep-buffer-manager.h b/src/native/eventpipe/ep-buffer-manager.h index a4ec7c6..99be802 100644 --- a/src/native/eventpipe/ep-buffer-manager.h +++ b/src/native/eventpipe/ep-buffer-manager.h @@ -99,9 +99,9 @@ struct _EventPipeBufferManager_Internal { // its own data, while at the same time, ensuring that when a thread is destroyed, // we keep the buffers around without having to perform any migration or // book-keeping. - ep_rt_thread_session_state_list_t thread_session_state_list; + dn_list_t *thread_session_state_list; // A queue of sequence points. - ep_rt_sequence_point_list_t sequence_points; + dn_list_t *sequence_points; // Event for synchronizing real time reading. ep_rt_wait_event_handle_t rt_wait_event; // Lock to protect access to the per-thread buffer list and total allocation size. diff --git a/src/native/eventpipe/ep-config.c b/src/native/eventpipe/ep-config.c index c8abf11..8125834 100644 --- a/src/native/eventpipe/ep-config.c +++ b/src/native/eventpipe/ep-config.c @@ -13,7 +13,7 @@ #include "ep-session.h" #include "ep-rt.h" -EventPipeConfiguration _ep_config_instance = { { 0 }, 0 }; +EventPipeConfiguration _ep_config_instance = { NULL, NULL, NULL, NULL}; /* * Forward declares of all static functions. @@ -43,6 +43,19 @@ config_unregister_provider ( EventPipeConfiguration *config, EventPipeProvider *provider); +static +bool +DN_CALLBACK_CALLTYPE +config_compare_provider_name_func ( + const void *a, + const void *b); + +static +EventPipeProvider * +config_find_provider_by_name ( + dn_list_t *list, + const ep_char8_t *name); + /* * EventPipeConfiguration. */ @@ -71,7 +84,7 @@ config_compute_keyword_and_level ( EventPipeSessionProviderList *providers = ep_session_get_providers (session); EP_ASSERT (providers != NULL); - EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (providers), ep_provider_get_provider_name (provider)); + EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (providers), ep_provider_get_provider_name (provider)); if (session_provider) { *keyword_for_all_sessions = *keyword_for_all_sessions | ep_session_provider_get_keywords (session_provider); *level_for_all_sessions = (ep_session_provider_get_logging_level (session_provider) > *level_for_all_sessions) ? ep_session_provider_get_logging_level (session_provider) : *level_for_all_sessions; @@ -96,7 +109,7 @@ config_register_provider ( ep_requires_lock_held (); // The provider has not been registered, so register it. - if (!ep_rt_provider_list_append (&config->provider_list, provider)) + if (!dn_list_push_back (config->provider_list, provider)) return false; int64_t keyword_for_all_sessions; @@ -110,7 +123,7 @@ config_register_provider ( EventPipeSessionProviderList *providers = ep_session_get_providers (session); EP_ASSERT (providers != NULL); - EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (providers), ep_provider_get_provider_name (provider)); + EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (providers), ep_provider_get_provider_name (provider)); if (session_provider) { EventPipeProviderCallbackData provider_callback_data; memset (&provider_callback_data, 0, sizeof (provider_callback_data)); @@ -145,18 +158,39 @@ config_unregister_provider ( ep_requires_lock_held (); - EventPipeProvider *existing_provider = NULL; - ep_rt_provider_list_t *provider_list = &config->provider_list; + bool unregistered = false; // The provider list should be non-NULL, but can be NULL on shutdown. - if (!ep_rt_provider_list_is_empty (provider_list)) { + if (!dn_list_empty (config->provider_list)) { // If we found the provider, remove it. - if (ep_rt_provider_list_find (provider_list, provider, &existing_provider)) - ep_rt_provider_list_remove (provider_list, existing_provider); + dn_list_it_t found = dn_list_find (config->provider_list, provider); + if (!dn_list_it_end (found)) { + dn_list_erase (found); + unregistered = true; + } } ep_requires_lock_held (); - return (existing_provider != NULL); + return unregistered; +} + +static +bool +DN_CALLBACK_CALLTYPE +config_compare_provider_name_func ( + const void *a, + const void *b) +{ + return (a) ? !ep_rt_utf8_string_compare (ep_provider_get_provider_name ((EventPipeProvider *)a), (const ep_char8_t *)b) : false; +} + +static +EventPipeProvider * +config_find_provider_by_name (dn_list_t *list, + const ep_char8_t *name) +{ + dn_list_it_t found = dn_list_custom_find (list, name, config_compare_provider_name_func); + return (!dn_list_it_end (found)) ? *dn_list_it_data_t (found, EventPipeProvider *) : NULL; } EventPipeConfiguration * @@ -170,8 +204,8 @@ ep_config_init (EventPipeConfiguration *config) EventPipeProviderCallbackData provider_callback_data; EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&callback_data_queue); - ep_rt_provider_list_alloc (&config->provider_list); - ep_raise_error_if_nok (ep_rt_provider_list_is_valid (&config->provider_list)); + config->provider_list = dn_list_alloc (); + ep_raise_error_if_nok (config->provider_list != NULL); EP_LOCK_ENTER (section1) config->config_provider = provider_create_register (ep_config_get_default_provider_name_utf8 (), NULL, NULL, provider_callback_data_queue); @@ -224,7 +258,8 @@ ep_config_shutdown (EventPipeConfiguration *config) // Take the lock before manipulating the list. EP_LOCK_ENTER (section1) // We don't delete provider itself because it can be in-use - ep_rt_provider_list_free (&config->provider_list, NULL); + dn_list_free (config->provider_list); + config->provider_list = NULL; EP_LOCK_EXIT (section1) ep_on_exit: @@ -449,8 +484,8 @@ config_get_provider ( ep_requires_lock_held (); // The provider list should be non-NULL, but can be NULL on shutdown. - ep_return_null_if_nok (!ep_rt_provider_list_is_empty (&config->provider_list)); - EventPipeProvider *provider = ep_rt_provider_list_find_by_name (&config->provider_list, name); + ep_return_null_if_nok (!dn_list_empty (config->provider_list)); + EventPipeProvider *provider = config_find_provider_by_name (config->provider_list, name); ep_requires_lock_held (); return provider; @@ -509,16 +544,15 @@ config_delete_deferred_providers (EventPipeConfiguration *config) ep_requires_lock_held (); // The provider list should be non-NULL, but can be NULL on shutdown. - const ep_rt_provider_list_t *provider_list = &config->provider_list; - if (!ep_rt_provider_list_is_empty (provider_list)) { - ep_rt_provider_list_iterator_t iterator = ep_rt_provider_list_iterator_begin (provider_list); + if (!dn_list_empty (config->provider_list)) { - while (!ep_rt_provider_list_iterator_end (provider_list, &iterator)) { - EventPipeProvider *provider = ep_rt_provider_list_iterator_value (&iterator); + for (dn_list_it_t it = dn_list_begin (config->provider_list); !dn_list_it_end (it); ) { + EventPipeProvider *provider = *dn_list_it_data_t(it, EventPipeProvider *); EP_ASSERT (provider != NULL); // Get next item before deleting current. - ep_rt_provider_list_iterator_next (&iterator); + it = dn_list_it_next (it); + if (ep_provider_get_delete_deferred (provider)) config_delete_provider (config, provider); } @@ -541,10 +575,8 @@ config_enable_disable ( EP_ASSERT (session != NULL); // The provider list should be non-NULL, but can be NULL on shutdown. - const ep_rt_provider_list_t *provider_list = &config->provider_list; - if (!ep_rt_provider_list_is_empty (provider_list)) { - for (ep_rt_provider_list_iterator_t iterator = ep_rt_provider_list_iterator_begin (provider_list); !ep_rt_provider_list_iterator_end (provider_list, &iterator); ep_rt_provider_list_iterator_next (&iterator)) { - EventPipeProvider *provider = ep_rt_provider_list_iterator_value (&iterator); + if (!dn_list_empty (config->provider_list)) { + DN_LIST_FOREACH_BEGIN (EventPipeProvider *, provider, config->provider_list) { if (provider) { // Enable/Disable the provider if it has been configured. EventPipeSessionProvider *session_provider = config_get_session_provider (config, session, provider); @@ -581,7 +613,7 @@ config_enable_disable ( ep_provider_callback_data_fini (&provider_callback_data); } } - } + } DN_LIST_FOREACH_END; } ep_requires_lock_held (); diff --git a/src/native/eventpipe/ep-config.h b/src/native/eventpipe/ep-config.h index 92a813d..c25f33e 100644 --- a/src/native/eventpipe/ep-config.h +++ b/src/native/eventpipe/ep-config.h @@ -24,7 +24,7 @@ struct _EventPipeConfiguration { #else struct _EventPipeConfiguration_Internal { #endif - ep_rt_provider_list_t provider_list; + dn_list_t *provider_list; EventPipeProvider *config_provider; EventPipeEvent *metadata_event; ep_char8_t *config_provider_name; diff --git a/src/native/eventpipe/ep-event-instance.c b/src/native/eventpipe/ep-event-instance.c index 2972c5d..2d1c2d2 100644 --- a/src/native/eventpipe/ep-event-instance.c +++ b/src/native/eventpipe/ep-event-instance.c @@ -230,17 +230,13 @@ sequence_point_fini (EventPipeSequencePoint *sequence_point) EP_ASSERT (sequence_point != NULL); // Each entry in the map owns a ref-count on the corresponding thread - if (ep_rt_thread_sequence_number_map_count (&sequence_point->thread_sequence_numbers) != 0) { - for (ep_rt_thread_sequence_number_hash_map_iterator_t iterator = ep_rt_thread_sequence_number_map_iterator_begin (&sequence_point->thread_sequence_numbers); - !ep_rt_thread_sequence_number_map_iterator_end (&sequence_point->thread_sequence_numbers, &iterator); - ep_rt_thread_sequence_number_map_iterator_next (&iterator)) { - - EventPipeThreadSessionState *key = ep_rt_thread_sequence_number_map_iterator_key (&iterator); + if (dn_umap_size (sequence_point->thread_sequence_numbers) != 0) { + DN_UMAP_FOREACH_KEY_BEGIN (EventPipeThreadSessionState *, key, sequence_point->thread_sequence_numbers) { ep_thread_release (ep_thread_session_state_get_thread (key)); - } + } DN_UMAP_FOREACH_END; } - ep_rt_thread_sequence_number_map_free (&sequence_point->thread_sequence_numbers); + dn_umap_free (sequence_point->thread_sequence_numbers); } @@ -266,8 +262,8 @@ ep_sequence_point_init (EventPipeSequencePoint *sequence_point) EP_ASSERT (sequence_point != NULL); sequence_point->timestamp = 0; - ep_rt_thread_sequence_number_map_alloc (&sequence_point->thread_sequence_numbers, NULL, NULL, NULL, NULL); - return ep_rt_thread_sequence_number_map_is_valid (&sequence_point->thread_sequence_numbers) ? sequence_point : NULL; + sequence_point->thread_sequence_numbers = dn_umap_alloc (); + return sequence_point->thread_sequence_numbers ? sequence_point : NULL; } void diff --git a/src/native/eventpipe/ep-event-instance.h b/src/native/eventpipe/ep-event-instance.h index 0ffb516..cf54e1f 100644 --- a/src/native/eventpipe/ep-event-instance.h +++ b/src/native/eventpipe/ep-event-instance.h @@ -121,7 +121,7 @@ struct _EventPipeSequencePoint { #else struct _EventPipeSequencePoint_Internal { #endif - ep_rt_thread_sequence_number_hash_map_t thread_sequence_numbers; + dn_umap_t *thread_sequence_numbers; ep_timestamp_t timestamp; }; @@ -131,7 +131,7 @@ struct _EventPipeSequencePoint { }; #endif -EP_DEFINE_GETTER_REF(EventPipeSequencePoint *, sequence_point, ep_rt_thread_sequence_number_hash_map_t *, thread_sequence_numbers) +EP_DEFINE_GETTER(EventPipeSequencePoint *, sequence_point, dn_umap_t *, thread_sequence_numbers) EP_DEFINE_GETTER(EventPipeSequencePoint *, sequence_point, ep_timestamp_t, timestamp) EP_DEFINE_SETTER(EventPipeSequencePoint *, sequence_point, ep_timestamp_t, timestamp) diff --git a/src/native/eventpipe/ep-file.c b/src/native/eventpipe/ep-file.c index 3cf3a81..b9ee217 100644 --- a/src/native/eventpipe/ep-file.c +++ b/src/native/eventpipe/ep-file.c @@ -30,6 +30,7 @@ file_free_func (void *object); static void +DN_CALLBACK_CALLTYPE stack_hash_value_free_func (void *entry); static @@ -74,6 +75,16 @@ static uint32_t file_get_file_minimum_version (EventPipeSerializationFormat format); +static +uint32_t +DN_CALLBACK_CALLTYPE +stack_hash_key_hash_func (const void *key); + +static +bool +DN_CALLBACK_CALLTYPE +stack_hash_key_equal_func (const void *key1, const void *key2); + /* * EventPipeFile. */ @@ -121,6 +132,7 @@ file_vtable = { static void +DN_CALLBACK_CALLTYPE stack_hash_value_free_func (void *entry) { ep_stack_hash_entry_free ((StackHashEntry *)entry); @@ -154,16 +166,16 @@ file_get_stack_id ( uint32_t stack_id = 0; EventPipeStackContentsInstance *stack_contents = ep_event_instance_get_stack_contents_instance_ref (event_instance); EventPipeStackBlock *stack_block = file->stack_block; - ep_rt_stack_hash_map_t *stack_hash = &file->stack_hash; - StackHashEntry *entry = NULL; + dn_umap_t *stack_hash = file->stack_hash; StackHashKey key; ep_stack_hash_key_init (&key, stack_contents); - if (!ep_rt_stack_hash_lookup (stack_hash, &key, &entry)) { + dn_umap_it_t found = dn_umap_find (stack_hash, &key); + if (dn_umap_it_end (found)) { stack_id = file->stack_id_counter + 1; file->stack_id_counter = stack_id; - entry = ep_stack_hash_entry_alloc (stack_contents, stack_id, ep_stack_hash_key_get_hash (&key)); + StackHashEntry *entry = ep_stack_hash_entry_alloc (stack_contents, stack_id, ep_stack_hash_key_get_hash (&key)); if (entry) { - if (!ep_rt_stack_hash_add (stack_hash, ep_stack_hash_entry_get_key_ref (entry), entry)) + if (!dn_umap_insert (stack_hash, ep_stack_hash_entry_get_key_ref (entry), entry).result) ep_stack_hash_entry_free (entry); entry = NULL; } @@ -177,7 +189,7 @@ file_get_stack_id ( EP_UNREACHABLE ("Should never fail to add event to a clear block. If we do the max size is too small."); } } else { - stack_id = ep_stack_hash_entry_get_id (entry); + stack_id = ep_stack_hash_entry_get_id (dn_umap_it_value_t (found, StackHashEntry *)); } ep_stack_hash_key_fini (&key); @@ -194,7 +206,9 @@ file_get_metadata_id ( EP_ASSERT (ep_event != NULL); uint32_t metadata_ids; - if (ep_rt_metadata_labels_hash_lookup (&file->metadata_ids, ep_event, &metadata_ids)) { + dn_umap_it_t found = dn_umap_ptr_uint32_find (file->metadata_ids, ep_event); + if (!dn_umap_it_end (found)) { + metadata_ids = dn_umap_it_value_uint32_t (found); EP_ASSERT (metadata_ids != 0); return metadata_ids; } @@ -260,13 +274,8 @@ file_save_metadata_id ( EP_ASSERT (ep_event != NULL); EP_ASSERT (metadata_id > 0); - // If a pre-existing metadata label exists, remove it. - uint32_t old_id; - if (ep_rt_metadata_labels_hash_lookup (&file->metadata_ids, ep_event, &old_id)) - ep_rt_metadata_labels_hash_remove (&file->metadata_ids, ep_event); - - // Add the metadata label. - return ep_rt_metadata_labels_hash_add (&file->metadata_ids, ep_event, metadata_id); + // Add/Replace the metadata label. + return dn_umap_ptr_uint32_insert_or_assign (file->metadata_ids, ep_event, metadata_id).result; } static @@ -304,6 +313,11 @@ ep_file_alloc ( StreamWriter *stream_writer, EventPipeSerializationFormat format) { + dn_umap_custom_alloc_params_t params = {0, }; + params.hash_func = stack_hash_key_hash_func; + params.equal_func = stack_hash_key_equal_func; + params.value_dispose_func = stack_hash_value_free_func; + EventPipeFile *instance = ep_rt_object_alloc (EventPipeFile); ep_raise_error_if_nok (instance != NULL); @@ -337,11 +351,11 @@ ep_file_alloc ( instance->sampling_rate_in_ns = (uint32_t)ep_sample_profiler_get_sampling_rate (); - ep_rt_metadata_labels_hash_alloc (&instance->metadata_ids, NULL, NULL, NULL, NULL); - ep_raise_error_if_nok (ep_rt_metadata_labels_hash_is_valid (&instance->metadata_ids)); + instance->metadata_ids = dn_umap_alloc (); + ep_raise_error_if_nok (instance->metadata_ids != NULL); - ep_rt_stack_hash_alloc (&instance->stack_hash, ep_rt_stack_hash_key_hash, ep_rt_stack_hash_key_equal, NULL, stack_hash_value_free_func); - ep_raise_error_if_nok (ep_rt_stack_hash_is_valid (&instance->stack_hash)); + instance->stack_hash = dn_umap_custom_alloc (¶ms); + ep_raise_error_if_nok (instance->stack_hash != NULL); // Start at 0 - The value is always incremented prior to use, so the first ID will be 1. ep_rt_volatile_store_uint32_t (&instance->metadata_id_counter, 0); @@ -376,8 +390,8 @@ ep_file_free (EventPipeFile *file) ep_metadata_block_free (file->metadata_block); ep_stack_block_free (file->stack_block); ep_fast_serializer_free (file->fast_serializer); - ep_rt_metadata_labels_hash_free (&file->metadata_ids); - ep_rt_stack_hash_free (&file->stack_hash); + dn_umap_free (file->metadata_ids); + dn_umap_free (file->stack_hash); // If file has not been initialized, stream_writer ownership // have not been passed along and needs to be freed by file. @@ -487,7 +501,7 @@ ep_file_write_sequence_point ( // stack cache resets on sequence points file->stack_id_counter = 0; - ep_rt_stack_hash_remove_all (&file->stack_hash); + dn_umap_clear (file->stack_hash); ep_on_exit: return; @@ -590,6 +604,30 @@ hash_bytes (const uint8_t *data, size_t data_len) return hash; } +static +uint32_t +DN_CALLBACK_CALLTYPE +stack_hash_key_hash_func (const void *key) +{ + EP_ASSERT (key != NULL); + return ((const StackHashKey *)key)->hash; +} + +static +bool +DN_CALLBACK_CALLTYPE +stack_hash_key_equal_func (const void *key1, const void *key2) +{ + EP_ASSERT (key1 != NULL); + EP_ASSERT (key2 != NULL); + + const StackHashKey * stack_hash_key1 = (const StackHashKey *)key1; + const StackHashKey * stack_hash_key2 = (const StackHashKey *)key2; + + return stack_hash_key1->stack_size_in_bytes == stack_hash_key2->stack_size_in_bytes && + !memcmp (stack_hash_key1->stack_bytes, stack_hash_key2->stack_bytes, stack_hash_key1->stack_size_in_bytes); +} + StackHashKey * ep_stack_hash_key_init ( StackHashKey *key, @@ -611,26 +649,6 @@ ep_stack_hash_key_fini (StackHashKey *key) ; } -uint32_t -ep_stack_hash_key_hash (const void *key) -{ - EP_ASSERT (key != NULL); - return ((const StackHashKey *)key)->hash; -} - -bool -ep_stack_hash_key_equal (const void *key1, const void *key2) -{ - EP_ASSERT (key1 != NULL); - EP_ASSERT (key2 != NULL); - - const StackHashKey * stack_hash_key1 = (const StackHashKey *)key1; - const StackHashKey * stack_hash_key2 = (const StackHashKey *)key2; - - return stack_hash_key1->stack_size_in_bytes == stack_hash_key2->stack_size_in_bytes && - !memcmp (stack_hash_key1->stack_bytes, stack_hash_key2->stack_bytes, stack_hash_key1->stack_size_in_bytes); -} - #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ #endif /* ENABLE_PERFTRACING */ diff --git a/src/native/eventpipe/ep-file.h b/src/native/eventpipe/ep-file.h index 9a64abc..0dcb5a0 100644 --- a/src/native/eventpipe/ep-file.h +++ b/src/native/eventpipe/ep-file.h @@ -34,8 +34,8 @@ struct _EventPipeFile_Internal { EventPipeMetadataBlock *metadata_block; EventPipeStackBlock *stack_block; // Hashtable of metadata labels. - ep_rt_metadata_labels_hash_map_t metadata_ids; - ep_rt_stack_hash_map_t stack_hash; + dn_umap_t *metadata_ids; + dn_umap_t *stack_hash; // The timestamp when the file was opened. Used for calculating file-relative timestamps. ep_timestamp_t file_open_timestamp; #ifdef EP_CHECKED_BUILD @@ -128,12 +128,6 @@ ep_stack_hash_key_init ( void ep_stack_hash_key_fini (StackHashKey *key); -uint32_t -ep_stack_hash_key_hash (const void *key); - -bool -ep_stack_hash_key_equal (const void *key1, const void *key2); - /* * StackHashEntry. */ diff --git a/src/native/eventpipe/ep-provider.c b/src/native/eventpipe/ep-provider.c index 5939fd6..0a7f7b7 100644 --- a/src/native/eventpipe/ep-provider.c +++ b/src/native/eventpipe/ep-provider.c @@ -19,6 +19,7 @@ static void +DN_CALLBACK_CALLTYPE event_free_func (void *ep_event); static @@ -58,6 +59,7 @@ provider_compute_event_enable_mask ( static void +DN_CALLBACK_CALLTYPE event_free_func (void *ep_event) { ep_event_free ((EventPipeEvent *)ep_event); @@ -95,11 +97,11 @@ provider_refresh_all_events (EventPipeProvider *provider) ep_requires_lock_held (); - const ep_rt_event_list_t *event_list = &provider->event_list; - EP_ASSERT (event_list != NULL); + EP_ASSERT (provider->event_list != NULL); - for (ep_rt_event_list_iterator_t iterator = ep_rt_event_list_iterator_begin (event_list); !ep_rt_event_list_iterator_end (event_list, &iterator); ep_rt_event_list_iterator_next (&iterator)) - provider_refresh_event_state (ep_rt_event_list_iterator_value (&iterator)); + DN_LIST_FOREACH_BEGIN (EventPipeEvent *, current_event, provider->event_list) { + provider_refresh_event_state (current_event); + } DN_LIST_FOREACH_END; ep_requires_lock_held (); return; @@ -183,8 +185,8 @@ ep_provider_alloc ( instance->provider_name_utf16 = ep_rt_utf8_to_utf16le_string (provider_name, -1); ep_raise_error_if_nok (instance->provider_name_utf16 != NULL); - ep_rt_event_list_alloc (&instance->event_list); - ep_raise_error_if_nok (ep_rt_event_list_is_valid (&instance->event_list)); + instance->event_list = dn_list_alloc (); + ep_raise_error_if_nok (instance->event_list != NULL); instance->keywords = 0; instance->provider_level = EP_EVENT_LEVEL_CRITICAL; @@ -210,9 +212,10 @@ ep_provider_free (EventPipeProvider * provider) ep_requires_lock_not_held (); - if (!ep_rt_event_list_is_empty (&provider->event_list)) { + if (provider->event_list) { EP_LOCK_ENTER (section1) - ep_rt_event_list_free (&provider->event_list, event_free_func); + dn_list_custom_free (provider->event_list, event_free_func); + provider->event_list = NULL; EP_LOCK_EXIT (section1) } @@ -267,7 +270,7 @@ ep_provider_add_event ( // Take the config lock before inserting a new event. EP_LOCK_ENTER (section1) - ep_raise_error_if_nok_holding_lock (ep_rt_event_list_append (&provider->event_list, instance), section1); + ep_raise_error_if_nok_holding_lock (dn_list_push_back (provider->event_list, instance), section1); provider_refresh_event_state (instance); EP_LOCK_EXIT (section1) @@ -457,8 +460,7 @@ provider_free (EventPipeProvider * provider) ep_requires_lock_held (); - if (!ep_rt_event_list_is_empty (&provider->event_list)) - ep_rt_event_list_free (&provider->event_list, event_free_func); + dn_list_custom_free (provider->event_list, event_free_func); ep_rt_utf16_string_free (provider->provider_name_utf16); ep_rt_utf8_string_free (provider->provider_name); @@ -492,7 +494,7 @@ provider_add_event ( ep_raise_error_if_nok (instance != NULL); - ep_raise_error_if_nok (ep_rt_event_list_append (&provider->event_list, instance)); + ep_raise_error_if_nok (dn_list_push_back (provider->event_list, instance)); provider_refresh_event_state (instance); ep_on_exit: diff --git a/src/native/eventpipe/ep-provider.h b/src/native/eventpipe/ep-provider.h index cae9bd3..abb743f 100644 --- a/src/native/eventpipe/ep-provider.h +++ b/src/native/eventpipe/ep-provider.h @@ -30,7 +30,7 @@ struct _EventPipeProvider_Internal { ep_char16_t *provider_name_utf16; // List of every event currently associated with the provider. // New events can be added on-the-fly. - ep_rt_event_list_t event_list; + dn_list_t *event_list; // The optional provider callback function. EventPipeCallback callback_func; // The optional provider callback data pointer. diff --git a/src/native/eventpipe/ep-rt-types.h b/src/native/eventpipe/ep-rt-types.h index acdc2d0..9e219ed 100644 --- a/src/native/eventpipe/ep-rt-types.h +++ b/src/native/eventpipe/ep-rt-types.h @@ -9,104 +9,15 @@ #define EP_UNLIKELY(expr) ep_rt_redefine /* - * EventPipeBuffer. - */ - -#define ep_rt_buffer_array_t ep_rt_redefine -#define ep_rt_buffer_array_iterator_t ep_rt_redefine - -/* - * EventPipeBufferList. - */ - -#define ep_rt_buffer_list_array_t ep_rt_redefine -#define ep_rt_buffer_list_array_iterator_t ep_rt_redefine - -/* - * EventPipeEvent. - */ - -#define ep_rt_event_list_t ep_rt_redefine -#define ep_rt_event_list_iterator_t ep_rt_redefine - -/* - * EventPipeFile. - */ - -#define ep_rt_metadata_labels_hash_map_t ep_rt_redefine -#define ep_rt_metadata_labels_hash_map_iterator_t ep_rt_redefine - -#define ep_rt_stack_hash_map_t ep_rt_redefine -#define ep_rt_stack_hash_map_iterator_t ep_rt_redefine - -/* - * EventPipeProvider. - */ - -#define ep_rt_provider_list_t ep_rt_redefine -#define ep_rt_provider_list_iterator_t ep_rt_redefine - -#define ep_rt_provider_callback_data_queue_t ep_rt_redefine - -/* - * EventPipeProviderConfiguration. - */ - -#define ep_rt_provider_config_array_t ep_rt_redefine -#define ep_rt_provider_config_array_iterator_t ep_rt_redefine - -/* - * EventPipeSessionProvider. - */ - -#define ep_rt_session_provider_list_t ep_rt_redefine -#define ep_rt_session_provider_list_iterator_t ep_rt_redefine - -/* - * EventPipeSequencePoint. - */ - -#define ep_rt_sequence_point_list_t ep_rt_redefine -#define ep_rt_sequence_point_list_iterator_t ep_rt_redefine - -/* - * EventPipeThread. - */ - -#define ep_rt_thread_list_t ep_rt_redefine -#define ep_rt_thread_list_iterator_t ep_rt_redefine - -#define ep_rt_thread_array_t ep_rt_redefine -#define ep_rt_thread_array_iterator_t ep_rt_redefine - -/* - * EventPipeThreadSessionState. - */ - -#define ep_rt_thread_session_state_list_t ep_rt_redefine -#define ep_rt_thread_session_state_list_iterator_t ep_rt_redefine - -#define ep_rt_thread_session_state_array_t ep_rt_redefine -#define ep_rt_thread_session_state_array_iterator_t ep_rt_redefine - -/* * EventPipe. */ -#define ep_rt_session_id_array_t ep_rt_redefine -#define ep_rt_session_id_array_iterator_t ep_rt_redefine - #define ep_rt_method_desc_t ep_rt_redefine -#define ep_rt_execution_checkpoint_array_t ep_rt_redefine - /* * PAL. */ -#define ep_rt_env_array_utf16_t ep_rt_redefine -#define ep_rt_env_array_utf16_iterator_t ep_rt_redefine - #define ep_rt_file_handle_t ep_rt_redefine #define ep_rt_wait_event_handle_t ep_rt_redefine @@ -132,13 +43,6 @@ #define ep_rt_thread_params_t ep_rt_redefine /* - * ThreadSequenceNumberMap. - */ - -#define ep_rt_thread_sequence_number_hash_map_t ep_rt_redefine -#define ep_rt_thread_sequence_number_hash_map_iterator_t ep_rt_redefine - -/* * ErrorHandling. */ diff --git a/src/native/eventpipe/ep-rt.h b/src/native/eventpipe/ep-rt.h index fe9dc18..8f9e667 100644 --- a/src/native/eventpipe/ep-rt.h +++ b/src/native/eventpipe/ep-rt.h @@ -19,178 +19,35 @@ #define EP_NEVER_INLINE ep_rt_redefine #define EP_ALIGN_UP(val,align) ep_rt_redefine -#ifndef EP_RT_BUILD_TYPE_FUNC_NAME -#define EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, type_name, func_name) \ -prefix_name ## _rt_ ## type_name ## _ ## func_name -#endif - -#define EP_RT_DECLARE_LIST_PREFIX(prefix_name, list_name, list_type, item_type) \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, alloc) (list_type *list); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, free) (list_type *list, void (*callback)(void *)); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, clear) (list_type *list, void (*callback)(void *)); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, append) (list_type *list, item_type item); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, remove) (list_type *list, const item_type item); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, find) (const list_type *list, const item_type item_to_find, item_type *found_item); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_empty) (const list_type *list); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_valid) (const list_type *list); - -#define EP_RT_DECLARE_LIST(list_name, list_type, item_type) \ - EP_RT_DECLARE_LIST_PREFIX(ep, list_name, list_type, item_type) - -#define EP_RT_DEFINE_LIST ep_rt_redefine - -#define EP_RT_DECLARE_LIST_ITERATOR_PREFIX(prefix_name, list_name, list_type, iterator_type, item_type) \ - static iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_begin) (const list_type *list); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_end) (const list_type *list, const iterator_type *iterator); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_next) (iterator_type *iterator); \ - static item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_value) (const iterator_type *iterator); - -#define EP_RT_DECLARE_LIST_ITERATOR(list_name, list_type, iterator_type, item_type) \ - EP_RT_DECLARE_LIST_ITERATOR_PREFIX(ep, list_name, list_type, iterator_type, item_type) - -#define EP_RT_DEFINE_LIST_ITERATOR ep_rt_redefine - -#define EP_RT_DECLARE_QUEUE_PREFIX(prefix_name, queue_name, queue_type, item_type) \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, alloc) (queue_type *queue); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, free) (queue_type *queue); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, pop_head) (queue_type *queue, item_type *item); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_head) (queue_type *queue, item_type item); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_tail) (queue_type *queue, item_type item); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_empty) (const queue_type *queue); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_valid) (const queue_type *queue); - -#define EP_RT_DECLARE_QUEUE(queue_name, queue_type, item_type) \ - EP_RT_DECLARE_QUEUE_PREFIX(ep, queue_name, queue_type, item_type) - -#define EP_RT_DEFINE_QUEUE ep_rt_redefine - -#define EP_RT_DECLARE_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc) (array_type *ep_array); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc_capacity) (array_type *ep_array, size_t capacity); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, free) (array_type *ep_array); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, append) (array_type *ep_array, item_type item); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, clear) (array_type *ep_array); \ - static size_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, size) (const array_type *ep_array); \ - static item_type * EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, data) (const array_type *ep_array); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, is_valid) (const array_type *ep_array); - -#define EP_RT_DECLARE_LOCAL_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init) (array_type *ep_array); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init_capacity) (array_type *ep_array, size_t capacity); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, fini) (array_type *ep_array); - -#define EP_RT_DECLARE_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DECLARE_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DEFINE_ARRAY ep_rt_redefine - -#define EP_RT_DECLARE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \ - EP_RT_DECLARE_LOCAL_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DEFINE_LOCAL_ARRAY ep_rt_redefine - -#define EP_RT_DECLARE_ARRAY_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_begin) (const array_type *ep_array); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_end) (const array_type *ep_array, const iterator_type *iterator); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_next) (iterator_type *iterator); \ - static item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_value) (const iterator_type *iterator); - -#define EP_RT_DECLARE_ARRAY_REVERSE_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \ - static iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_begin) (const array_type *ep_array); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_end) (const array_type *ep_array, const iterator_type *iterator); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_next) (iterator_type *iterator); \ - static item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_value) (const iterator_type *iterator); - -#define EP_RT_DECLARE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DECLARE_ARRAY_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DEFINE_ARRAY_ITERATOR ep_rt_redefine - -#define EP_RT_DECLARE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \ - EP_RT_DECLARE_ARRAY_REVERSE_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type) - -#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR ep_rt_redefine - -#ifndef EP_RT_USE_CUSTOM_HASH_MAP_CALLBACKS -typedef uint32_t (*ep_rt_hash_map_hash_callback_t)(const void *); -typedef bool (*ep_rt_hash_map_equal_callback_t)(const void *, const void *); -#endif - -#define EP_RT_DECLARE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, alloc) (hash_map_type *hash_map, ep_rt_hash_map_hash_callback_t hash_callback, ep_rt_hash_map_equal_callback_t eq_callback, void (*key_free_callback)(void *), void (*value_free_callback)(void *)); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, free) (hash_map_type *hash_map); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add) (hash_map_type *hash_map, key_type key, value_type value); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove_all) (hash_map_type *hash_map); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, lookup) (const hash_map_type *hash_map, const key_type key, value_type *value); \ - static uint32_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, count) (const hash_map_type *hash_map); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, is_valid) (const hash_map_type *hash_map); - -#define EP_RT_DECLARE_HASH_MAP_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DECLARE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add_or_replace) (hash_map_type *hash_map, key_type key, value_type value); - -#define EP_RT_DECLARE_HASH_MAP_REMOVE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DECLARE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove) (hash_map_type *hash_map, const key_type key); - -#define EP_RT_DECLARE_HASH_MAP(hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DECLARE_HASH_MAP_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type) - -#define EP_RT_DEFINE_HASH_MAP ep_rt_redefine - -#define EP_RT_DECLARE_HASH_MAP_REMOVE(hash_map_name, hash_map_type, key_type, value_type) \ - EP_RT_DECLARE_HASH_MAP_REMOVE_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type) - -#define EP_RT_DEFINE_HASH_MAP_REMOVE ep_rt_redefine - -#define EP_RT_DECLARE_HASH_MAP_ITERATOR_PREFIX(prefix_name, hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ - static iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_begin) (const hash_map_type *hash_map); \ - static bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_end) (const hash_map_type *hash_map, const iterator_type *iterator); \ - static void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_next) (iterator_type *iterator); \ - static key_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_key) (const iterator_type *iterator); \ - static value_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_value) (const iterator_type *iterator); - -#define EP_RT_DECLARE_HASH_MAP_ITERATOR(hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ - EP_RT_DECLARE_HASH_MAP_ITERATOR_PREFIX(ep, hash_map_name, hash_map_type, iterator_type, key_type, value_type) - -#define EP_RT_DEFINE_HASH_MAP_ITERATOR ep_rt_redefine - /* * Little-Endian Conversion. */ static -inline uint16_t ep_rt_val_uint16_t (uint16_t value); static -inline uint32_t ep_rt_val_uint32_t (uint32_t value); static -inline uint64_t ep_rt_val_uint64_t (uint64_t value); static -inline int16_t ep_rt_val_int16_t (int16_t value); static -inline int32_t ep_rt_val_int32_t (int32_t value); static -inline int64_t ep_rt_val_int64_t (int64_t value); static -inline uintptr_t ep_rt_val_uintptr_t (uintptr_t value); @@ -226,20 +83,10 @@ static size_t ep_rt_atomic_compare_exchange_size_t (volatile size_t *target, size_t expected, size_t value); -static -ep_char8_t * -eo_rt_atomic_compare_exchange_utf8_string (volatile ep_char8_t **target, ep_char8_t *expected, ep_char8_t *value); - /* * EventPipe. */ -EP_RT_DECLARE_ARRAY (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID) -EP_RT_DECLARE_ARRAY_ITERATOR (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID) - -EP_RT_DECLARE_ARRAY (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *) -EP_RT_DECLARE_ARRAY_ITERATOR (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *) - static void ep_rt_init (void); @@ -320,67 +167,9 @@ ep_rt_provider_invoke_callback ( void *callback_data); /* - * EventPipeBuffer. - */ - -EP_RT_DECLARE_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) -EP_RT_DECLARE_LOCAL_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) -EP_RT_DECLARE_ARRAY_ITERATOR (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *) - -#define EP_RT_DECLARE_LOCAL_BUFFER_ARRAY(var_name) ds_rt_redefine - -/* - * EventPipeBufferList. - */ - -EP_RT_DECLARE_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) -EP_RT_DECLARE_LOCAL_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) -EP_RT_DECLARE_ARRAY_ITERATOR (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *) - -#define EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY(var_name) ds_rt_redefine - -/* - * EventPipeEvent. - */ - -EP_RT_DECLARE_LIST (event_list, ep_rt_event_list_t, EventPipeEvent *) -EP_RT_DECLARE_LIST_ITERATOR (event_list, ep_rt_event_list_t, ep_rt_event_list_iterator_t, EventPipeEvent *) - -/* - * EventPipeFile. - */ - -EP_RT_DECLARE_HASH_MAP_REMOVE(metadata_labels_hash, ep_rt_metadata_labels_hash_map_t, EventPipeEvent *, uint32_t) -EP_RT_DECLARE_HASH_MAP(stack_hash, ep_rt_stack_hash_map_t, StackHashKey *, StackHashEntry *) -EP_RT_DECLARE_HASH_MAP_ITERATOR(stack_hash, ep_rt_stack_hash_map_t, ep_rt_stack_hash_map_iterator_t, StackHashKey *, StackHashEntry *) - -#ifndef EP_RT_USE_CUSTOM_HASH_MAP_CALLBACKS -#define ep_rt_stack_hash_key_hash ep_stack_hash_key_hash -#define ep_rt_stack_hash_key_equal ep_stack_hash_key_equal -#endif - -/* - * EventPipeProvider. - */ - -EP_RT_DECLARE_LIST (provider_list, ep_rt_provider_list_t, EventPipeProvider *) -EP_RT_DECLARE_LIST_ITERATOR (provider_list, ep_rt_provider_list_t, ep_rt_provider_list_iterator_t, EventPipeProvider *) - -EP_RT_DECLARE_QUEUE (provider_callback_data_queue, ep_rt_provider_callback_data_queue_t, EventPipeProviderCallbackData *) - -static -EventPipeProvider * -ep_rt_provider_list_find_by_name ( - const ep_rt_provider_list_t *list, - const ep_char8_t *name); - -/* * EventPipeProviderConfiguration. */ -EP_RT_DECLARE_ARRAY (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration) -EP_RT_DECLARE_ARRAY_ITERATOR (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration) - static bool ep_rt_config_value_get_enable (void); @@ -420,52 +209,6 @@ void ep_rt_notify_profiler_provider_created (EventPipeProvider *provider); /* - * EventPipeSessionProvider. - */ - -EP_RT_DECLARE_LIST (session_provider_list, ep_rt_session_provider_list_t, EventPipeSessionProvider *) -EP_RT_DECLARE_LIST_ITERATOR (session_provider_list, ep_rt_session_provider_list_t, ep_rt_session_provider_list_iterator_t, EventPipeSessionProvider *) - -static -EventPipeSessionProvider * -ep_rt_session_provider_list_find_by_name ( - const ep_rt_session_provider_list_t *list, - const ep_char8_t *name); - -/* - * EventPipeSequencePoint. - */ - -EP_RT_DECLARE_LIST (sequence_point_list, ep_rt_sequence_point_list_t, EventPipeSequencePoint *) -EP_RT_DECLARE_LIST_ITERATOR (sequence_point_list, ep_rt_sequence_point_list_t, ep_rt_sequence_point_list_iterator_t, EventPipeSequencePoint *) - -/* - * EventPipeThread. - */ - -EP_RT_DECLARE_LIST (thread_list, ep_rt_thread_list_t, EventPipeThread *) -EP_RT_DECLARE_LIST_ITERATOR (thread_list, ep_rt_thread_list_t, ep_rt_thread_list_iterator_t, EventPipeThread *) - -EP_RT_DECLARE_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) -EP_RT_DECLARE_LOCAL_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) -EP_RT_DECLARE_ARRAY_ITERATOR (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *) - -#define EP_RT_DECLARE_LOCAL_THREAD_ARRAY(var_name) ds_rt_redefine - -/* - * EventPipeThreadSessionState. - */ - -EP_RT_DECLARE_LIST (thread_session_state_list, ep_rt_thread_session_state_list_t, EventPipeThreadSessionState *) -EP_RT_DECLARE_LIST_ITERATOR (thread_session_state_list, ep_rt_thread_session_state_list_t, ep_rt_thread_session_state_list_iterator_t, EventPipeThreadSessionState *) - -EP_RT_DECLARE_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) -EP_RT_DECLARE_LOCAL_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) -EP_RT_DECLARE_ARRAY_ITERATOR (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *) - -#define EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY(var_name) ds_rt_redefine - -/* * Arrays. */ @@ -539,7 +282,7 @@ ep_rt_is_running (void); static void -ep_rt_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints); +ep_rt_execute_rundown (dn_vector_ptr_t *execution_checkpoints); /* * Objects. @@ -651,13 +394,9 @@ ep_rt_temp_path_get ( ep_char8_t *buffer, uint32_t buffer_len); - -EP_RT_DECLARE_ARRAY (env_array_utf16_, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *) -EP_RT_DECLARE_ARRAY_ITERATOR (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *) - static void -ep_rt_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array); +ep_rt_os_environment_get_utf16 (dn_vector_ptr_t *os_env); static const ep_char8_t * @@ -878,14 +617,6 @@ ep_rt_thread_set_activity_id ( uint32_t activity_id_len); /* - * ThreadSequenceNumberMap. - */ - -EP_RT_DECLARE_HASH_MAP_REMOVE(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, EventPipeThreadSessionState *, uint32_t) -EP_RT_DECLARE_HASH_MAP_ITERATOR(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, ep_rt_thread_sequence_number_hash_map_iterator_t, EventPipeThreadSessionState *, uint32_t) - - -/* * Volatile. */ diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 99682b6..c4bbdf5 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -13,19 +13,38 @@ static void +DN_CALLBACK_CALLTYPE session_provider_free_func (void *session_provider); +static +bool +DN_CALLBACK_CALLTYPE +session_provider_compare_name_func ( + const void *a, + const void *b); + /* * EventPipeSessionProvider. */ static void +DN_CALLBACK_CALLTYPE session_provider_free_func (void *session_provider) { ep_session_provider_free ((EventPipeSessionProvider *)session_provider); } +static +bool +DN_CALLBACK_CALLTYPE +session_provider_compare_name_func ( + const void *a, + const void *b) +{ + return (a) ? !ep_rt_utf8_string_compare (ep_session_provider_get_provider_name ((EventPipeSessionProvider *)a), (const ep_char8_t *)b) : false; +} + EventPipeSessionProvider * ep_session_provider_alloc ( const ep_char8_t *provider_name, @@ -82,8 +101,8 @@ ep_session_provider_list_alloc ( EventPipeSessionProviderList *instance = ep_rt_object_alloc (EventPipeSessionProviderList); ep_raise_error_if_nok (instance != NULL); - ep_rt_session_provider_list_alloc (&instance->providers); - ep_raise_error_if_nok (ep_rt_session_provider_list_is_valid (&instance->providers)); + instance->providers = dn_list_alloc (); + ep_raise_error_if_nok (instance->providers != NULL); instance->catch_all_provider = NULL; @@ -104,7 +123,7 @@ ep_session_provider_list_alloc ( ep_provider_config_get_keywords (config), ep_provider_config_get_logging_level (config), ep_provider_config_get_filter_data (config)); - ep_raise_error_if_nok (ep_rt_session_provider_list_append (&instance->providers, session_provider)); + ep_raise_error_if_nok (dn_list_push_back (instance->providers, session_provider)); } } @@ -122,7 +141,7 @@ ep_session_provider_list_free (EventPipeSessionProviderList *session_provider_li { ep_return_void_if_nok (session_provider_list != NULL); - ep_rt_session_provider_list_free (&session_provider_list->providers, session_provider_free_func); + dn_list_custom_free (session_provider_list->providers, session_provider_free_func); ep_session_provider_free (session_provider_list->catch_all_provider); ep_rt_object_free (session_provider_list); } @@ -131,14 +150,14 @@ void ep_session_provider_list_clear (EventPipeSessionProviderList *session_provider_list) { EP_ASSERT (session_provider_list != NULL); - ep_rt_session_provider_list_clear (&session_provider_list->providers, session_provider_free_func); + dn_list_custom_clear (session_provider_list->providers, session_provider_free_func); } bool ep_session_provider_list_is_empty (const EventPipeSessionProviderList *session_provider_list) { EP_ASSERT (session_provider_list != NULL); - return (ep_rt_session_provider_list_is_empty (&session_provider_list->providers) && session_provider_list->catch_all_provider == NULL); + return (dn_list_empty (session_provider_list->providers) && session_provider_list->catch_all_provider == NULL); } bool @@ -149,7 +168,16 @@ ep_session_provider_list_add_session_provider ( EP_ASSERT (session_provider_list != NULL); EP_ASSERT (session_provider != NULL); - return ep_rt_session_provider_list_append (&session_provider_list->providers, session_provider); + return dn_list_push_back (session_provider_list->providers, session_provider); +} + +EventPipeSessionProvider * +ep_session_provider_list_find_by_name ( + dn_list_t *list, + const ep_char8_t *name) +{ + dn_list_it_t found = dn_list_custom_find (list, name, session_provider_compare_name_func); + return (!dn_list_it_end (found)) ? *dn_list_it_data_t(found, EventPipeSessionProvider *) : NULL; } #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index f8ba291..31852c7 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -55,7 +55,7 @@ struct _EventPipeSessionProviderList { #else struct _EventPipeSessionProviderList_Internal { #endif - ep_rt_session_provider_list_t providers; + dn_list_t *providers; EventPipeSessionProvider *catch_all_provider; }; @@ -65,7 +65,7 @@ struct _EventPipeSessionProviderList { }; #endif -EP_DEFINE_GETTER_REF(EventPipeSessionProviderList *, session_provider_list, ep_rt_session_provider_list_t *, providers) +EP_DEFINE_GETTER(EventPipeSessionProviderList *, session_provider_list, dn_list_t *, providers) EP_DEFINE_GETTER(EventPipeSessionProviderList *, session_provider_list, EventPipeSessionProvider *, catch_all_provider) EventPipeSessionProviderList * @@ -87,5 +87,10 @@ ep_session_provider_list_add_session_provider ( EventPipeSessionProviderList *session_provider_list, EventPipeSessionProvider *session_provider); +EventPipeSessionProvider * +ep_session_provider_list_find_by_name ( + dn_list_t *list, + const ep_char8_t *name); + #endif /* ENABLE_PERFTRACING */ #endif /** __EVENTPIPE_SESSION_PROVIDER_H__ **/ diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index f7069c3..e2f1227 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -251,7 +251,7 @@ ep_session_get_session_provider ( if (catch_all) return catch_all; - EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_ref (providers), ep_provider_get_provider_name (provider)); + EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (providers), ep_provider_get_provider_name (provider)); ep_requires_lock_held (); return session_provider; @@ -312,7 +312,7 @@ ep_on_error: void ep_session_execute_rundown ( EventPipeSession *session, - ep_rt_execution_checkpoint_array_t *execution_checkpoints) + dn_vector_ptr_t *execution_checkpoints) { EP_ASSERT (session != NULL); @@ -332,26 +332,29 @@ ep_session_suspend_write_event (EventPipeSession *session) // Need to disable the session before calling this method. EP_ASSERT (!ep_is_session_enabled ((EventPipeSessionID)session)); - EP_RT_DECLARE_LOCAL_THREAD_ARRAY (threads); - ep_rt_thread_array_init (&threads); + DN_DEFAULT_LOCAL_ALLOCATOR (allocator, dn_vector_ptr_default_local_allocator_byte_size); - ep_thread_get_threads (&threads); + dn_vector_ptr_custom_init_params_t params = {0, }; + params.allocator = (dn_allocator_t *)&allocator; + params.capacity = dn_vector_ptr_buffer_capacity (dn_vector_ptr_default_local_allocator_byte_size); - ep_rt_thread_array_iterator_t threads_iterator = ep_rt_thread_array_iterator_begin (&threads); - while (!ep_rt_thread_array_iterator_end (&threads, &threads_iterator)) { - EventPipeThread *thread = ep_rt_thread_array_iterator_value (&threads_iterator); - if (thread) { - // Wait for the thread to finish any writes to this session - EP_YIELD_WHILE (ep_thread_get_session_write_in_progress (thread) == session->index); + dn_vector_ptr_t threads; - // Since we've already disabled the session, the thread won't call back in to this - // session once its done with the current write - ep_thread_release (thread); - } - ep_rt_thread_array_iterator_next (&threads_iterator); - } + if (dn_vector_ptr_custom_init (&threads, ¶ms)) { + ep_thread_get_threads (&threads); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeThread *, thread, &threads) { + if (thread) { + // Wait for the thread to finish any writes to this session + EP_YIELD_WHILE (ep_thread_get_session_write_in_progress (thread) == session->index); - ep_rt_thread_array_fini (&threads); + // Since we've already disabled the session, the thread won't call back in to this + // session once its done with the current write + ep_thread_release (thread); + } + } DN_VECTOR_PTR_FOREACH_END; + + dn_vector_ptr_dispose (&threads); + } if (session->buffer_manager) // Convert all buffers to read only to ensure they get flushed diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index 36879e2..c7923cb 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -110,7 +110,7 @@ ep_session_enable_rundown (EventPipeSession *session); void ep_session_execute_rundown ( EventPipeSession *session, - ep_rt_execution_checkpoint_array_t *execution_checkpoints); + dn_vector_ptr_t *execution_checkpoints); // Force all in-progress writes to either finish or cancel // This is required to ensure we can safely flush and delete the buffers diff --git a/src/native/eventpipe/ep-stream.h b/src/native/eventpipe/ep-stream.h index fdb41ae..dc3e546 100644 --- a/src/native/eventpipe/ep-stream.h +++ b/src/native/eventpipe/ep-stream.h @@ -5,6 +5,7 @@ #ifdef ENABLE_PERFTRACING #include "ep-types.h" +#include "ep-rt.h" #undef EP_IMPL_GETTER_SETTER #ifdef EP_IMPL_STREAM_GETTER_SETTER diff --git a/src/native/eventpipe/ep-thread.c b/src/native/eventpipe/ep-thread.c index 0f2eac6..234b829 100644 --- a/src/native/eventpipe/ep-thread.c +++ b/src/native/eventpipe/ep-thread.c @@ -11,7 +11,7 @@ #include "ep-rt.h" static ep_rt_spin_lock_handle_t _ep_threads_lock = {0}; -static ep_rt_thread_list_t _ep_threads = {0}; +static dn_list_t *_ep_threads = NULL; /* * Forward declares of all static functions. @@ -88,8 +88,8 @@ ep_thread_init (void) if (!ep_rt_spin_lock_is_valid (&_ep_threads_lock)) EP_UNREACHABLE ("Failed to allocate threads lock."); - ep_rt_thread_list_alloc (&_ep_threads); - if (!ep_rt_thread_list_is_valid (&_ep_threads)) + _ep_threads = dn_list_alloc (); + if (!_ep_threads) EP_UNREACHABLE ("Failed to allocate threads list."); } @@ -99,8 +99,9 @@ ep_thread_fini (void) // If threads are still included in list (depending on runtime shutdown order), // don't clean up since TLS destructor migh callback freeing items, no new // threads should however not be added to list at this stage. - if (ep_rt_thread_list_is_empty (&_ep_threads)) { - ep_rt_thread_list_free (&_ep_threads, NULL); + if (dn_list_empty (_ep_threads)) { + dn_list_free (_ep_threads); + _ep_threads = NULL; ep_rt_spin_lock_free (&_ep_threads_lock); } } @@ -117,7 +118,7 @@ ep_thread_register (EventPipeThread *thread) ep_thread_addref (thread); ep_rt_spin_lock_acquire (&_ep_threads_lock); - result = ep_rt_thread_list_append (&_ep_threads, thread); + result = dn_list_push_back (_ep_threads, thread); ep_rt_spin_lock_release (&_ep_threads_lock); if (!result) @@ -138,17 +139,15 @@ ep_thread_unregister (EventPipeThread *thread) bool found = false; EP_SPIN_LOCK_ENTER (&_ep_threads_lock, section1) // Remove ourselves from the global list - ep_rt_thread_list_iterator_t iterator = ep_rt_thread_list_iterator_begin (&_ep_threads); - while (!ep_rt_thread_list_iterator_end (&_ep_threads, &iterator)) { - if (ep_rt_thread_list_iterator_value (&iterator) == thread) { - ep_rt_thread_list_remove (&_ep_threads, thread); + DN_LIST_FOREACH_BEGIN (EventPipeThread *, current_thread, _ep_threads) { + if (current_thread == thread) { + dn_list_remove (_ep_threads, thread); ep_rt_volatile_store_uint32_t(&thread->unregistered, 1); ep_thread_release (thread); found = true; break; } - ep_rt_thread_list_iterator_next (&iterator); - } + } DN_LIST_FOREACH_END; EP_SPIN_LOCK_EXIT (&_ep_threads_lock, section1) EP_ASSERT (found || !"We couldn't find ourselves in the global thread list"); @@ -174,21 +173,18 @@ ep_thread_get_or_create (void) } void -ep_thread_get_threads (ep_rt_thread_array_t *threads) +ep_thread_get_threads (dn_vector_ptr_t *threads) { EP_ASSERT (threads != NULL); EP_SPIN_LOCK_ENTER (&_ep_threads_lock, section1) - ep_rt_thread_list_iterator_t threads_iterator = ep_rt_thread_list_iterator_begin (&_ep_threads); - while (!ep_rt_thread_list_iterator_end (&_ep_threads, &threads_iterator)) { - EventPipeThread *thread = ep_rt_thread_list_iterator_value (&threads_iterator); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeThread *, thread, threads) { if (thread) { // Add ref so the thread doesn't disappear when we release the lock ep_thread_addref (thread); - ep_rt_thread_array_append (threads, thread); + dn_vector_ptr_push_back (threads, thread); } - ep_rt_thread_list_iterator_next (&threads_iterator); - } + } DN_VECTOR_PTR_FOREACH_END; EP_SPIN_LOCK_EXIT (&_ep_threads_lock, section1) ep_on_exit: diff --git a/src/native/eventpipe/ep-thread.h b/src/native/eventpipe/ep-thread.h index 604840e..c3f8fd7 100644 --- a/src/native/eventpipe/ep-thread.h +++ b/src/native/eventpipe/ep-thread.h @@ -108,7 +108,7 @@ EventPipeThread * ep_thread_get_or_create (void); void -ep_thread_get_threads (ep_rt_thread_array_t *threads); +ep_thread_get_threads (dn_vector_ptr_t *threads); static inline diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 71a0a28..3085659 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -199,7 +199,7 @@ typedef void (*EventPipeSessionSynchronousCallback)( /*ep_rt_thread_handle_t*/ void *event_thread, uint32_t stack_frames_len, uintptr_t *stack_frames, - void *additional_data); + void *additional_data); typedef bool (*EventPipeIpcStreamFactorySuspendedPortsCallback)(void); diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index 6f61454..5273f2b 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -14,6 +14,12 @@ #include "ep-rt-types.h" +#include +#include +#include +#include +#include + /* * EventFilterDescriptor. */ @@ -138,7 +144,7 @@ struct _EventPipeProviderCallbackDataQueue { #else struct _EventPipeProviderCallbackDataQueue_Internal { #endif - ep_rt_provider_callback_data_queue_t queue; + dn_queue_t *queue; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) @@ -147,7 +153,7 @@ struct _EventPipeProviderCallbackDataQueue { }; #endif -EP_DEFINE_GETTER_REF(EventPipeProviderCallbackDataQueue *, provider_callback_data_queue, ep_rt_provider_callback_data_queue_t *, queue) +EP_DEFINE_GETTER(EventPipeProviderCallbackDataQueue *, provider_callback_data_queue, dn_queue_t *, queue) EventPipeProviderCallbackDataQueue * ep_provider_callback_data_queue_init (EventPipeProviderCallbackDataQueue *provider_callback_data_queue); diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index dae4281..dd327ef 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -17,12 +17,12 @@ static bool _ep_can_start_threads = false; -static ep_rt_session_id_array_t _ep_deferred_enable_session_ids = { 0 }; -static ep_rt_session_id_array_t _ep_deferred_disable_session_ids = { 0 }; +static dn_vector_t *_ep_deferred_enable_session_ids = NULL; +static dn_vector_t *_ep_deferred_disable_session_ids = NULL; static EventPipeIpcStreamFactorySuspendedPortsCallback _ep_ipc_stream_factory_suspended_ports_callback = NULL; -static ep_rt_execution_checkpoint_array_t _ep_rundown_execution_checkpoints = { 0 }; +static dn_vector_ptr_t *_ep_rundown_execution_checkpoints = NULL; /* * Forward declares of all static functions. @@ -195,15 +195,16 @@ EventPipeProviderCallbackDataQueue * ep_provider_callback_data_queue_init (EventPipeProviderCallbackDataQueue *provider_callback_data_queue) { EP_ASSERT (provider_callback_data_queue != NULL); - ep_rt_provider_callback_data_queue_alloc (&provider_callback_data_queue->queue); - return ep_rt_provider_callback_data_queue_is_valid (&provider_callback_data_queue->queue) ? provider_callback_data_queue : NULL; + provider_callback_data_queue->queue = dn_queue_alloc (); + return provider_callback_data_queue->queue ? provider_callback_data_queue : NULL; } void ep_provider_callback_data_queue_fini (EventPipeProviderCallbackDataQueue *provider_callback_data_queue) { ep_return_void_if_nok (provider_callback_data_queue != NULL); - ep_rt_provider_callback_data_queue_free (&provider_callback_data_queue->queue); + dn_queue_free (provider_callback_data_queue->queue); + provider_callback_data_queue->queue = NULL; } /* @@ -592,7 +593,7 @@ disable_holding_lock ( { config_enable_disable (ep_config_get (), session, provider_callback_data_queue, true); { - ep_session_execute_rundown (session, &_ep_rundown_execution_checkpoints); + ep_session_execute_rundown (session, _ep_rundown_execution_checkpoints); } config_enable_disable(ep_config_get (), session, provider_callback_data_queue, false); } @@ -922,7 +923,7 @@ bool session_requested_sampling (EventPipeSession *session) { EP_ASSERT (session != NULL); - return ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (ep_session_get_providers (session)), ep_config_get_sample_profiler_provider_name_utf8 ()); + return ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (ep_session_get_providers (session)), ep_config_get_sample_profiler_provider_name_utf8 ()); } static @@ -1130,7 +1131,7 @@ ep_disable (EventPipeSessionID id) EP_LOCK_ENTER (section1) if (!_ep_can_start_threads && !ipc_stream_factory_any_suspended_ports ()) { - ep_rt_session_id_array_append (&_ep_deferred_disable_session_ids, id); + dn_vector_push_back (_ep_deferred_disable_session_ids, id); ep_raise_error_holding_lock (section1); } EP_LOCK_EXIT (section1) @@ -1187,7 +1188,7 @@ ep_start_streaming (EventPipeSessionID session_id) if (_ep_can_start_threads) ep_session_start_streaming ((EventPipeSession *)(uintptr_t)session_id); else - ep_rt_session_id_array_append (&_ep_deferred_enable_session_ids, session_id); + dn_vector_push_back (_ep_deferred_enable_session_ids, session_id); EP_LOCK_EXIT (section1) ep_on_exit: @@ -1350,10 +1351,13 @@ ep_init (void) const uint32_t default_profiler_sample_rate_in_nanoseconds = 1000000; // 1 msec. ep_sample_profiler_set_sampling_rate (default_profiler_sample_rate_in_nanoseconds); - ep_rt_session_id_array_alloc (&_ep_deferred_enable_session_ids); - ep_rt_session_id_array_alloc (&_ep_deferred_disable_session_ids); + _ep_deferred_enable_session_ids = dn_vector_alloc_t (EventPipeSessionID); + _ep_deferred_disable_session_ids = dn_vector_alloc_t (EventPipeSessionID); - ep_rt_execution_checkpoint_array_alloc (&_ep_rundown_execution_checkpoints); + ep_raise_error_if_nok (_ep_deferred_enable_session_ids && _ep_deferred_disable_session_ids); + + _ep_rundown_execution_checkpoints = dn_vector_ptr_alloc (); + ep_raise_error_if_nok (_ep_rundown_execution_checkpoints); EP_LOCK_ENTER (section1) ep_volatile_store_eventpipe_state (EP_STATE_INITIALIZED); @@ -1380,14 +1384,13 @@ ep_finish_init (void) EP_LOCK_ENTER (section1) _ep_can_start_threads = true; if (ep_volatile_load_eventpipe_state () == EP_STATE_INITIALIZED) { - ep_rt_session_id_array_iterator_t deferred_session_ids_iterator = ep_rt_session_id_array_iterator_begin (&_ep_deferred_enable_session_ids); - while (!ep_rt_session_id_array_iterator_end (&_ep_deferred_enable_session_ids, &deferred_session_ids_iterator)) { - EventPipeSessionID session_id = ep_rt_session_id_array_iterator_value (&deferred_session_ids_iterator); - if (is_session_id_in_collection (session_id)) - ep_session_start_streaming ((EventPipeSession *)(uintptr_t)session_id); - ep_rt_session_id_array_iterator_next (&deferred_session_ids_iterator); + if (_ep_deferred_enable_session_ids) { + DN_VECTOR_FOREACH_BEGIN (EventPipeSessionID, session_id, _ep_deferred_enable_session_ids) { + if (is_session_id_in_collection (session_id)) + ep_session_start_streaming ((EventPipeSession *)(uintptr_t)session_id); + } DN_VECTOR_FOREACH_END; + dn_vector_clear (_ep_deferred_enable_session_ids); } - ep_rt_session_id_array_clear (&_ep_deferred_enable_session_ids); } ep_sample_profiler_can_start_sampling (); @@ -1398,13 +1401,12 @@ ep_finish_init (void) // lock since we've set _ep_can_start_threads to true inside the lock. Anyone // who was waiting on that lock will see that state and not mutate the defer list if (ep_volatile_load_eventpipe_state () == EP_STATE_INITIALIZED) { - ep_rt_session_id_array_iterator_t deferred_disable_session_ids_iterator = ep_rt_session_id_array_iterator_begin (&_ep_deferred_disable_session_ids); - while (!ep_rt_session_id_array_iterator_end (&_ep_deferred_disable_session_ids, &deferred_disable_session_ids_iterator)) { - EventPipeSessionID session_id = ep_rt_session_id_array_iterator_value (&deferred_disable_session_ids_iterator); - disable_helper (session_id); - ep_rt_session_id_array_iterator_next (&deferred_disable_session_ids_iterator); + if (_ep_deferred_disable_session_ids) { + DN_VECTOR_FOREACH_BEGIN (EventPipeSessionID, session_id, _ep_deferred_disable_session_ids) { + disable_helper (session_id); + } DN_VECTOR_FOREACH_END; + dn_vector_clear (_ep_deferred_disable_session_ids); } - ep_rt_session_id_array_clear (&_ep_deferred_disable_session_ids); } ep_on_exit: @@ -1434,19 +1436,20 @@ ep_shutdown (void) ep_disable ((EventPipeSessionID)session); } - ep_rt_execution_checkpoint_array_iterator_t checkpoint_iterator; - EventPipeExecutionCheckpoint *checkpoint; - checkpoint_iterator = ep_rt_execution_checkpoint_array_iterator_begin (&_ep_rundown_execution_checkpoints); - while (!ep_rt_execution_checkpoint_array_iterator_end (&_ep_rundown_execution_checkpoints, &checkpoint_iterator)) { - checkpoint = ep_rt_execution_checkpoint_array_iterator_value (&checkpoint_iterator); - if (checkpoint) - ep_rt_utf8_string_free (checkpoint->name); - ep_rt_execution_checkpoint_array_iterator_next (&checkpoint_iterator); + if (_ep_rundown_execution_checkpoints) { + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeExecutionCheckpoint *, checkpoint, _ep_rundown_execution_checkpoints) { + if (checkpoint) + ep_rt_utf8_string_free (checkpoint->name); + } DN_VECTOR_PTR_FOREACH_END; + dn_vector_ptr_free (_ep_rundown_execution_checkpoints); + _ep_rundown_execution_checkpoints = NULL; } - ep_rt_execution_checkpoint_array_free (&_ep_rundown_execution_checkpoints); - ep_rt_session_id_array_free (&_ep_deferred_enable_session_ids); - ep_rt_session_id_array_free (&_ep_deferred_disable_session_ids); + dn_vector_free (_ep_deferred_enable_session_ids); + _ep_deferred_enable_session_ids = NULL; + + dn_vector_free (_ep_deferred_disable_session_ids); + _ep_deferred_disable_session_ids = NULL; ep_thread_fini (); @@ -1574,7 +1577,7 @@ ep_add_rundown_execution_checkpoint ( ep_raise_error_if_nok (exec_checkpoint != NULL); EP_LOCK_ENTER (section1) - ep_raise_error_if_nok_holding_lock (ep_rt_execution_checkpoint_array_append (&_ep_rundown_execution_checkpoints, exec_checkpoint), section1); + ep_raise_error_if_nok_holding_lock (dn_vector_ptr_push_back (_ep_rundown_execution_checkpoints, exec_checkpoint), section1); exec_checkpoint = NULL; EP_LOCK_EXIT (section1) @@ -1602,7 +1605,7 @@ ep_provider_callback_data_queue_enqueue ( EP_ASSERT (provider_callback_data_queue != NULL); EventPipeProviderCallbackData *provider_callback_data_move = ep_provider_callback_data_alloc_move (provider_callback_data); ep_raise_error_if_nok (provider_callback_data_move != NULL); - ep_raise_error_if_nok (ep_rt_provider_callback_data_queue_push_tail (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), provider_callback_data_move)); + ep_raise_error_if_nok (dn_queue_push (ep_provider_callback_data_queue_get_queue (provider_callback_data_queue), provider_callback_data_move)); return true; @@ -1618,10 +1621,13 @@ ep_provider_callback_data_queue_try_dequeue ( { EP_ASSERT (provider_callback_data_queue != NULL); - ep_return_false_if_nok (!ep_rt_provider_callback_data_queue_is_empty (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue))); + dn_queue_t *queue = ep_provider_callback_data_queue_get_queue (provider_callback_data_queue); + ep_return_false_if_nok (!dn_queue_empty (queue)); + + EventPipeProviderCallbackData *value = *dn_queue_front_t (queue, EventPipeProviderCallbackData *); + dn_queue_pop (queue); - EventPipeProviderCallbackData *value = NULL; - ep_raise_error_if_nok (ep_rt_provider_callback_data_queue_pop_head (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), &value)); + ep_raise_error_if_nok (value != NULL); ep_provider_callback_data_init_move (provider_callback_data, value); ep_provider_callback_data_free (value); diff --git a/src/native/eventpipe/CMakeLists.txt b/src/native/eventpipe/eventpipe.cmake similarity index 100% rename from src/native/eventpipe/CMakeLists.txt rename to src/native/eventpipe/eventpipe.cmake -- 2.7.4