aboutsummaryrefslogtreecommitdiff
path: root/zencore
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-10-14 19:07:14 +0200
committerGitHub <[email protected]>2021-10-14 19:07:14 +0200
commit2b71d6a8d57c773bc7734b253a1ffd1e47162184 (patch)
treec0c70f9f2f8b9dc895080aac9f7de1140c56ebf0 /zencore
parentMerge branch 'main' of https://github.com/EpicGames/zen (diff)
downloadzen-2b71d6a8d57c773bc7734b253a1ffd1e47162184.tar.xz
zen-2b71d6a8d57c773bc7734b253a1ffd1e47162184.zip
asio HTTP implementation (#23)
asio-based HTTP implementation
Diffstat (limited to 'zencore')
-rw-r--r--zencore/include/zencore/iobuffer.h1
-rw-r--r--zencore/include/zencore/string.h22
-rw-r--r--zencore/include/zencore/thread.h3
-rw-r--r--zencore/iobuffer.cpp83
-rw-r--r--zencore/string.cpp7
-rw-r--r--zencore/thread.cpp55
6 files changed, 143 insertions, 28 deletions
diff --git a/zencore/include/zencore/iobuffer.h b/zencore/include/zencore/iobuffer.h
index 5fbeaeaeb..db462e238 100644
--- a/zencore/include/zencore/iobuffer.h
+++ b/zencore/include/zencore/iobuffer.h
@@ -374,6 +374,7 @@ public:
ZENCORE_API static IoBuffer MakeFromFile(const path_char_t* FileName, uint64_t Offset = 0, uint64_t Size = ~0ull);
ZENCORE_API static IoBuffer MakeFromTemporaryFile(const std::filesystem::path& FileName);
ZENCORE_API static IoBuffer MakeFromFileHandle(void* FileHandle, uint64_t Offset = 0, uint64_t Size = ~0ull);
+ ZENCORE_API static IoBuffer ReadFromFileMaybe(IoBuffer& InBuffer);
inline static IoBuffer MakeCloneFromMemory(const void* Ptr, size_t Sz) { return IoBuffer(IoBuffer::Clone, Ptr, Sz); }
};
diff --git a/zencore/include/zencore/string.h b/zencore/include/zencore/string.h
index c205b199d..a94e063a4 100644
--- a/zencore/include/zencore/string.h
+++ b/zencore/include/zencore/string.h
@@ -619,9 +619,23 @@ HashStringDjb2(const std::string_view& InString)
{
uint32_t HashValue = 5381;
- for (int c : InString)
+ for (int CurChar : InString)
{
- HashValue = HashValue * 33 + c;
+ HashValue = HashValue * 33 + CurChar;
+ }
+
+ return HashValue;
+}
+
+constexpr uint32_t
+HashStringAsLowerDjb2(const std::string_view& InString)
+{
+ uint32_t HashValue = 5381;
+
+ for (int CurChar : InString)
+ {
+ CurChar -= ((CurChar - 'A') <= ('Z' - 'A')) * ('A' - 'a'); // this should be compiled into branchless logic
+ HashValue = HashValue * 33 + CurChar;
}
return HashValue;
@@ -634,9 +648,9 @@ ToLower(const std::string_view& InString)
{
std::string Out(InString);
- for (char& C : Out)
+ for (char& CurChar : Out)
{
- C = static_cast<char>(std::tolower(C));
+ CurChar -= ((CurChar - 'A') <= ('Z' - 'A')) * ('A' - 'a'); // this should be compiled into branchless logic
}
return Out;
diff --git a/zencore/include/zencore/thread.h b/zencore/include/zencore/thread.h
index 410ffbd1e..9fc4c87a2 100644
--- a/zencore/include/zencore/thread.h
+++ b/zencore/include/zencore/thread.h
@@ -6,10 +6,13 @@
#include <shared_mutex>
+#include <string_view>
#include <vector>
namespace zen {
+void SetCurrentThreadName(std::string_view ThreadName);
+
/**
* Reader-writer lock
*
diff --git a/zencore/iobuffer.cpp b/zencore/iobuffer.cpp
index 922c14f83..119e37d0b 100644
--- a/zencore/iobuffer.cpp
+++ b/zencore/iobuffer.cpp
@@ -144,7 +144,7 @@ IoBufferCore::MakeOwned(bool Immutable)
{
if (!IsOwned())
{
- const void* OldDataPtr = m_DataPtr;
+ const void* OldDataPtr = m_DataPtr;
AllocateBuffer(m_DataBytes, sizeof(void*));
memcpy(const_cast<void*>(m_DataPtr), OldDataPtr, m_DataBytes);
SetIsOwnedByThis(true);
@@ -188,29 +188,29 @@ IoBufferExtendedCore::~IoBufferExtendedCore()
{
if (m_MappedPointer)
{
-# if ZEN_PLATFORM_WINDOWS
+#if ZEN_PLATFORM_WINDOWS
UnmapViewOfFile(m_MappedPointer);
-# else
+#else
uint64_t MapSize = ~uint64_t(uintptr_t(m_MmapHandle));
munmap(m_MappedPointer, MapSize);
-# endif
+#endif
}
-# if ZEN_PLATFORM_WINDOWS
+#if ZEN_PLATFORM_WINDOWS
if (m_Flags & kOwnsMmap)
{
CloseHandle(m_MmapHandle);
}
-# endif
+#endif
if (m_Flags & kOwnsFile)
{
-# if ZEN_PLATFORM_WINDOWS
+#if ZEN_PLATFORM_WINDOWS
BOOL Success = CloseHandle(m_FileHandle);
-# else
+#else
int Fd = int(uintptr_t(m_FileHandle));
bool Success = (close(Fd) == 0);
-# endif
+#endif
if (!Success)
{
@@ -244,7 +244,7 @@ IoBufferExtendedCore::Materialize() const
const uint64_t MappedOffsetDisplacement = m_FileOffset - MapOffset;
const uint64_t MapSize = m_DataBytes + MappedOffsetDisplacement;
-# if ZEN_PLATFORM_WINDOWS
+#if ZEN_PLATFORM_WINDOWS
m_MmapHandle = CreateFileMapping(m_FileHandle,
/* lpFileMappingAttributes */ nullptr,
/* flProtect */ PAGE_READONLY,
@@ -265,7 +265,7 @@ IoBufferExtendedCore::Materialize() const
/* FileOffsetHigh */ uint32_t(MapOffset >> 32),
/* FileOffsetLow */ uint32_t(MapOffset & 0xffFFffFFu),
/* dwNumberOfBytesToMap */ MapSize);
-# else
+#else
m_MmapHandle = (void*)uintptr_t(~MapSize); // ~ so it's never null (assuming MapSize >= 0)
m_Flags |= kOwnsMmap;
@@ -276,7 +276,7 @@ IoBufferExtendedCore::Materialize() const
/* flags */ MAP_SHARED | MAP_NORESERVE,
/* fd */ int(uintptr_t(m_FileHandle)),
/* offset */ MapOffset);
-# endif // ZEN_PLATFORM_WINDOWS
+#endif // ZEN_PLATFORM_WINDOWS
if (MappedBase == nullptr)
{
@@ -371,6 +371,41 @@ IoBuffer::GetFileReference(IoBufferFileReference& OutRef) const
//////////////////////////////////////////////////////////////////////////
IoBuffer
+IoBufferBuilder::ReadFromFileMaybe(IoBuffer& InBuffer)
+{
+ IoBufferFileReference FileRef;
+ if (InBuffer.GetFileReference(/* out */ FileRef))
+ {
+ IoBuffer OutBuffer(FileRef.FileChunkSize);
+
+#if ZEN_PLATFORM_WINDOWS
+ OVERLAPPED Ovl{};
+
+ const uint64_t NumberOfBytesToRead = FileRef.FileChunkSize;
+ const uint64_t& FileOffset = FileRef.FileChunkOffset;
+
+ Ovl.Offset = DWORD(FileOffset & 0xffff'ffffu);
+ Ovl.OffsetHigh = DWORD(FileOffset >> 32);
+
+ DWORD dwNumberOfBytesRead = 0;
+ BOOL Success = ::ReadFile(FileRef.FileHandle, OutBuffer.MutableData(), DWORD(NumberOfBytesToRead), &dwNumberOfBytesRead, &Ovl);
+
+ ZEN_ASSERT(dwNumberOfBytesRead == NumberOfBytesToRead);
+
+ // TODO: error handling
+
+ return OutBuffer;
+#else
+# error Needs implementation
+#endif
+ }
+ else
+ {
+ return InBuffer;
+ }
+}
+
+IoBuffer
IoBufferBuilder::MakeFromFileHandle(void* FileHandle, uint64_t Offset, uint64_t Size)
{
return IoBuffer(IoBuffer::BorrowedFile, FileHandle, Offset, Size);
@@ -381,7 +416,7 @@ IoBufferBuilder::MakeFromFile(const path_char_t* FileName, uint64_t Offset, uint
{
uint64_t FileSize;
-# if ZEN_PLATFORM_WINDOWS
+#if ZEN_PLATFORM_WINDOWS
CAtlFile DataFile;
HRESULT hRes = DataFile.Create(FileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING);
@@ -392,7 +427,7 @@ IoBufferBuilder::MakeFromFile(const path_char_t* FileName, uint64_t Offset, uint
}
DataFile.GetSize((ULONGLONG&)FileSize);
-# else
+#else
int Fd = open(FileName, O_RDONLY);
if (Fd < 0)
{
@@ -403,7 +438,7 @@ IoBufferBuilder::MakeFromFile(const path_char_t* FileName, uint64_t Offset, uint
struct stat Stat;
fstat(Fd, &Stat);
FileSize = Stat.st_size;
-# endif // ZEN_PLATFORM_WINDOWS
+#endif // ZEN_PLATFORM_WINDOWS
// TODO: should validate that offset is in range
@@ -422,15 +457,15 @@ IoBufferBuilder::MakeFromFile(const path_char_t* FileName, uint64_t Offset, uint
if (Size)
{
-# if ZEN_PLATFORM_WINDOWS
+#if ZEN_PLATFORM_WINDOWS
void* Fd = DataFile.Detach();
-# endif
+#endif
return IoBuffer(IoBuffer::File, (void*)uintptr_t(Fd), Offset, Size);
}
-# if !ZEN_PLATFORM_WINDOWS
+#if !ZEN_PLATFORM_WINDOWS
close(Fd);
-# endif
+#endif
// For an empty file, we may as well just return an empty memory IoBuffer
return IoBuffer(IoBuffer::Wrap, "", 0);
@@ -442,7 +477,7 @@ IoBufferBuilder::MakeFromTemporaryFile(const std::filesystem::path& FileName)
uint64_t FileSize;
void* Handle;
-# if ZEN_PLATFORM_WINDOWS
+#if ZEN_PLATFORM_WINDOWS
CAtlFile DataFile;
// We need to open with DELETE since this is used for the case
@@ -459,7 +494,7 @@ IoBufferBuilder::MakeFromTemporaryFile(const std::filesystem::path& FileName)
DataFile.GetSize((ULONGLONG&)FileSize);
Handle = DataFile.Detach();
-# else
+#else
int Fd = open(FileName.native().c_str(), O_RDONLY);
if (Fd < 0)
{
@@ -472,7 +507,7 @@ IoBufferBuilder::MakeFromTemporaryFile(const std::filesystem::path& FileName)
FileSize = Stat.st_size;
Handle = (void*)uintptr_t(Fd);
-# endif // ZEN_PLATFORM_WINDOWS
+#endif // ZEN_PLATFORM_WINDOWS
IoBuffer Iob(IoBuffer::File, Handle, 0, FileSize);
Iob.m_Core->SetIsWholeFile(true);
@@ -489,7 +524,7 @@ HashBuffer(IoBuffer& Buffer)
//////////////////////////////////////////////////////////////////////////
-# if ZEN_WITH_TESTS
+#if ZEN_WITH_TESTS
void
iobuffer_forcelink()
@@ -503,6 +538,6 @@ TEST_CASE("IoBuffer")
zen::IoBuffer buffer3(buffer2, 0, buffer2.Size());
}
-# endif
+#endif
} // namespace zen
diff --git a/zencore/string.cpp b/zencore/string.cpp
index 49824a910..8e7921bb6 100644
--- a/zencore/string.cpp
+++ b/zencore/string.cpp
@@ -929,6 +929,13 @@ TEST_CASE("string")
{
using namespace std::literals;
+ SUBCASE("hash_djb2")
+ {
+ CHECK(HashStringAsLowerDjb2("AbcdZ"sv) == HashStringDjb2("abcdz"sv));
+ CHECK(HashStringAsLowerDjb2("aBCd"sv) == HashStringDjb2("abcd"sv));
+ CHECK(HashStringAsLowerDjb2("aBCd"sv) == HashStringDjb2(ToLower("aBCd"sv)));
+ }
+
SUBCASE("ForEachStrTok")
{
const auto Tokens = "here,is,my,different,tokens"sv;
diff --git a/zencore/thread.cpp b/zencore/thread.cpp
index 20ab19f56..6f27ee528 100644
--- a/zencore/thread.cpp
+++ b/zencore/thread.cpp
@@ -14,6 +14,61 @@
namespace zen {
+#if ZEN_PLATFORM_WINDOWS
+// The information on how to set the thread name comes from
+// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
+const DWORD kVCThreadNameException = 0x406D1388;
+typedef struct tagTHREADNAME_INFO
+{
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+// The SetThreadDescription API was brought in version 1607 of Windows 10.
+typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
+// This function has try handling, so it is separated out of its caller.
+void
+SetNameInternal(DWORD thread_id, const char* name)
+{
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = name;
+ info.dwThreadID = thread_id;
+ info.dwFlags = 0;
+ __try
+ {
+ RaiseException(kVCThreadNameException, 0, sizeof(info) / sizeof(DWORD), reinterpret_cast<DWORD_PTR*>(&info));
+ }
+ __except (EXCEPTION_CONTINUE_EXECUTION)
+ {
+ }
+}
+#endif
+
+void
+SetCurrentThreadName([[maybe_unused]] std::string_view ThreadName)
+{
+#if ZEN_PLATFORM_WINDOWS
+ // The SetThreadDescription API works even if no debugger is attached.
+ static auto SetThreadDescriptionFunc =
+ reinterpret_cast<SetThreadDescription>(::GetProcAddress(::GetModuleHandle(L"Kernel32.dll"), "SetThreadDescription"));
+
+ if (SetThreadDescriptionFunc)
+ {
+ SetThreadDescriptionFunc(::GetCurrentThread(), Utf8ToWide(ThreadName).c_str());
+ }
+ // The debugger needs to be around to catch the name in the exception. If
+ // there isn't a debugger, we are just needlessly throwing an exception.
+ if (!::IsDebuggerPresent())
+ return;
+
+ std::string ThreadNameZ{ThreadName};
+ SetNameInternal(GetCurrentThreadId(), ThreadNameZ.c_str());
+#else
+#endif
+} // namespace zen
+
void
RwLock::AcquireShared()
{