Files
Bigfoot/Bigfoot/Libs/System/File/MemoryMappedFile.cpp
T
rboullard f82d40532c
Bigfoot / Sonarqube (game) (push) Skipped
Bigfoot / Sonarqube (toolmode) (push) Skipped
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Failing after 12s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Failing after 11s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Failing after 10s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Failing after 9s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 10s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 10s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 15s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Failing after 9s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 10s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Failing after 11s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Failing after 10s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Failing after 9s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Failing after 10s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 11s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Failing after 10s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 10s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Failing after 10s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Failing after 9s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Failing after 10s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Failing after 9s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 11s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 12s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Failing after 10s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 9s
Bigfoot / Clang Format Checks (push) Failing after 12s
Refactor Bigfoot files layout + Create our three graphics libraries
2026-09-03 00:02:09 +02:00

235 lines
8.6 KiB
C++

/*********************************************************************
* \file MemoryMappedFile.cpp
*
* \author Romain BOULLARD
* \date August 2026
*********************************************************************/
#include <System/File/MemoryMappedFile.hpp>
#include <System/SystemAssertHandler.hpp>
#include <string>
#ifdef BIGFOOT_WINDOWS
#include <Windows.h>
#elif defined BIGFOOT_LINUX
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
namespace Bigfoot
{
MemoryMappedFile::MemoryMappedFile(const File& p_file)
{
const File absoluteFile = p_file.ToAbsolute();
const eastl::string_view path = absoluteFile.GetPath();
#ifdef BIGFOOT_WINDOWS
m_fileHandle = CreateFileA(path.data(),
GENERIC_READ,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
nullptr);
CRITICAL_ASSERT(SystemAssertHandler, m_fileHandle != INVALID_HANDLE_VALUE, "Failed to open file {}", path);
LARGE_INTEGER fileSize {};
[[maybe_unused]]
const BOOL gotFileSize = GetFileSizeEx(m_fileHandle, &fileSize);
CRITICAL_ASSERT(SystemAssertHandler, gotFileSize, "Failed to get the size of file {}", path);
m_size = static_cast<std::size_t>(fileSize.QuadPart);
if (m_size != 0)
{
m_mappingHandle = CreateFileMappingA(m_fileHandle, nullptr, PAGE_READONLY, 0, 0, nullptr);
CRITICAL_ASSERT(SystemAssertHandler, m_mappingHandle != nullptr, "Failed create the file mapping {}", path);
m_data = static_cast<std::byte*>(MapViewOfFile(m_mappingHandle, FILE_MAP_READ, 0, 0, 0));
CRITICAL_ASSERT(SystemAssertHandler, m_data != nullptr, "Failed to map the file {}", path);
}
#elif defined BIGFOOT_LINUX
m_fileDescriptor = open(path.data(), O_RDONLY);
CRITICAL_ASSERT(SystemAssertHandler, m_fileDescriptor != -1, "Failed to open file {}", path);
struct stat fileStat {};
[[maybe_unused]]
const int statResult = fstat(m_fileDescriptor, &fileStat);
CRITICAL_ASSERT(SystemAssertHandler, statResult == 0, "Failed to get the size of file {}", path);
m_size = static_cast<std::size_t>(fileStat.st_size);
if (m_size != 0)
{
void* const mapped = mmap(nullptr, m_size, PROT_READ, MAP_PRIVATE, m_fileDescriptor, 0);
CRITICAL_ASSERT(SystemAssertHandler, mapped != MAP_FAILED, "Failed to map file {}", path);
m_data = static_cast<std::byte*>(mapped);
[[maybe_unused]]
const int adviseResult = madvise(mapped, m_size, MADV_RANDOM);
}
#else
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
#endif
}
/****************************************************************************************/
MemoryMappedFile::~MemoryMappedFile()
{
#ifdef BIGFOOT_WINDOWS
if (m_data != nullptr)
{
[[maybe_unused]]
const BOOL unmapped = UnmapViewOfFile(m_data);
CRITICAL_ASSERT(SystemAssertHandler, unmapped, "Failed to unmap the file");
}
if (m_mappingHandle != nullptr)
{
[[maybe_unused]]
const BOOL closedMapping = CloseHandle(m_mappingHandle);
CRITICAL_ASSERT(SystemAssertHandler, closedMapping, "Failed to close the file mapping");
}
if (m_fileHandle != INVALID_HANDLE_VALUE)
{
[[maybe_unused]]
const BOOL closedFile = CloseHandle(m_fileHandle);
CRITICAL_ASSERT(SystemAssertHandler, closedFile, "Failed to close the file");
}
#elif defined BIGFOOT_LINUX
if (m_data != nullptr)
{
[[maybe_unused]]
const int unmapped = munmap(m_data, m_size);
CRITICAL_ASSERT(SystemAssertHandler, unmapped == 0, "Failed to unmap the file");
}
if (m_fileDescriptor != -1)
{
[[maybe_unused]]
const int closedFile = close(m_fileDescriptor);
CRITICAL_ASSERT(SystemAssertHandler, closedFile == 0, "Failed to close the file");
}
#else
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
#endif
}
/****************************************************************************************/
eastl::span<const std::byte> MemoryMappedFile::GetData() const
{
return eastl::span<const std::byte> {m_data, m_size};
}
/****************************************************************************************/
WritableMemoryMappedFile::WritableMemoryMappedFile(const File& p_file, const std::size_t p_size):
m_size(p_size)
{
const File absoluteFile = p_file.ToAbsolute();
const eastl::string_view path = absoluteFile.GetPath();
#ifdef BIGFOOT_WINDOWS
m_fileHandle =
CreateFileA(path.data(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
CRITICAL_ASSERT(SystemAssertHandler, m_fileHandle != INVALID_HANDLE_VALUE, "Failed to create file {}", path);
const LARGE_INTEGER size {.QuadPart = static_cast<LONGLONG>(p_size)};
m_mappingHandle = CreateFileMappingA(m_fileHandle, nullptr, PAGE_READWRITE, size.HighPart, size.LowPart, nullptr);
CRITICAL_ASSERT(SystemAssertHandler, m_mappingHandle != nullptr, "Failed create the file mapping {}", path);
m_data = static_cast<std::byte*>(MapViewOfFile(m_mappingHandle, FILE_MAP_WRITE, 0, 0, 0));
CRITICAL_ASSERT(SystemAssertHandler, m_data != nullptr, "Failed to map the file {}", path);
#elif defined BIGFOOT_LINUX
m_fileDescriptor = open(path.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
CRITICAL_ASSERT(SystemAssertHandler, m_fileDescriptor != -1, "Failed to create file {}", path);
struct stat fileStat {};
fstat(m_fileDescriptor, &fileStat);
if (static_cast<std::size_t>(fileStat.st_size) < p_size)
{
[[maybe_unused]]
const int truncateResult = ftruncate(m_fileDescriptor, static_cast<off_t>(p_size));
CRITICAL_ASSERT(SystemAssertHandler, truncateResult == 0, "Failed to size file {}", path);
}
void* const mapped = mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fileDescriptor, 0);
CRITICAL_ASSERT(SystemAssertHandler, mapped != MAP_FAILED, "Failed to map file {}", path);
m_data = static_cast<std::byte*>(mapped);
#else
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
#endif
}
/****************************************************************************************/
WritableMemoryMappedFile::~WritableMemoryMappedFile()
{
#ifdef BIGFOOT_WINDOWS
if (m_data != nullptr)
{
[[maybe_unused]]
const BOOL unmapped = UnmapViewOfFile(m_data);
CRITICAL_ASSERT(SystemAssertHandler, unmapped, "Failed to unmap the file");
}
if (m_mappingHandle != nullptr)
{
[[maybe_unused]]
const BOOL closedMapping = CloseHandle(m_mappingHandle);
CRITICAL_ASSERT(SystemAssertHandler, closedMapping, "Failed to close the file mapping");
}
if (m_fileHandle != INVALID_HANDLE_VALUE)
{
[[maybe_unused]]
const BOOL closedFile = CloseHandle(m_fileHandle);
CRITICAL_ASSERT(SystemAssertHandler, closedFile, "Failed to close the file");
}
#elif defined BIGFOOT_LINUX
if (m_data != nullptr)
{
[[maybe_unused]]
const int unmapped = munmap(m_data, m_size);
CRITICAL_ASSERT(SystemAssertHandler, unmapped == 0, "Failed to unmap the file");
}
if (m_fileDescriptor != -1)
{
[[maybe_unused]]
const int closedFile = close(m_fileDescriptor);
CRITICAL_ASSERT(SystemAssertHandler, closedFile == 0, "Failed to close the file");
}
#else
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
#endif
}
/****************************************************************************************/
eastl::span<std::byte> WritableMemoryMappedFile::GetData() const
{
return eastl::span<std::byte> {m_data, m_size};
}
/****************************************************************************************/
void WritableMemoryMappedFile::Prefetch(const std::size_t p_offset, const std::size_t p_size) const
{
#ifdef BIGFOOT_WINDOWS
WIN32_MEMORY_RANGE_ENTRY range {.VirtualAddress = m_data + p_offset, .NumberOfBytes = p_size};
[[maybe_unused]]
const BOOL prefetched = PrefetchVirtualMemory(GetCurrentProcess(), 1, &range, 0);
#elif defined BIGFOOT_LINUX
[[maybe_unused]]
const int adviseResult = madvise(m_data + p_offset, p_size, MADV_WILLNEED);
#else
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
#endif
}
} // namespace Bigfoot