diff --git a/src/Core/DataStructures/ArrayView.h b/src/Core/DataStructures/ArrayView.h index e9930f0..5aa3234 100644 --- a/src/Core/DataStructures/ArrayView.h +++ b/src/Core/DataStructures/ArrayView.h @@ -9,38 +9,23 @@ namespace Kraid { template - struct ArrayView + class ArrayView { - T* data; - uint64 size; - - ArrayView(const std::vector& vector) - { - this->data = vector.data(); - this->size = vector.size(); - } - - ArrayView(const Buffer& buffer) - { - this->data = buffer.data; - this->size = buffer.size; - } - - ArrayView(const T* buffer, uint64 size) - { - this->data = buffer; - this->size = size; - } - - inline uint64 GetSize() - { - return this->size; - } - - inline T* GetArray() - { - return this->data; - } + public: + const T* const data; + const uint64 size; + public: + ArrayView(const std::vector& vector): + data(vector.data()), + size(vector.size()) {} + + ArrayView(const Buffer& buffer): + data(buffer.data), + size(buffer.size) {} + + ArrayView(const T* buffer, uint64 size): + data(buffer), + size(size) {} inline T& operator[](const uint64 index) { diff --git a/src/Core/DataStructures/Buffer.cpp b/src/Core/DataStructures/Buffer.cpp index 352620a..c833aee 100644 --- a/src/Core/DataStructures/Buffer.cpp +++ b/src/Core/DataStructures/Buffer.cpp @@ -15,7 +15,7 @@ namespace Kraid memcpy(this->data, other.data, other.size); this->size = other.size; }; - + Buffer::Buffer(Buffer&& other) { if (this->data == other.data) return; @@ -23,7 +23,7 @@ namespace Kraid this->data = other.data; other.data = nullptr; } - + Buffer::Buffer(uint8* data, uint64 size) :data(data), size(size) {} Buffer& Buffer::operator=(const Buffer& other) @@ -39,7 +39,7 @@ namespace Kraid return *this; } - + Buffer::~Buffer() { if (data == nullptr) return; @@ -47,7 +47,6 @@ namespace Kraid free(data); data = nullptr; size = 0; - LINFO("Freed"); } } diff --git a/src/Core/DataStructures/Buffer.h b/src/Core/DataStructures/Buffer.h index dd8eed5..c88065b 100644 --- a/src/Core/DataStructures/Buffer.h +++ b/src/Core/DataStructures/Buffer.h @@ -6,11 +6,12 @@ namespace Kraid { - struct Buffer + class Buffer { + public: uint8* data = nullptr; uint64 size = 0; - + public: Buffer() = default; Buffer(uint64 size); Buffer(const Buffer& other); diff --git a/src/Core/DataStructures/RefCounter.cpp b/src/Core/DataStructures/RefCounter.cpp index 41e52b9..fcde13f 100644 --- a/src/Core/DataStructures/RefCounter.cpp +++ b/src/Core/DataStructures/RefCounter.cpp @@ -5,14 +5,14 @@ namespace Kraid ReferenceCounter::ReferenceCounter() { - this->refcounter = new ReferenceCounterInternal(); - this->refcounter_mutex = new Mutex(); + this->m_refcounter = new uint64(0); + this->m_refcounter_mutex = new Mutex(); } ReferenceCounter::ReferenceCounter(const ReferenceCounter& other) { - this->refcounter = other.refcounter; - this->refcounter_mutex = other.refcounter_mutex; + this->m_refcounter = other.m_refcounter; + this->m_refcounter_mutex = other.m_refcounter_mutex; this->Increment(); } @@ -20,45 +20,45 @@ namespace Kraid { if(this == &other) return *this; - this->refcounter = other.refcounter; - this->refcounter_mutex = other.refcounter_mutex; + this->m_refcounter = other.m_refcounter; + this->m_refcounter_mutex = other.m_refcounter_mutex; this->Increment(); return *this; } - ReferenceCounterInternal* ReferenceCounter::operator->() const + uint64* ReferenceCounter::operator->() const { - return this->refcounter; + return this->m_refcounter; } void ReferenceCounter::Increment() const { - this->refcounter_mutex->Lock(); - this->refcounter->refcount++; - this->refcounter_mutex->Lock(); + this->m_refcounter_mutex->Lock(); + (*this->m_refcounter)++; + this->m_refcounter_mutex->Lock(); } void ReferenceCounter::Decrement() const { bool should_free_mutex = false; - this->refcounter_mutex->Lock(); + this->m_refcounter_mutex->Lock(); - this->refcounter->refcount--; - if(this->refcounter_mutex == 0) + (*this->m_refcounter)--; + if(*this->m_refcounter == 0) { - free(this->refcounter); - this->refcounter = nullptr; + free(this->m_refcounter); + this->m_refcounter = nullptr; should_free_mutex = true; } - this->refcounter_mutex->Unlock(); + this->m_refcounter_mutex->Unlock(); if(should_free_mutex) { - free(this->refcounter_mutex); - this->refcounter_mutex = nullptr; + free(this->m_refcounter_mutex); + this->m_refcounter_mutex = nullptr; } } diff --git a/src/Core/DataStructures/RefCounter.h b/src/Core/DataStructures/RefCounter.h index 5ab7371..04931de 100644 --- a/src/Core/DataStructures/RefCounter.h +++ b/src/Core/DataStructures/RefCounter.h @@ -6,24 +6,16 @@ namespace Kraid { - struct ReferenceCounterInternal + class ReferenceCounter { - mutable uint64 refcount = 0; - - ReferenceCounterInternal() = default; - ReferenceCounterInternal(const ReferenceCounterInternal& other) = delete; - ReferenceCounterInternal& operator=(const ReferenceCounterInternal& other) = delete; - }; - - struct ReferenceCounter - { - mutable ReferenceCounterInternal* refcounter = nullptr; - mutable Mutex* refcounter_mutex = nullptr; - + private: + mutable uint64* m_refcounter = nullptr; + mutable Mutex* m_refcounter_mutex = nullptr; + public: ReferenceCounter(); ReferenceCounter(const ReferenceCounter& other); ReferenceCounter& operator=(const ReferenceCounter& other); - ReferenceCounterInternal* operator->() const; + uint64* operator->() const; void Increment() const; void Decrement() const; @@ -31,9 +23,9 @@ namespace Kraid //NOTE(Tiago):when the reference counted object decrements the object, only the last one to decrement will have a null pointer, //which means that only that threads copy of the refcounter will return on this, ensuring that only one thread tries to release //their data. - bool inline ShouldFree() const + bool inline ShouldFree() const { - return this->refcounter==nullptr && this->refcounter_mutex == nullptr; + return this->m_refcounter==nullptr; } }; diff --git a/src/Core/DataStructures/RingBuffer.h b/src/Core/DataStructures/RingBuffer.h index 7618673..17f0109 100644 --- a/src/Core/DataStructures/RingBuffer.h +++ b/src/Core/DataStructures/RingBuffer.h @@ -5,26 +5,42 @@ namespace Kraid { - template + template class CircularBuffer { + private: + T* m_buffer = nullptr; + T* m_backbuffer = nullptr; public: - T* buffer = nullptr; - T* backbuffer = nullptr; uint64 size = 0; public: CircularBuffer(uint64 size):size(size) { - buffer = (T*)malloc(size * sizeof(T)); - backbuffer = (T*)malloc(size * sizeof(T)); - memset(buffer, 0, size * sizeof(T)); + m_buffer = (T*)malloc(size * sizeof(T)); + m_backbuffer = (T*)malloc(size * sizeof(T)); + memset(m_buffer, 0, size * sizeof(T)); + } + + T& operator[](const uint64 index) + { + return this->m_buffer[index]; + } + + T at(const uint64 index) const + { + return this->m_buffer[index]; + } + + T* data() const + { + return this->m_buffer; } void push(T value) { - memcpy(backbuffer, buffer + 1, (size - 1) * sizeof(T)); - backbuffer[size - 1] = value; - memcpy(buffer, backbuffer, size * sizeof(T)); + memcpy(m_backbuffer, m_buffer + 1, (size - 1) * sizeof(T)); + m_backbuffer[size - 1] = value; + memcpy(m_buffer, m_backbuffer, size * sizeof(T)); } }; diff --git a/src/Core/DataStructures/RingeBuffer.cpp b/src/Core/DataStructures/RingeBuffer.cpp deleted file mode 100644 index 37745d6..0000000 --- a/src/Core/DataStructures/RingeBuffer.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "RingBuffer.h" - -namespace Kraid -{ - - - -} diff --git a/src/Core/DataStructures/StringView.h b/src/Core/DataStructures/StringView.h index ac628d3..f7e1988 100644 --- a/src/Core/DataStructures/StringView.h +++ b/src/Core/DataStructures/StringView.h @@ -6,8 +6,8 @@ namespace Kraid { - - class StringView:public ArrayView + + class StringView: public ArrayView { public: StringView(const char* string):ArrayView(string, strlen(string)){}; @@ -15,6 +15,7 @@ namespace Kraid StringView(const std::string& string): ArrayView(string.data(), string.length()){}; const char* Get() const {return this->data;}; + operator const char*() const {return this->data;}; }; class WideStringView:public ArrayView @@ -25,6 +26,7 @@ namespace Kraid WideStringView(const std::wstring& string): ArrayView(string.data(), string.length()){}; const wchar_t* Get() const { return this->data; }; + operator const wchar_t*() const { return this->data; }; }; } diff --git a/src/Core/Filesystem/Directory.cpp b/src/Core/Filesystem/Directory.cpp index 7a14f57..2519854 100644 --- a/src/Core/Filesystem/Directory.cpp +++ b/src/Core/Filesystem/Directory.cpp @@ -9,14 +9,15 @@ namespace Kraid Directory::Directory(const wchar_t* path) { - this->directory_handle = CreateFileW(path, + this->m_directory_handle = CreateFileW( + path, FILE_LIST_DIRECTORY | GENERIC_READ | GENERIC_WRITE , FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if(this->directory_handle == INVALID_HANDLE_VALUE) + if(this->m_directory_handle == INVALID_HANDLE_VALUE) { PRINT_WINERROR(); } @@ -24,9 +25,9 @@ namespace Kraid Directory::~Directory() { - CloseHandle(this->directory_handle); - this->directory_handle = nullptr; - this->changes_obtained_once = false; + CloseHandle(this->m_directory_handle); + this->m_directory_handle = nullptr; + this->m_changes_obtained_once = false; } std::vector Directory::GetChangedFiles() @@ -35,13 +36,31 @@ namespace Kraid uint32 entries_read; FILE_NOTIFY_INFORMATION* changed_entries = (FILE_NOTIFY_INFORMATION*)malloc(CHANGED_FILE_ENTRY_COUNT * sizeof(FILE_NOTIFY_INFORMATION)); if (changed_entries == nullptr) return {}; - //NOTE(Tiago): there is a weird behavior where a write causes two change notifications to be launched for the same file, this seems to be related to metadata. The issue is that in teh first time that a change is detected, the second notification is not received and as such we have to have a way to handle that special corner case. - bool result = ReadDirectoryChangesW(this->directory_handle, (void*)changed_entries, CHANGED_FILE_ENTRY_COUNT, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, (DWORD*)&entries_read, NULL, NULL); - if(this->changes_obtained_once) + //NOTE(Tiago): there is a weird behavior where a write causes two change notifications to be launched for the same file, this seems to be related to metadata. + //The issue is that in teh first time that a change is detected, the second notification is not received and as such we have to have a way to handle that + //special corner case. + bool result = ReadDirectoryChangesW( + this->m_directory_handle, + (void*)changed_entries, + CHANGED_FILE_ENTRY_COUNT, + FALSE, + FILE_NOTIFY_CHANGE_LAST_WRITE, + (DWORD*)&entries_read, + NULL, + NULL); + if(this->m_changes_obtained_once) { - result = ReadDirectoryChangesW(this->directory_handle, (void*)changed_entries, CHANGED_FILE_ENTRY_COUNT, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, (DWORD*)&entries_read, NULL, NULL); + result = ReadDirectoryChangesW( + this->m_directory_handle, + (void*)changed_entries, + CHANGED_FILE_ENTRY_COUNT, + FALSE, + FILE_NOTIFY_CHANGE_LAST_WRITE, + (DWORD*)&entries_read, + NULL, + NULL); } - this->changes_obtained_once = true; + this->m_changes_obtained_once = true; if(result == false) { PRINT_WINERROR(); @@ -72,26 +91,26 @@ namespace Kraid DirectoryWatcher::DirectoryWatcher(const wchar_t* directory) { - this->watched_dir = {directory}; - this->wait_event_handle = FindFirstChangeNotificationW(directory, false, FILE_NOTIFY_CHANGE_LAST_WRITE); - if(this->wait_event_handle == INVALID_HANDLE_VALUE) + this->m_watched_dir = {directory}; + this->m_wait_event_handle = FindFirstChangeNotificationW(directory, false, FILE_NOTIFY_CHANGE_LAST_WRITE); + if(this->m_wait_event_handle == INVALID_HANDLE_VALUE) { PRINT_WINERROR(); return; } - this->watch_thread = Thread([this](void* args) -> DWORD + this->m_watch_thread = Thread([this](void* args) -> DWORD { - while(this->watched_dir.directory_handle != nullptr) + while(this->m_watched_dir.m_directory_handle != nullptr) { - uint32 wait_status = WaitForMultipleObjects(1, &this->wait_event_handle, TRUE, INFINITE); + uint32 wait_status = WaitForMultipleObjects(1, &this->m_wait_event_handle, TRUE, INFINITE); if(wait_status == WAIT_OBJECT_0) { - auto changed_files = this->watched_dir.GetChangedFiles(); + auto changed_files = this->m_watched_dir.GetChangedFiles(); for(auto& file: changed_files) { - this->file_callback_mutex.Lock(); - auto callbacks = this->file_change_callbacks[file]; + this->m_file_callback_mutex.Lock(); + auto callbacks = this->m_file_change_callbacks[file]; for(auto& callback: callbacks) { if(callback) @@ -103,17 +122,17 @@ namespace Kraid LWARNING(L"Attempt to invoke null callback for file change"); } } - this->file_callback_mutex.Unlock(); + this->m_file_callback_mutex.Unlock(); } } } return 0; - }); + }); } bool DirectoryWatcher::operator==(const DirectoryWatcher &other) { - return this->wait_event_handle == other.wait_event_handle; + return this->m_wait_event_handle == other.m_wait_event_handle; } void DirectoryWatcher::RegisterFileChangeCallback(const std::wstring& filename, const std::function& callback) @@ -124,12 +143,12 @@ namespace Kraid return; } - this->file_callback_mutex.Lock(); - this->file_change_callbacks[filename].push_back(callback); - this->file_callback_mutex.Unlock(); + this->m_file_callback_mutex.Lock(); + this->m_file_change_callbacks[filename].push_back(callback); + this->m_file_callback_mutex.Unlock(); } - //TODO(Tiago):associative containers in C++ are dogs ass, remember to implement your own hash + //TODO(Tiago):associative containers in C++ are dogs ass, remember to implement your own hash DirectoryWatcher& DirectoryWatcher::GetDirectoryWatcher(const std::wstring& directory) { std::wstring directory_path = Kraid::GetAbsoluteFilepath(directory); diff --git a/src/Core/Filesystem/Directory.h b/src/Core/Filesystem/Directory.h index 31b2fcf..6ece165 100644 --- a/src/Core/Filesystem/Directory.h +++ b/src/Core/Filesystem/Directory.h @@ -4,31 +4,37 @@ #include #include +#include + namespace Kraid { + class DirectoryWatcher; + //TODO(Tiago): improve structure packing of both of these structures, especially directory, it wastes a ton of memory with the bool for the read changes loop - struct Directory + class Directory { - public: - HANDLE directory_handle = nullptr; - bool changes_obtained_once = false;//NOTE(Tiago): used to detect if the directory change list has been read at least once. + private: + HANDLE m_directory_handle = nullptr; + bool m_changes_obtained_once = false;//NOTE(Tiago): used to detect if the directory change list has been read at least once. public: Directory() = default; Directory(const wchar_t* path); ~Directory(); std::vector GetChangedFiles(); + + friend DirectoryWatcher; }; - struct DirectoryWatcher + class DirectoryWatcher { friend Directory; - public: - HANDLE wait_event_handle = nullptr; - Directory watched_dir; - Thread watch_thread; - std::unordered_map>> file_change_callbacks; - Mutex file_callback_mutex = {}; private: + HANDLE m_wait_event_handle = nullptr; + Directory m_watched_dir; + Thread m_watch_thread; + std::unordered_map>> m_file_change_callbacks; + Mutex m_file_callback_mutex = {}; + inline static std::unordered_map directory_watcher_instances = {}; inline static Mutex watcher_instance_mutex = {}; public: diff --git a/src/Core/Filesystem/Filesystem.cpp b/src/Core/Filesystem/Filesystem.cpp index c014985..1847876 100644 --- a/src/Core/Filesystem/Filesystem.cpp +++ b/src/Core/Filesystem/Filesystem.cpp @@ -29,8 +29,9 @@ namespace Kraid File::File(const File& other) { - this->file_handle = other.file_handle; - this->refcount.Increment(); + this->m_file_handle = other.m_file_handle; + this->m_refcount = other.m_refcount; + this->m_refcount.Increment(); } File::File(const wchar_t* filepath, bool append) @@ -50,12 +51,12 @@ namespace Kraid { open_mode = CREATE_ALWAYS; } - this->file_handle = CreateFile2(filepath, + this->m_file_handle = CreateFile2(filepath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, open_mode, nullptr); - if(this->file_handle == INVALID_HANDLE_VALUE) + if(this->m_file_handle == INVALID_HANDLE_VALUE) { LERROR(FormatErrorMessage(GetLastError())); return; @@ -80,12 +81,12 @@ namespace Kraid { open_mode = CREATE_ALWAYS; } - this->file_handle = CreateFile2(filepath, + this->m_file_handle = CreateFile2(filepath, FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, open_mode, nullptr); - if(this->file_handle == INVALID_HANDLE_VALUE) + if(this->m_file_handle == INVALID_HANDLE_VALUE) { LERROR(FormatErrorMessage(GetLastError())); return; @@ -107,17 +108,17 @@ namespace Kraid File& File::operator=(const File& other) { - this->file_handle = other.file_handle; + this->m_file_handle = other.m_file_handle; return *this; } bool File::Write(const uint8* data, uint64 size) { - SetFilePointer(this->file_handle, 0, NULL, FILE_BEGIN); + SetFilePointer(this->m_file_handle, 0, NULL, FILE_BEGIN); //NOTE(Tiago):not using the EX version leads to cleaner code in my opinion, at no loss to functionality uint32 written = 0; bool result = WriteFile( - this->file_handle, + this->m_file_handle, (void*)data, size, (DWORD*)&written, NULL); @@ -128,7 +129,7 @@ namespace Kraid free(message); return false; } - uint32 result_code = WaitForSingleObjectEx(this->file_handle, INFINITE, true); + uint32 result_code = WaitForSingleObjectEx(this->m_file_handle, INFINITE, true); if(result_code == WAIT_FAILED) { wchar_t* message = FormatErrorMessage(GetLastError()); @@ -142,10 +143,10 @@ namespace Kraid bool File::Append(const uint8 *data, uint64 size) { - SetFilePointer(this->file_handle, 0, NULL, FILE_END); + SetFilePointer(this->m_file_handle, 0, NULL, FILE_END); uint32 written = 0; bool result = WriteFile( - this->file_handle, + this->m_file_handle, (void*)data, size, (DWORD*)&written, NULL); @@ -156,7 +157,7 @@ namespace Kraid free(message); return false; } - uint32 result_code = WaitForSingleObjectEx(this->file_handle, INFINITE, true); + uint32 result_code = WaitForSingleObjectEx(this->m_file_handle, INFINITE, true); if(result_code == WAIT_FAILED) { wchar_t* message = FormatErrorMessage(GetLastError()); @@ -170,7 +171,7 @@ namespace Kraid Buffer File::Read() { - SetFilePointer(this->file_handle, 0, NULL, FILE_BEGIN); + SetFilePointer(this->m_file_handle, 0, NULL, FILE_BEGIN); uint64 file_size = this->GetSize(); uint32 dummy_var = 0; @@ -185,7 +186,7 @@ namespace Kraid while(total_amount_left_to_read > UINT32_MAX) { uint32 amount_to_read = UINT32_MAX; - bool result = ReadFile(this->file_handle, buffer + (file_size - total_amount_left_to_read), amount_to_read, (DWORD*)&dummy_var, NULL); + bool result = ReadFile(this->m_file_handle, buffer + (file_size - total_amount_left_to_read), amount_to_read, (DWORD*)&dummy_var, NULL); if(result == false) { PRINT_WINERROR(); @@ -194,7 +195,7 @@ namespace Kraid } total_amount_left_to_read -= UINT32_MAX; } - bool result = ReadFile(this->file_handle, buffer + (file_size - total_amount_left_to_read), (uint32)total_amount_left_to_read, (DWORD*)&dummy_var, NULL); + bool result = ReadFile(this->m_file_handle, buffer + (file_size - total_amount_left_to_read), (uint32)total_amount_left_to_read, (DWORD*)&dummy_var, NULL); if(result == false) { PRINT_WINERROR(); @@ -209,7 +210,7 @@ namespace Kraid uint64 File::GetSize() const { uint32 file_size_high_word = 0;//NOTE(Tiago):contaisn the high 32-bits of data from a 64-bit filesize - uint32 file_size_low_word = GetFileSize(this->file_handle, (DWORD*)&file_size_high_word); + uint32 file_size_low_word = GetFileSize(this->m_file_handle, (DWORD*)&file_size_high_word); if(file_size_low_word == INVALID_FILE_SIZE) { PRINT_WINERROR(); @@ -220,12 +221,12 @@ namespace Kraid File::~File() { - if(this->file_handle == INVALID_HANDLE_VALUE || this->file_handle == nullptr) return; + if(this->m_file_handle == INVALID_HANDLE_VALUE || this->m_file_handle == nullptr) return; - refcount.Decrement(); - if(refcount.ShouldFree()) + m_refcount.Decrement(); + if(m_refcount.ShouldFree()) { - if(!CloseHandle(this->file_handle)) + if(!CloseHandle(this->m_file_handle)) { LERROR(FormatErrorMessage(GetLastError())); return; diff --git a/src/Core/Filesystem/Filesystem.h b/src/Core/Filesystem/Filesystem.h index d75e363..6dd25f9 100644 --- a/src/Core/Filesystem/Filesystem.h +++ b/src/Core/Filesystem/Filesystem.h @@ -13,9 +13,9 @@ namespace Kraid struct File { - public: - HANDLE file_handle = nullptr; - ReferenceCounter refcount; + private: + HANDLE m_file_handle = nullptr; + ReferenceCounter m_refcount; public: File() = default; diff --git a/src/main.cpp b/src/main.cpp index 33b5d42..4be1520 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -97,7 +97,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmd float cummulative_frame_time = 0; for(uint64 i = 0; i < frame_times.size; ++i) { - float frame_time = frame_times.buffer[i]; + float frame_time = frame_times[i]; cummulative_frame_time += frame_time; if(frame_time > highest_time) highest_time = frame_time; if(frame_time < lowest_time) lowest_time = frame_time; @@ -113,8 +113,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmd gui.StartFrame(); ImGui::Begin("Frame time"); - if (frame_times.buffer >= frame_times.buffer + frame_times.size) __debugbreak(); - ImGui::PlotLines("", frame_times.buffer, frame_times.size, 0, average_fps_string.c_str(), lowest_time, highest_time, ImVec2(0.0f, 100.0f)); + ImGui::PlotLines("", frame_times.data(), frame_times.size, 0, average_fps_string.c_str(), lowest_time, highest_time, ImVec2(0.0f, 100.0f)); ImGui::End(); input.view_matrix = camera.ViewMatrix();