|
2 | 2 | // This file is part of the "Nabla Engine" and was originally part of the "Irrlicht Engine"
|
3 | 3 | // For conditions of distribution and use, see copyright notice in nabla.h
|
4 | 4 | // See the original file in irrlicht source for authors
|
5 |
| - |
6 | 5 | #ifndef _NBL_SYSTEM_C_FILE_ARCHIVE_H_INCLUDED_
|
7 | 6 | #define _NBL_SYSTEM_C_FILE_ARCHIVE_H_INCLUDED_
|
8 | 7 |
|
| 8 | + |
9 | 9 | #include "nbl/system/IFileArchive.h"
|
10 | 10 | #include "nbl/system/CFileView.h"
|
11 | 11 | #include "nbl/system/IFileViewAllocator.h"
|
12 | 12 |
|
| 13 | + |
13 | 14 | namespace nbl::system
|
14 | 15 | {
|
15 | 16 |
|
@@ -58,62 +59,74 @@ class CFileArchive : public IFileArchive
|
58 | 59 | static inline constexpr size_t ALIGNOF_INNER_ARCHIVE_FILE = std::max(alignof(CInnerArchiveFile<CPlainHeapAllocator>), alignof(CInnerArchiveFile<VirtualMemoryAllocator>));
|
59 | 60 |
|
60 | 61 | public:
|
61 |
| - core::smart_refctd_ptr<IFile> readFile(const SOpenFileParams& params) |
| 62 | + inline core::smart_refctd_ptr<IFile> getFile(const path& pathRelativeToArchive, const std::string_view& password) override |
62 | 63 | {
|
63 |
| - auto index = getIndexByPath(params.filename); |
64 |
| - if (index == -1) return nullptr; |
65 |
| - switch (listAssets()[index].allocatorType) |
| 64 | + std::unique_lock lock(itemMutex); |
| 65 | + |
| 66 | + const auto* item = getItemFromPath(pathRelativeToArchive); |
| 67 | + if (!item) |
| 68 | + return nullptr; |
| 69 | + /* |
| 70 | + switch (item->allocatorType) |
66 | 71 | {
|
67 |
| - case EAT_NULL: |
68 |
| - return getFile_impl<CNullAllocator>(params, index); |
69 |
| - break; |
70 |
| - case EAT_MALLOC: |
71 |
| - return getFile_impl<CPlainHeapAllocator>(params, index); |
72 |
| - break; |
73 |
| - case EAT_VIRTUAL_ALLOC: |
74 |
| - return getFile_impl<VirtualMemoryAllocator>(params, index); |
75 |
| - break; |
| 72 | + case EAT_NULL: |
| 73 | + return getFile_impl<CNullAllocator>(item); |
| 74 | + break; |
| 75 | + case EAT_MALLOC: |
| 76 | + return getFile_impl<CPlainHeapAllocator>(item); |
| 77 | + break; |
| 78 | + case EAT_VIRTUAL_ALLOC: |
| 79 | + return getFile_impl<VirtualMemoryAllocator>(item); |
| 80 | + break; |
| 81 | + default: // directory or something |
| 82 | + break; |
76 | 83 | }
|
77 |
| - assert(false); |
| 84 | + */ |
78 | 85 | return nullptr;
|
79 | 86 | }
|
80 |
| - virtual core::smart_refctd_ptr<IFile> readFile_impl(const SOpenFileParams& params) = 0; |
81 |
| - int32_t getIndexByPath(const system::path& p) |
| 87 | + |
| 88 | + protected: |
| 89 | + CFileArchive(path&& _defaultAbsolutePath, system::logger_opt_smart_ptr&& logger, core::vector<SListEntry> _items) : |
| 90 | + IFileArchive(std::move(_defaultAbsolutePath),std::move(logger)) |
82 | 91 | {
|
83 |
| - for (int i = 0; i < m_files.size(); ++i) |
84 |
| - { |
85 |
| - if (p == m_files[i].fullName) return i; |
86 |
| - } |
87 |
| - return -1; |
| 92 | + m_items = std::move(_items); |
| 93 | + std::sort(m_items.begin(),m_items.end()); |
| 94 | + |
| 95 | + const auto fileCount = m_items.size(); |
| 96 | + m_filesBuffer = (std::byte*)_NBL_ALIGNED_MALLOC(fileCount*SIZEOF_INNER_ARCHIVE_FILE, ALIGNOF_INNER_ARCHIVE_FILE); |
| 97 | + m_fileFlags = (std::atomic_flag*)_NBL_ALIGNED_MALLOC(fileCount*sizeof(std::atomic_flag), alignof(std::atomic_flag)); |
| 98 | + for (size_t i=0u; i<fileCount; i++) |
| 99 | + m_fileFlags[i].clear(); |
| 100 | + memset(m_filesBuffer,0,fileCount*SIZEOF_INNER_ARCHIVE_FILE); |
88 | 101 | }
|
| 102 | + ~CFileArchive() |
| 103 | + { |
| 104 | + _NBL_ALIGNED_FREE(m_filesBuffer); |
| 105 | + _NBL_ALIGNED_FREE(m_fileFlags); |
| 106 | + } |
| 107 | + /* |
89 | 108 | template<class Allocator>
|
90 |
| - core::smart_refctd_ptr<CInnerArchiveFile<Allocator>> getFile_impl(const SOpenFileParams& params, const uint32_t index) |
| 109 | + core::smart_refctd_ptr<CInnerArchiveFile<Allocator>> getFile_impl(const IFileArchive::SListEntry* item) |
91 | 110 | {
|
92 |
| - std::unique_lock lock(fileMutex); |
93 |
| - |
94 |
| - auto* file = reinterpret_cast<CInnerArchiveFile<Allocator>*>(m_filesBuffer + index * SIZEOF_INNER_ARCHIVE_FILE); |
95 |
| - // intentionally calling grab() on maybe-not-existing object |
| 111 | + auto* file = reinterpret_cast<CInnerArchiveFile<Allocator>*>(m_filesBuffer+item->ID*SIZEOF_INNER_ARCHIVE_FILE); |
| 112 | + // NOTE: Intentionally calling grab() on maybe-not-existing object! |
96 | 113 | const auto oldRefcount = file->grab();
|
97 | 114 |
|
98 |
| - if (oldRefcount == 0) // need to construct |
| 115 | + if (oldRefcount==0) // need to construct (previous refcount was 0) |
99 | 116 | {
|
100 |
| - m_fileFlags[index].wait(true); //what should the param of wait be? |
101 |
| - new (file, &m_fileFlags[index]) CInnerArchiveFile<Allocator>(static_cast<CFileView<Allocator>*>(readFile_impl(params).get()), &m_fileFlags[index]); |
| 117 | + // Might have barged inbetween a refctr drop and finish of a destructor + delete, |
| 118 | + // need to wait for the "alive" flag to become `false` which tells us `operator delete` has finished. |
| 119 | + m_fileFlags[item->ID].wait(true); |
| 120 | + // coast is clear, do placement new |
| 121 | + new (file, &m_fileFlags[item->ID]) CInnerArchiveFile<Allocator>( |
| 122 | + static_cast<CFileView<Allocator>*>(readFile_impl(params).get()), |
| 123 | + &m_fileFlags[item->ID] |
| 124 | + ); |
102 | 125 | }
|
103 |
| - return core::smart_refctd_ptr<CInnerArchiveFile<Allocator>>(file, core::dont_grab); |
| 126 | + return core::smart_refctd_ptr<CInnerArchiveFile<Allocator>>(file,core::dont_grab); |
104 | 127 | }
|
| 128 | + */ |
105 | 129 |
|
106 |
| - protected: |
107 |
| - CFileArchive(core::smart_refctd_ptr<IFile>&& file, system::logger_opt_smart_ptr&& logger) : IFileArchive(std::move(file),std::move(logger)) {} |
108 |
| - ~CFileArchive() |
109 |
| - { |
110 |
| - _NBL_ALIGNED_FREE(m_filesBuffer); |
111 |
| - _NBL_ALIGNED_FREE(m_fileFlags); |
112 |
| - } |
113 |
| - |
114 |
| - void setFlagsVectorSize(size_t fileCount); |
115 |
| - |
116 |
| - std::mutex fileMutex; |
117 | 130 | std::atomic_flag* m_fileFlags = nullptr;
|
118 | 131 | std::byte* m_filesBuffer = nullptr;
|
119 | 132 | };
|
|
0 commit comments