Restore win32 prototypes, add virtual mem allocation and array, add fixed pool
This commit is contained in:
		
							parent
							
								
									39d75ae5bf
								
							
						
					
					
						commit
						7785e35f91
					
				
							
								
								
									
										604
									
								
								dqn.h
									
									
									
									
									
								
							
							
						
						
									
										604
									
								
								dqn.h
									
									
									
									
									
								
							| @ -47,6 +47,7 @@ | |||||||
| // #DqnHashTable   Hash Tables using Templates
 | // #DqnHashTable   Hash Tables using Templates
 | ||||||
| 
 | 
 | ||||||
| // #XPlatform (Win32 & Unix)
 | // #XPlatform (Win32 & Unix)
 | ||||||
|  | // #DqnVArray    Array backed by virtual memory
 | ||||||
| // #DqnFile      File I/O (Read, Write, Delete)
 | // #DqnFile      File I/O (Read, Write, Delete)
 | ||||||
| // #DqnTimer     High Resolution Timer
 | // #DqnTimer     High Resolution Timer
 | ||||||
| // #DqnLock      Mutex Synchronisation
 | // #DqnLock      Mutex Synchronisation
 | ||||||
| @ -74,9 +75,9 @@ | |||||||
| // This needs to be above the portable layer so  that, if the user requests a platform
 | // This needs to be above the portable layer so  that, if the user requests a platform
 | ||||||
| // implementation, platform specific implementations in the portable layer will get activated.
 | // implementation, platform specific implementations in the portable layer will get activated.
 | ||||||
| #if (defined(_WIN32) || defined(_WIN64)) | #if (defined(_WIN32) || defined(_WIN64)) | ||||||
|     #define DQN__IS_WIN32 1 |     #define DQN_IS_WIN32 1 | ||||||
| #else | #else | ||||||
|     #define DQN__IS_UNIX 1 |     #define DQN_IS_UNIX 1 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if defined(DQN_PLATFORM_IMPLEMENTATION) | #if defined(DQN_PLATFORM_IMPLEMENTATION) | ||||||
| @ -187,6 +188,348 @@ FILE_SCOPE const bool IS_DEBUG = true; | |||||||
| 
 | 
 | ||||||
| // #External Code
 | // #External Code
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
|  | #if defined(DQN_PLATFORM_HEADER) && defined(DQN_IS_WIN32) && !defined(_WINDOWS_) | ||||||
|  | using WORD      = unsigned short; | ||||||
|  | using DWORD     = unsigned long; | ||||||
|  | using BOOL      = int; | ||||||
|  | using LONG      = long; | ||||||
|  | using LONGLONG  = long long; | ||||||
|  | using HANDLE    = void *; | ||||||
|  | using HMODULE   = HANDLE; | ||||||
|  | using HWND      = HANDLE; | ||||||
|  | using UINT      = unsigned int; | ||||||
|  | using ULONG     = unsigned long; | ||||||
|  | using ULONGLONG = unsigned long long; | ||||||
|  | using DWORD64   = unsigned long long; | ||||||
|  | using BYTE      = unsigned char; | ||||||
|  | 
 | ||||||
|  | u32    const MB_OK                         = 0x00000000L; | ||||||
|  | HANDLE const INVALID_HANDLE_VALUE          = ((HANDLE)(LONG *)-1); | ||||||
|  | u32    const MAX_PATH                      = 260; | ||||||
|  | u32    const INFINITE                      = 0xFFFFFFFF; | ||||||
|  | u32    const CP_UTF8                       = 65001; | ||||||
|  | u32    const FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; | ||||||
|  | u32    const FORMAT_MESSAGE_FROM_SYSTEM    = 0x00001000; | ||||||
|  | u32    const MEM_COMMIT                    = 0x00001000; | ||||||
|  | u32    const MEM_RESERVE                   = 0x00002000; | ||||||
|  | u32    const PAGE_READWRITE                = 0x04; | ||||||
|  | u32    const MEM_DECOMMIT                  = 0x4000; | ||||||
|  | u32    const MEM_RELEASE                   = 0x8000; | ||||||
|  | 
 | ||||||
|  | struct RECT | ||||||
|  | { | ||||||
|  |     LONG left; | ||||||
|  |     LONG top; | ||||||
|  |     LONG right; | ||||||
|  |     LONG bottom; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | union LARGE_INTEGER | ||||||
|  | { | ||||||
|  |     struct { DWORD LowPart; LONG HighPart; }; | ||||||
|  |     struct { DWORD LowPart; LONG HighPart; } u; | ||||||
|  |     LONGLONG QuadPart; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | union ULARGE_INTEGER | ||||||
|  | { | ||||||
|  |   struct { DWORD LowPart; DWORD HighPart; }; | ||||||
|  |   struct { DWORD LowPart; DWORD HighPart; } u; | ||||||
|  |   ULONGLONG QuadPart; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SECURITY_ATTRIBUTES | ||||||
|  | { | ||||||
|  |     DWORD length; | ||||||
|  |     void *securityDescriptor; | ||||||
|  |     BOOL inheritHandle; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct PROCESS_INFORMATION | ||||||
|  | { | ||||||
|  |     void *hProcess; | ||||||
|  |     void *hThread; | ||||||
|  |     DWORD dwProcessId; | ||||||
|  |     DWORD dwThreadId; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | struct FILETIME | ||||||
|  | { | ||||||
|  |   DWORD dwLowDateTime; | ||||||
|  |   DWORD dwHighDateTime; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct WIN32_FILE_ATTRIBUTE_DATA | ||||||
|  | { | ||||||
|  |     DWORD dwFileAttributes; | ||||||
|  |     FILETIME ftCreationTime; | ||||||
|  |     FILETIME ftLastAccessTime; | ||||||
|  |     FILETIME ftLastWriteTime; | ||||||
|  |     DWORD nFileSizeHigh; | ||||||
|  |     DWORD nFileSizeLow; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum GET_FILEEX_INFO_LEVELS | ||||||
|  | { | ||||||
|  |     GetFileExInfoStandard, | ||||||
|  |     GetFileExMaxInfoLevel | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct WIN32_FIND_DATAW | ||||||
|  | { | ||||||
|  |   DWORD    dwFileAttributes; | ||||||
|  |   FILETIME ftCreationTime; | ||||||
|  |   FILETIME ftLastAccessTime; | ||||||
|  |   FILETIME ftLastWriteTime; | ||||||
|  |   DWORD    nFileSizeHigh; | ||||||
|  |   DWORD    nFileSizeLow; | ||||||
|  |   DWORD    dwReserved0; | ||||||
|  |   DWORD    dwReserved1; | ||||||
|  |   wchar_t  cFileName[MAX_PATH]; | ||||||
|  |   wchar_t  cAlternateFileName[14]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct LIST_ENTRY { | ||||||
|  |    struct LIST_ENTRY *Flink; | ||||||
|  |    struct LIST_ENTRY *Blink; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct RTL_CRITICAL_SECTION_DEBUG | ||||||
|  | { | ||||||
|  |     WORD Type; | ||||||
|  |     WORD CreatorBackTraceIndex; | ||||||
|  |     struct CRITICAL_SECTION *CriticalSection; | ||||||
|  |     LIST_ENTRY ProcessLocksList; | ||||||
|  |     DWORD EntryCount; | ||||||
|  |     DWORD ContentionCount; | ||||||
|  |     DWORD Flags; | ||||||
|  |     WORD CreatorBackTraceIndexHigh; | ||||||
|  |     WORD SpareWORD; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct CRITICAL_SECTION | ||||||
|  | { | ||||||
|  |     RTL_CRITICAL_SECTION_DEBUG *DebugInfo; | ||||||
|  |     LONG LockCount; | ||||||
|  |     LONG RecursionCount; | ||||||
|  |     HANDLE OwningThread; | ||||||
|  |     HANDLE LockSemaphore; | ||||||
|  |     ULONG *SpinCount; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct OVERLAPPED { | ||||||
|  |   ULONG *Internal; | ||||||
|  |   ULONG *InternalHigh; | ||||||
|  |   union { | ||||||
|  |     struct { | ||||||
|  |       DWORD Offset; | ||||||
|  |       DWORD OffsetHigh; | ||||||
|  |     }; | ||||||
|  |     void  *Pointer; | ||||||
|  |   }; | ||||||
|  |   HANDLE    hEvent; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SYSTEM_INFO { | ||||||
|  |   union | ||||||
|  |   { | ||||||
|  |     DWORD  dwOemId; | ||||||
|  |     struct | ||||||
|  |     { | ||||||
|  |       WORD wProcessorArchitecture; | ||||||
|  |       WORD wReserved; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  |   DWORD  dwPageSize; | ||||||
|  |   void  *lpMinimumApplicationAddress; | ||||||
|  |   void  *lpMaximumApplicationAddress; | ||||||
|  |   DWORD *dwActiveProcessorMask; | ||||||
|  |   DWORD  dwNumberOfProcessors; | ||||||
|  |   DWORD  dwProcessorType; | ||||||
|  |   DWORD  dwAllocationGranularity; | ||||||
|  |   WORD   wProcessorLevel; | ||||||
|  |   WORD   wProcessorRevision; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum LOGICAL_PROCESSOR_RELATIONSHIP | ||||||
|  | { | ||||||
|  |     RelationProcessorCore, | ||||||
|  |     RelationNumaNode, | ||||||
|  |     RelationCache, | ||||||
|  |     RelationProcessorPackage, | ||||||
|  |     RelationGroup, | ||||||
|  |     RelationAll = 0xffff | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef unsigned long *KAFFINITY; | ||||||
|  | struct GROUP_AFFINITY { | ||||||
|  |     KAFFINITY Mask; | ||||||
|  |     WORD   Group; | ||||||
|  |     WORD   Reserved[3]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct PROCESSOR_RELATIONSHIP | ||||||
|  | { | ||||||
|  |     BYTE  Flags; | ||||||
|  |     BYTE  EfficiencyClass; | ||||||
|  |     BYTE  Reserved[20]; | ||||||
|  |     WORD  GroupCount; | ||||||
|  |     GROUP_AFFINITY GroupMask[1]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct NUMA_NODE_RELATIONSHIP { | ||||||
|  |     DWORD NodeNumber; | ||||||
|  |     BYTE  Reserved[20]; | ||||||
|  |     GROUP_AFFINITY GroupMask; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum PROCESSOR_CACHE_TYPE | ||||||
|  | { | ||||||
|  |     CacheUnified, | ||||||
|  |     CacheInstruction, | ||||||
|  |     CacheData, | ||||||
|  |     CacheTrace | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct CACHE_RELATIONSHIP | ||||||
|  | { | ||||||
|  |     BYTE Level; | ||||||
|  |     BYTE Associativity; | ||||||
|  |     WORD LineSize; | ||||||
|  |     DWORD CacheSize; | ||||||
|  |     PROCESSOR_CACHE_TYPE Type; | ||||||
|  |     BYTE Reserved[20]; | ||||||
|  |     GROUP_AFFINITY GroupMask; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct PROCESSOR_GROUP_INFO | ||||||
|  | { | ||||||
|  |     BYTE MaximumProcessorCount; | ||||||
|  |     BYTE ActiveProcessorCount; | ||||||
|  |     BYTE Reserved[38]; | ||||||
|  |     KAFFINITY ActiveProcessorMask; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct GROUP_RELATIONSHIP | ||||||
|  | { | ||||||
|  |     WORD MaximumGroupCount; | ||||||
|  |     WORD ActiveGroupCount; | ||||||
|  |     BYTE Reserved[20]; | ||||||
|  |     PROCESSOR_GROUP_INFO GroupInfo[1]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX | ||||||
|  | { | ||||||
|  |     LOGICAL_PROCESSOR_RELATIONSHIP Relationship; | ||||||
|  |     DWORD Size; | ||||||
|  |     union | ||||||
|  |     { | ||||||
|  |         PROCESSOR_RELATIONSHIP Processor; | ||||||
|  |         NUMA_NODE_RELATIONSHIP NumaNode; | ||||||
|  |         CACHE_RELATIONSHIP Cache; | ||||||
|  |         GROUP_RELATIONSHIP Group; | ||||||
|  |     }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | typedef DWORD (*LPTHREAD_START_ROUTINE)(void *lpThreadParameter); | ||||||
|  | 
 | ||||||
|  | DWORD64 __rdtsc(); | ||||||
|  | 
 | ||||||
|  | void    DeleteCriticalSection           (CRITICAL_SECTION *lpCriticalSection); | ||||||
|  | BOOL    DeleteFileA                     (char    const *lpFileName); // TODO(doyle): Wide versions only
 | ||||||
|  | BOOL    DeleteFileW                     (wchar_t const *lpFileName); | ||||||
|  | BOOL    CloseHandle                     (HANDLE hObject); | ||||||
|  | BOOL    CopyFileA                       (char    const *lpExistingFileName, char const *lpNewFileName, BOOL bFailIfExists); | ||||||
|  | BOOL    CopyFileW                       (wchar_t const *lpExistingFileName, wchar_t const *lpNewFileName, BOOL bFailIfExists); | ||||||
|  | BOOL    CloseHandle                     (HANDLE *hObject); | ||||||
|  | HANDLE  CreateFileW                     (wchar_t const *lpFileName, | ||||||
|  |                                          DWORD dwDesiredAccess, | ||||||
|  |                                          DWORD dwShareMode, | ||||||
|  |                                          SECURITY_ATTRIBUTES *lpSecurityAttributes, | ||||||
|  |                                          DWORD dwCreationDisposition, | ||||||
|  |                                          DWORD dwFlagsAndAttributes, | ||||||
|  |                                          HANDLE hTemplateFile); | ||||||
|  | HANDLE  CreateSemaphoreA                (SECURITY_ATTRIBUTES *lpSemaphoreAttributes, | ||||||
|  |                                          long lInitialCount, | ||||||
|  |                                          long lMaximumCount, | ||||||
|  |                                          char const *lpName); | ||||||
|  | HANDLE  CreateThread                    (SECURITY_ATTRIBUTES *lpThreadAttributes, | ||||||
|  |                                          size_t dwStackSize, | ||||||
|  |                                          LPTHREAD_START_ROUTINE lpStartAddress, | ||||||
|  |                                          void *lpParameter, | ||||||
|  |                                          DWORD dwCreationFlags, | ||||||
|  |                                          DWORD *lpThreadId); | ||||||
|  | void    EnterCriticalSection            (CRITICAL_SECTION *lpCriticalSection); | ||||||
|  | BOOL    FindClose                       (HANDLE hFindFile); | ||||||
|  | HANDLE  FindFirstFileW                  (wchar_t const *lpFileName, WIN32_FIND_DATAW *lpFindFileData); | ||||||
|  | BOOL    FindNextFileW                   (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); | ||||||
|  | DWORD   FormatMessageA                  (DWORD dwFlags, | ||||||
|  |                                          void const *lpSource, | ||||||
|  |                                          DWORD dwMessageId, | ||||||
|  |                                          DWORD dwLanguageId, | ||||||
|  |                                          char *lpBuffer, | ||||||
|  |                                          DWORD nSize, | ||||||
|  |                                          va_list *Arguments); | ||||||
|  | BOOL    GetClientRect                   (HWND hWnd, RECT *lpRect); | ||||||
|  | BOOL    GetExitCodeProcess              (HANDLE *hProcess, DWORD *lpExitCode); | ||||||
|  | BOOL    GetFileSizeEx                   (HANDLE hFile, LARGE_INTEGER *lpFileSize); | ||||||
|  | BOOL    GetFileAttributesExW            (wchar_t const *lpFileName, | ||||||
|  |                                          GET_FILEEX_INFO_LEVELS fInfoLevelId, | ||||||
|  |                                          void *lpFileInformation); | ||||||
|  | DWORD   GetLastError                    (void); | ||||||
|  | DWORD   GetModuleFileNameA              (HMODULE hModule, char *lpFilename, DWORD nSize); | ||||||
|  | void    GetNativeSystemInfo             (SYSTEM_INFO *lpSystemInfo); | ||||||
|  | BOOL    GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, | ||||||
|  |                                          SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *Buffer, | ||||||
|  |                                          DWORD *ReturnedLength); | ||||||
|  | BOOL    InitializeCriticalSectionEx     (CRITICAL_SECTION *lpCriticalSection, | ||||||
|  |                                          DWORD dwSpinCount, | ||||||
|  |                                          DWORD Flags); | ||||||
|  | long    InterlockedAdd                  (long volatile *Addend, long Value); | ||||||
|  | long    InterlockedCompareExchange      (long volatile *Destination, long Exchange, long Comparand); | ||||||
|  | void    LeaveCriticalSection            (CRITICAL_SECTION *lpCriticalSection); | ||||||
|  | int     MessageBoxA                     (HWND hWnd, char const *lpText, char const *lpCaption, UINT uType); | ||||||
|  | int     MultiByteToWideChar             (unsigned int CodePage, | ||||||
|  |                                          DWORD dwFlags, | ||||||
|  |                                          char const *lpMultiByteStr, | ||||||
|  |                                          int cbMultiByte, | ||||||
|  |                                          wchar_t *lpWideCharStr, | ||||||
|  |                                          int cchWideChar); | ||||||
|  | void    OutputDebugStringA              (char const *lpOutputString); | ||||||
|  | BOOL    ReadFile                        (HANDLE hFile, | ||||||
|  |                                          void *lpBuffer, | ||||||
|  |                                          DWORD nNumberOfBytesToRead, | ||||||
|  |                                          DWORD *lpNumberOfBytesRead, | ||||||
|  |                                          OVERLAPPED *lpOverlapped); | ||||||
|  | BOOL    ReleaseSemaphore                (HANDLE hSemaphore, long lReleaseCount, long *lpPreviousCount); | ||||||
|  | BOOL    QueryPerformanceFrequency       (LARGE_INTEGER *lpFrequency); | ||||||
|  | BOOL    QueryPerformanceCounter         (LARGE_INTEGER *lpPerformanceCount); | ||||||
|  | DWORD   WaitForSingleObject             (HANDLE *hHandle, DWORD dwMilliseconds); | ||||||
|  | DWORD   WaitForSingleObjectEx           (HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable); | ||||||
|  | int     WideCharToMultiByte             (unsigned int CodePage, | ||||||
|  |                                          DWORD dwFlags, | ||||||
|  |                                          wchar_t const *lpWideCharStr, | ||||||
|  |                                          int cchWideChar, | ||||||
|  |                                          char *lpMultiByteStr, | ||||||
|  |                                          int cbMultiByte, | ||||||
|  |                                          char const *lpDefaultChar, | ||||||
|  |                                          BOOL *lpUsedDefaultChar); | ||||||
|  | void    Sleep                           (DWORD dwMilliseconds); | ||||||
|  | BOOL    WriteFile                       (HANDLE hFile, | ||||||
|  |                                          void *const lpBuffer, | ||||||
|  |                                          DWORD nNumberOfBytesToWrite, | ||||||
|  |                                          DWORD *lpNumberOfBytesWritten, | ||||||
|  |                                          OVERLAPPED *lpOverlapped); | ||||||
|  | void   *VirtualAlloc                    (void *lpAddress, | ||||||
|  |                                          size_t dwSize, | ||||||
|  |                                          DWORD  flAllocationType, | ||||||
|  |                                          DWORD  flProtect); | ||||||
|  | BOOL    VirtualFree                     (void *lpAddress, | ||||||
|  |                                          size_t dwSize, | ||||||
|  |                                          DWORD  dwFreeType); | ||||||
|  | #endif // defined(DQN_PLATFORM_HEADER) && defined(DQN_IS_WIN32) && !defined(_WINDOWS_)
 | ||||||
| #ifndef STB_SPRINTF_H_INCLUDE | #ifndef STB_SPRINTF_H_INCLUDE | ||||||
| #define STB_SPRINTF_H_INCLUDE | #define STB_SPRINTF_H_INCLUDE | ||||||
| #define STB_SPRINTF_DECORATE(name) Dqn_##name | #define STB_SPRINTF_DECORATE(name) Dqn_##name | ||||||
| @ -857,7 +1200,7 @@ public: | |||||||
| // #DqnPool API
 | // #DqnPool API
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| template <typename T, i16 SIZE> | template <typename T, i16 SIZE> | ||||||
| struct DqnPool | struct DqnFixedPool | ||||||
| { | { | ||||||
|     struct Entry : public T |     struct Entry : public T | ||||||
|     { |     { | ||||||
| @ -870,7 +1213,7 @@ struct DqnPool | |||||||
|     i16    freeIndex; |     i16    freeIndex; | ||||||
|     i16    numFree; |     i16    numFree; | ||||||
| 
 | 
 | ||||||
|     DqnPool() : freeIndex(0) , numFree(SIZE) |     DqnFixedPool() : freeIndex(0) , numFree(SIZE) | ||||||
|     { |     { | ||||||
|         DQN_FOR_EACH(i, SIZE - 1) |         DQN_FOR_EACH(i, SIZE - 1) | ||||||
|         { |         { | ||||||
| @ -899,6 +1242,54 @@ struct DqnPool | |||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // #DqnPool API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | template <typename T> | ||||||
|  | struct DqnPool | ||||||
|  | { | ||||||
|  |     struct Entry : public T | ||||||
|  |     { | ||||||
|  |         u16 nextIndex; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     Entry  *pool; | ||||||
|  |     i16     freeIndex; | ||||||
|  |     i16     numFree; | ||||||
|  |     i32     size; | ||||||
|  | 
 | ||||||
|  |     void UseMemory(Entry *pool_, isize size) | ||||||
|  |     { | ||||||
|  |         pool      = pool_; | ||||||
|  |         freeIndex = 0; | ||||||
|  |         numFree   = size; | ||||||
|  | 
 | ||||||
|  |         DQN_FOR_EACH(i, size - 1) | ||||||
|  |         { | ||||||
|  |             Entry *entry     = pool + i; | ||||||
|  |             entry->nextIndex = i + 1; | ||||||
|  |         } | ||||||
|  |         Entry *last     = pool + (size - 1); | ||||||
|  |         last->nextIndex = size; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     T *GetNext() | ||||||
|  |     { | ||||||
|  |         if (freeIndex == size) return nullptr; | ||||||
|  |         Entry *result = pool + freeIndex; | ||||||
|  |         freeIndex     = result->nextIndex; | ||||||
|  |         numFree--; | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void Return(T *item) | ||||||
|  |     { | ||||||
|  |         auto *entry      = reinterpret_cast<Entry *>(item); | ||||||
|  |         entry->nextIndex = freeIndex; | ||||||
|  |         freeIndex        = entry - pool; | ||||||
|  |         numFree++; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| FILE_SCOPE DqnMemAPI DQN_DEFAULT_HEAP_ALLOCATOR_ = DqnMemAPI::HeapAllocator(); | FILE_SCOPE DqnMemAPI DQN_DEFAULT_HEAP_ALLOCATOR_ = DqnMemAPI::HeapAllocator(); | ||||||
| FILE_SCOPE DqnMemAPI *DQN_DEFAULT_HEAP_ALLOCATOR = &DQN_DEFAULT_HEAP_ALLOCATOR_; | FILE_SCOPE DqnMemAPI *DQN_DEFAULT_HEAP_ALLOCATOR = &DQN_DEFAULT_HEAP_ALLOCATOR_; | ||||||
| 
 | 
 | ||||||
| @ -924,6 +1315,7 @@ struct DqnArray | |||||||
|     void  Resize     (isize newCount)                             { if (newCount > max) Reserve(GrowCapacity_(newCount)); count = newCount; } |     void  Resize     (isize newCount)                             { if (newCount > max) Reserve(GrowCapacity_(newCount)); count = newCount; } | ||||||
|     void  Resize     (isize newCount, T const *v)                 { if (newCount > max) Reserve(GrowCapacity_(newCount)); if (newCount > count) for (isize n = count; n < newCount; n++) data[n] = *v; count = newCount; } |     void  Resize     (isize newCount, T const *v)                 { if (newCount > max) Reserve(GrowCapacity_(newCount)); if (newCount > count) for (isize n = count; n < newCount; n++) data[n] = *v; count = newCount; } | ||||||
|     void  Reserve    (isize newMax); |     void  Reserve    (isize newMax); | ||||||
|  |     T    *Make       (isize num = 1)                              { count += num; if (count > max) Reserve(GrowCapacity_(count)); return &data[count - num]; } | ||||||
|     T    *Push       (T const &v)                                 { return Insert(count, &v, 1); } |     T    *Push       (T const &v)                                 { return Insert(count, &v, 1); } | ||||||
|     T    *Push       (T const *v, isize numItems = 1)             { return Insert(count,  v, numItems); } |     T    *Push       (T const *v, isize numItems = 1)             { return Insert(count,  v, numItems); } | ||||||
|     void  Pop        ()                                           { if (count > 0) count--; } |     void  Pop        ()                                           { if (count > 0) count--; } | ||||||
| @ -2462,11 +2854,78 @@ DQN_FILE_SCOPE DqnJson DqnJson_GetNextArrayItem(DqnJson *iterator); | |||||||
| #ifndef DQN_PLATFORM_H | #ifndef DQN_PLATFORM_H | ||||||
| #define DQN_PLATFORM_H | #define DQN_PLATFORM_H | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_UNIX) | #if defined(DQN_IS_UNIX) | ||||||
|     #include <pthread.h> |     #include <pthread.h> | ||||||
|     #include <semaphore.h> |     #include <semaphore.h> | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | // XPlatform > #DqnOS API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | DQN_FILE_SCOPE void *DqnOS_VAlloc(isize size, void *baseAddress = nullptr); | ||||||
|  | DQN_FILE_SCOPE void  DqnOS_VFree (void *address, isize size); | ||||||
|  | 
 | ||||||
|  | // Uses a single call to DqnMem_Calloc() and DqnMem_Free(). Not completely platform "independent" for Unix.
 | ||||||
|  | // numCores: numThreadsPerCore: Can be nullptr, the function will just skip it.
 | ||||||
|  | DQN_FILE_SCOPE void DqnOS_GetThreadsAndCores(u32 *const numCores, u32 *const numThreadsPerCore); | ||||||
|  | 
 | ||||||
|  | // #XPlatform > #DqnVArray Array backed by virtual memory
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | template<typename T> | ||||||
|  | struct DqnVArray | ||||||
|  | { | ||||||
|  |     isize  count;   // Read
 | ||||||
|  |     isize  max;     // Read
 | ||||||
|  |     T     *data;    // Read
 | ||||||
|  | 
 | ||||||
|  |      DqnVArray       ()                                           { count = 0; max = DQN_MEGABYTE(1) / sizeof(T); data = (T *)DqnOS_VAlloc(max * sizeof(T)); DQN_ASSERT(data); } | ||||||
|  |     ~DqnVArray       ()                                           { if (data)   DqnOS_VFree(data, sizeof(T) * max); } | ||||||
|  |     void  Clear      (Dqn::ZeroClear clear = Dqn::ZeroClear::Yes) { if (data) { count = 0; if (clear == Dqn::ZeroClear::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } } | ||||||
|  |     void  Free       ()                                           { if (data) { DqnOS_VFree(data, sizeof(T) * max); } *this = {}; } | ||||||
|  |     T    *Front      ()                                           { DQN_ASSERT(count > 0); return data + 0; } | ||||||
|  |     T    *Back       ()                                           { DQN_ASSERT(count > 0); return data + (count - 1); } | ||||||
|  |     T    *Make       (isize num = 1)                              { count += num; DQN_ASSERT(count < max); return &data[count - num]; } | ||||||
|  |     T    *Push       (T const &v)                                 { return Insert(count, &v, 1); } | ||||||
|  |     T    *Push       (T const *v, isize numItems = 1)             { return Insert(count,  v, numItems); } | ||||||
|  |     void  Pop        ()                                           { if (count > 0) count--; } | ||||||
|  |     void  Erase      (isize index)                                { DQN_ASSERT(index >= 0 && index < count); data[index] = data[--count]; } | ||||||
|  |     void  EraseStable(isize index); | ||||||
|  |     T    *Insert     (isize index, T const *v)                    { return Insert(index,  v, 1); } | ||||||
|  |     T    *Insert     (isize index, T const &v)                    { return Insert(index, &v, 1); } | ||||||
|  |     T    *Insert     (isize index, T const *v, isize numItems); | ||||||
|  |     bool  Contains   (T const *v) const                           { T const *ptr = data;  T const *end = data + count; while (ptr < end) if (*ptr++ == *v) return true; return false; } | ||||||
|  | 
 | ||||||
|  |     T    &operator[] (isize i) const                              { DQN_ASSERT(i < count && i > 0); return this->data[i]; } | ||||||
|  |     T    *begin      ()                                           { return data; } | ||||||
|  |     T    *end        ()                                           { return data + count; } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template<typename T> T *DqnVArray<T>::Insert(isize index, T const *v, isize numItems) | ||||||
|  | { | ||||||
|  |     index                = DQN_MIN(DQN_MAX(index, 0), count); | ||||||
|  |     isize const newCount = count + numItems; | ||||||
|  |     DQN_ASSERT(newCount < max); | ||||||
|  | 
 | ||||||
|  |     T *src  = data + index; | ||||||
|  |     T *dest = src + numItems; | ||||||
|  | 
 | ||||||
|  |     if (src < dest) | ||||||
|  |         memmove(dest, src, ((data + count) - src) * sizeof(T)); | ||||||
|  | 
 | ||||||
|  |     count = newCount; | ||||||
|  |     for (isize i = 0; i < numItems; i++) | ||||||
|  |         src[i] = v[i]; | ||||||
|  | 
 | ||||||
|  |     return src; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename T> void DqnVArray<T>::EraseStable(isize index) | ||||||
|  | { | ||||||
|  |     DQN_ASSERT(index >= 0 && index < count); | ||||||
|  |     isize const off = (data + index) - data; | ||||||
|  |     memmove(data + off, data + off + 1, ((usize)count - (usize)off - 1) * sizeof(T)); | ||||||
|  |     count--; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // XPlatform > #DqnFile API
 | // XPlatform > #DqnFile API
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| struct DqnFile | struct DqnFile | ||||||
| @ -2573,7 +3032,7 @@ DQN_FILE_SCOPE f64  DqnTimer_NowInS (); | |||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| typedef struct DqnLock | typedef struct DqnLock | ||||||
| { | { | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     CRITICAL_SECTION win32Handle; |     CRITICAL_SECTION win32Handle; | ||||||
| #else | #else | ||||||
|     pthread_mutex_t  unixHandle; |     pthread_mutex_t  unixHandle; | ||||||
| @ -2647,7 +3106,7 @@ struct DqnJobQueue | |||||||
|     i32   volatile jobToExecuteIndex; |     i32   volatile jobToExecuteIndex; | ||||||
|     i32   volatile numJobsToComplete; |     i32   volatile numJobsToComplete; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     void *semaphore; |     void *semaphore; | ||||||
| #else | #else | ||||||
|     sem_t semaphore; |     sem_t semaphore; | ||||||
| @ -2705,18 +3164,12 @@ DQN_FILE_SCOPE i32 DqnAtomic_CompareSwap32(i32 volatile *const dest, const i32 s | |||||||
| // return: The new value at src
 | // return: The new value at src
 | ||||||
| DQN_FILE_SCOPE i32 DqnAtomic_Add32(i32 volatile *const src, const i32 value); | DQN_FILE_SCOPE i32 DqnAtomic_Add32(i32 volatile *const src, const i32 value); | ||||||
| 
 | 
 | ||||||
| // XPlatform > #DqnOS API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| // Uses a single call to DqnMem_Calloc() and DqnMem_Free(). Not completely platform "independent" for Unix.
 |  | ||||||
| // numCores: numThreadsPerCore: Can be nullptr, the function will just skip it.
 |  | ||||||
| DQN_FILE_SCOPE void DqnOS_GetThreadsAndCores(u32 *const numCores, u32 *const numThreadsPerCore); |  | ||||||
| 
 |  | ||||||
| // #Platform Specific API
 | // #Platform Specific API
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| // Functions here are only available for the #defined sections (i.e. all functions in
 | // Functions here are only available for the #defined sections (i.e. all functions in
 | ||||||
| // DQN__IS_WIN32 only have a valid implementation in Win32.
 | // DQN_IS_WIN32 only have a valid implementation in Win32.
 | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
| // Platform > #DqnWin32 API
 | // Platform > #DqnWin32 API
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| #define DQN__WIN32_ERROR_BOX(text, title) MessageBoxA(nullptr, text, title, MB_OK); | #define DQN__WIN32_ERROR_BOX(text, title) MessageBoxA(nullptr, text, title, MB_OK); | ||||||
| @ -2750,7 +3203,7 @@ DQN_FILE_SCOPE void DqnWin32_OutputDebugString(const char *const formatStr, ...) | |||||||
| // return: The offset to the last backslash. -1 if bufLen was not large enough or buf is null. (i.e.
 | // return: The offset to the last backslash. -1 if bufLen was not large enough or buf is null. (i.e.
 | ||||||
| //         buf + offsetToLastSlash + 1, gives C:/Path/)
 | //         buf + offsetToLastSlash + 1, gives C:/Path/)
 | ||||||
| DQN_FILE_SCOPE i32  DqnWin32_GetEXEDirectory(char *const buf, const u32 bufLen); | DQN_FILE_SCOPE i32  DqnWin32_GetEXEDirectory(char *const buf, const u32 bufLen); | ||||||
| #endif // DQN__IS_WIN32
 | #endif // DQN_IS_WIN32
 | ||||||
| #endif // DQN_PLATFORM_H
 | #endif // DQN_PLATFORM_H
 | ||||||
| #endif // DQN_PLATFORM_HEADER
 | #endif // DQN_PLATFORM_HEADER
 | ||||||
| 
 | 
 | ||||||
| @ -2802,7 +3255,7 @@ DQN_FILE_SCOPE void DqnLog(char const *file, char const *functionName, i32 lineN | |||||||
|     char const *const formatStr = "%s:%s,%d: DqnLog: %s\n"; |     char const *const formatStr = "%s:%s,%d: DqnLog: %s\n"; | ||||||
|     fprintf(stderr, formatStr, file, functionName, lineNum, userMsg); |     fprintf(stderr, formatStr, file, functionName, lineNum, userMsg); | ||||||
| 
 | 
 | ||||||
|     #if defined(DQN__IS_WIN32) |     #if defined(DQN_IS_WIN32) | ||||||
|         DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, userMsg); |         DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, userMsg); | ||||||
|     #endif |     #endif | ||||||
| } | } | ||||||
| @ -2837,7 +3290,7 @@ DQN_FILE_SCOPE void DqnLogExpr(char const *file, char const *functionName, i32 l | |||||||
|     char const *const formatStr = ":%s:%s,%d(%s): DqnLog: %s\n"; |     char const *const formatStr = ":%s:%s,%d(%s): DqnLog: %s\n"; | ||||||
|     fprintf(stderr, formatStr, file, functionName, lineNum, expr, userMsg); |     fprintf(stderr, formatStr, file, functionName, lineNum, expr, userMsg); | ||||||
| 
 | 
 | ||||||
|     #if defined(DQN__IS_WIN32) |     #if defined(DQN_IS_WIN32) | ||||||
|         DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, expr, userMsg); |         DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, expr, userMsg); | ||||||
|     #endif |     #endif | ||||||
| } | } | ||||||
| @ -5733,13 +6186,13 @@ FILE_SCOPE u64 DqnRnd__Murmur3Avalanche64(u64 h) | |||||||
|     return h; |     return h; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_UNIX) | #if defined(DQN_IS_UNIX) | ||||||
|     #include <x86intrin.h> // __rdtsc |     #include <x86intrin.h> // __rdtsc | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| FILE_SCOPE u32 DqnRnd__MakeSeed() | FILE_SCOPE u32 DqnRnd__MakeSeed() | ||||||
| { | { | ||||||
| #if defined(DQN_PLATFORM_IMPLEMENTATION) && (defined(DQN__IS_WIN32) || defined(DQN__IS_UNIX)) | #if defined(DQN_PLATFORM_IMPLEMENTATION) && (defined(DQN_IS_WIN32) || defined(DQN_IS_UNIX)) | ||||||
|     i64 numClockCycles = __rdtsc(); |     i64 numClockCycles = __rdtsc(); | ||||||
|     return (u32)numClockCycles; |     return (u32)numClockCycles; | ||||||
| #else | #else | ||||||
| @ -5946,7 +6399,7 @@ bool DqnString::InitLiteral(wchar_t const *cstr, DqnMemStack *stack) | |||||||
| 
 | 
 | ||||||
| bool DqnString::InitLiteral(wchar_t const *cstr, DqnMemAPI *api) | bool DqnString::InitLiteral(wchar_t const *cstr, DqnMemAPI *api) | ||||||
| { | { | ||||||
| #if defined(DQN__IS_WIN32) && defined(DQN_PLATFORM_IMPLEMENTATION) | #if defined(DQN_IS_WIN32) && defined(DQN_PLATFORM_IMPLEMENTATION) | ||||||
|     i32 reqLenInclNullTerminator = DqnWin32_WCharToUTF8(cstr, nullptr, 0); |     i32 reqLenInclNullTerminator = DqnWin32_WCharToUTF8(cstr, nullptr, 0); | ||||||
|     if (!this->InitSize(reqLenInclNullTerminator - 1, api)) |     if (!this->InitSize(reqLenInclNullTerminator - 1, api)) | ||||||
|     { |     { | ||||||
| @ -6175,7 +6628,7 @@ void DqnString::Free() | |||||||
| 
 | 
 | ||||||
| i32 DqnString::ToWChar(wchar_t *buf, i32 bufSize) const | i32 DqnString::ToWChar(wchar_t *buf, i32 bufSize) const | ||||||
| { | { | ||||||
| #if defined(DQN__IS_WIN32) && defined(DQN_PLATFORM_IMPLEMENTATION) | #if defined(DQN_IS_WIN32) && defined(DQN_PLATFORM_IMPLEMENTATION) | ||||||
|     i32 result = DqnWin32_UTF8ToWChar(this->str, buf, bufSize); |     i32 result = DqnWin32_UTF8ToWChar(this->str, buf, bufSize); | ||||||
|     return result; |     return result; | ||||||
| 
 | 
 | ||||||
| @ -6191,7 +6644,7 @@ wchar_t *DqnString::ToWChar(DqnMemAPI *api) const | |||||||
|     // TODO(doyle): Should the "in" string allow specifyign len? probably
 |     // TODO(doyle): Should the "in" string allow specifyign len? probably
 | ||||||
|     // Otherwise a c-string and a literal initiated string might have different lengths
 |     // Otherwise a c-string and a literal initiated string might have different lengths
 | ||||||
|     // to wchar will produce an unintuitive output
 |     // to wchar will produce an unintuitive output
 | ||||||
| #if defined(DQN__IS_WIN32) && defined(DQN_PLATFORM_IMPLEMENTATION) | #if defined(DQN_IS_WIN32) && defined(DQN_PLATFORM_IMPLEMENTATION) | ||||||
|     i32 requiredLenInclNull = DqnWin32_UTF8ToWChar(this->str, nullptr, 0); |     i32 requiredLenInclNull = DqnWin32_UTF8ToWChar(this->str, nullptr, 0); | ||||||
| 
 | 
 | ||||||
|     i32 allocSize = sizeof(wchar_t) * requiredLenInclNull; |     i32 allocSize = sizeof(wchar_t) * requiredLenInclNull; | ||||||
| @ -8133,7 +8586,7 @@ static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, c | |||||||
| // Functions in the Cross Platform are guaranteed to be supported in both Unix
 | // Functions in the Cross Platform are guaranteed to be supported in both Unix
 | ||||||
| // and Win32
 | // and Win32
 | ||||||
| 
 | 
 | ||||||
| #ifdef DQN__IS_UNIX | #ifdef DQN_IS_UNIX | ||||||
|     #include <stdio.h>    // Basic File I/O // TODO(doyle): Syscall versions |     #include <stdio.h>    // Basic File I/O // TODO(doyle): Syscall versions | ||||||
| 
 | 
 | ||||||
|     #include <dirent.h>   // readdir()/opendir()/closedir() |     #include <dirent.h>   // readdir()/opendir()/closedir() | ||||||
| @ -8147,7 +8600,7 @@ static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, c | |||||||
| 
 | 
 | ||||||
| // XPlatform > #DqnFile
 | // XPlatform > #DqnFile
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| #ifdef DQN__IS_WIN32 | #ifdef DQN_IS_WIN32 | ||||||
| 
 | 
 | ||||||
| FILE_SCOPE bool | FILE_SCOPE bool | ||||||
| DqnFile__Win32Open(wchar_t const *path, DqnFile *file, u32 flags, DqnFile::Action action) | DqnFile__Win32Open(wchar_t const *path, DqnFile *file, u32 flags, DqnFile::Action action) | ||||||
| @ -8307,9 +8760,9 @@ DQN_FILE__LIST_DIR(DqnFile__PlatformListDir) | |||||||
|         return list; |         return list; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| #endif // DQN__IS_WIN32
 | #endif // DQN_IS_WIN32
 | ||||||
| 
 | 
 | ||||||
| #ifdef DQN__IS_UNIX | #ifdef DQN_IS_UNIX | ||||||
| FILE_SCOPE bool DqnFile__UnixGetFileSize(char const *path, usize *size) | FILE_SCOPE bool DqnFile__UnixGetFileSize(char const *path, usize *size) | ||||||
| { | { | ||||||
|     struct stat fileStat = {}; |     struct stat fileStat = {}; | ||||||
| @ -8464,13 +8917,13 @@ DQN_FILE__LIST_DIR(DqnFile__PlatformListDir) | |||||||
|         return list; |         return list; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| #endif // DQN__IS_UNIX
 | #endif // DQN_IS_UNIX
 | ||||||
| 
 | 
 | ||||||
| bool DqnFile::Open(char const *path, u32 flags_, Action action) | bool DqnFile::Open(char const *path, u32 flags_, Action action) | ||||||
| { | { | ||||||
|     if (!path) return false; |     if (!path) return false; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     // TODO(doyle): MAX PATH is baad
 |     // TODO(doyle): MAX PATH is baad
 | ||||||
|     wchar_t widePath[MAX_PATH] = {}; |     wchar_t widePath[MAX_PATH] = {}; | ||||||
|     DqnWin32_UTF8ToWChar(path, widePath, DQN_ARRAY_COUNT(widePath)); |     DqnWin32_UTF8ToWChar(path, widePath, DQN_ARRAY_COUNT(widePath)); | ||||||
| @ -8484,7 +8937,7 @@ bool DqnFile::Open(wchar_t const *path, u32 flags_, Action action) | |||||||
| { | { | ||||||
|     if (!path) return false; |     if (!path) return false; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     return DqnFile__Win32Open(path, this, flags_, action); |     return DqnFile__Win32Open(path, this, flags_, action); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -8499,7 +8952,7 @@ usize DqnFile::Write(u8 const *buf, usize numBytesToWrite, usize fileOffset) | |||||||
|     DQN_ASSERTM(fileOffset == 0, "File writing into offset is not implemented."); |     DQN_ASSERTM(fileOffset == 0, "File writing into offset is not implemented."); | ||||||
|     usize numBytesWritten = 0; |     usize numBytesWritten = 0; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     DWORD bytesToWrite = (DWORD)numBytesToWrite; |     DWORD bytesToWrite = (DWORD)numBytesToWrite; | ||||||
|     DWORD bytesWritten; |     DWORD bytesWritten; | ||||||
|     BOOL result = WriteFile(this->handle, (void *)buf, bytesToWrite, &bytesWritten, nullptr); |     BOOL result = WriteFile(this->handle, (void *)buf, bytesToWrite, &bytesWritten, nullptr); | ||||||
| @ -8528,7 +8981,7 @@ usize DqnFile::Read(u8 *buf, usize numBytesToRead) | |||||||
|     usize numBytesRead = 0; |     usize numBytesRead = 0; | ||||||
|     if (this->handle) |     if (this->handle) | ||||||
|     { |     { | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|         DWORD bytesToRead = (DWORD)numBytesToRead; |         DWORD bytesToRead = (DWORD)numBytesToRead; | ||||||
|         DWORD bytesRead    = 0; |         DWORD bytesRead    = 0; | ||||||
|         HANDLE win32Handle = this->handle; |         HANDLE win32Handle = this->handle; | ||||||
| @ -8666,7 +9119,7 @@ void DqnFile::Close() | |||||||
| { | { | ||||||
|     if (this->handle) |     if (this->handle) | ||||||
|     { |     { | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|         CloseHandle(this->handle); |         CloseHandle(this->handle); | ||||||
| #else | #else | ||||||
|         fclose((FILE *)this->handle); |         fclose((FILE *)this->handle); | ||||||
| @ -8678,7 +9131,7 @@ void DqnFile::Close() | |||||||
|     this->flags = 0; |     this->flags = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     DQN_COMPILE_ASSERT(sizeof(DWORD)  == sizeof(u32)); |     DQN_COMPILE_ASSERT(sizeof(DWORD)  == sizeof(u32)); | ||||||
| #endif | #endif | ||||||
| bool DqnFile::GetFileSize(wchar_t const *path, usize *size) | bool DqnFile::GetFileSize(wchar_t const *path, usize *size) | ||||||
| @ -8700,7 +9153,7 @@ bool DqnFile::GetFileSize(char const *path, usize *size) | |||||||
|     if (!path || !size) return false; |     if (!path || !size) return false; | ||||||
| 
 | 
 | ||||||
|     // TODO(doyle): Logging
 |     // TODO(doyle): Logging
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     // TODO(doyle): MAX PATH is baad
 |     // TODO(doyle): MAX PATH is baad
 | ||||||
|     wchar_t widePath[MAX_PATH] = {0}; |     wchar_t widePath[MAX_PATH] = {0}; | ||||||
|     DqnWin32_UTF8ToWChar(path, widePath, DQN_ARRAY_COUNT(widePath)); |     DqnWin32_UTF8ToWChar(path, widePath, DQN_ARRAY_COUNT(widePath)); | ||||||
| @ -8717,7 +9170,7 @@ bool DqnFile::GetInfo(wchar_t const *path, Info *info) | |||||||
| { | { | ||||||
|     if (!path || !info) return false; |     if (!path || !info) return false; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     auto FileTimeToSeconds = [](FILETIME const *time) -> i64 { |     auto FileTimeToSeconds = [](FILETIME const *time) -> i64 { | ||||||
|         ULARGE_INTEGER timeLargeInt = {}; |         ULARGE_INTEGER timeLargeInt = {}; | ||||||
|         timeLargeInt.LowPart        = time->dwLowDateTime; |         timeLargeInt.LowPart        = time->dwLowDateTime; | ||||||
| @ -8760,7 +9213,7 @@ bool DqnFile::GetInfo(char const *path, Info *info) | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     // TODO(doyle): MAX PATH is baad
 |     // TODO(doyle): MAX PATH is baad
 | ||||||
|     wchar_t widePath[MAX_PATH] = {}; |     wchar_t widePath[MAX_PATH] = {}; | ||||||
|     DqnWin32_UTF8ToWChar(path, widePath, DQN_ARRAY_COUNT(widePath)); |     DqnWin32_UTF8ToWChar(path, widePath, DQN_ARRAY_COUNT(widePath)); | ||||||
| @ -8788,7 +9241,7 @@ bool DqnFile::Delete(char const *path) | |||||||
|     if (!path) return false; |     if (!path) return false; | ||||||
| 
 | 
 | ||||||
| // TODO(doyle): Logging
 | // TODO(doyle): Logging
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     return DeleteFileA(path); |     return DeleteFileA(path); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -8805,7 +9258,7 @@ bool DqnFile::Delete(wchar_t const *path) | |||||||
|     if (!path) return false; |     if (!path) return false; | ||||||
| 
 | 
 | ||||||
|     // TODO(doyle): Logging
 |     // TODO(doyle): Logging
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     return DeleteFileW(path); |     return DeleteFileW(path); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -8820,7 +9273,7 @@ bool DqnFile::Copy(char const *src, char const *dest) | |||||||
|     if (!src || !dest) return false; |     if (!src || !dest) return false; | ||||||
| 
 | 
 | ||||||
|     // TODO(doyle): Logging
 |     // TODO(doyle): Logging
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     BOOL result = (CopyFileA(src, dest, /*FailIfExist*/false) != 0); |     BOOL result = (CopyFileA(src, dest, /*FailIfExist*/false) != 0); | ||||||
|     if (result == 0) |     if (result == 0) | ||||||
|     { |     { | ||||||
| @ -8840,7 +9293,7 @@ bool DqnFile::Copy(wchar_t const *src, wchar_t const *dest) | |||||||
|     if (!src || !dest) return false; |     if (!src || !dest) return false; | ||||||
| 
 | 
 | ||||||
|     // TODO(doyle): Logging
 |     // TODO(doyle): Logging
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     return (CopyFileW(src, dest, /*FailIfExist*/false) != 0); |     return (CopyFileW(src, dest, /*FailIfExist*/false) != 0); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -8872,7 +9325,7 @@ void DqnFile::ListDirFree(char **fileList, i32 numFiles, DqnMemAPI *api) | |||||||
| 
 | 
 | ||||||
| // XPlatform > #DqnTimer
 | // XPlatform > #DqnTimer
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| #if defined (DQN__IS_WIN32) | #if defined (DQN_IS_WIN32) | ||||||
| FILE_SCOPE f64 DqnTimerInternal_Win32QueryPerfCounterTimeInMs() | FILE_SCOPE f64 DqnTimerInternal_Win32QueryPerfCounterTimeInMs() | ||||||
| { | { | ||||||
|     LOCAL_PERSIST LARGE_INTEGER queryPerformanceFrequency = {0}; |     LOCAL_PERSIST LARGE_INTEGER queryPerformanceFrequency = {0}; | ||||||
| @ -8896,7 +9349,7 @@ FILE_SCOPE f64 DqnTimerInternal_Win32QueryPerfCounterTimeInMs() | |||||||
| DQN_FILE_SCOPE f64 DqnTimer_NowInMs() | DQN_FILE_SCOPE f64 DqnTimer_NowInMs() | ||||||
| { | { | ||||||
|     f64 result = 0; |     f64 result = 0; | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     result = DQN_MAX(DqnTimerInternal_Win32QueryPerfCounterTimeInMs(), 0); |     result = DQN_MAX(DqnTimerInternal_Win32QueryPerfCounterTimeInMs(), 0); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -8923,7 +9376,7 @@ bool DqnLock_Init(DqnLock *lock) | |||||||
| { | { | ||||||
|     if (!lock) return false; |     if (!lock) return false; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     if (InitializeCriticalSectionEx(&lock->win32Handle, lock->win32SpinCount, 0)) |     if (InitializeCriticalSectionEx(&lock->win32Handle, lock->win32SpinCount, 0)) | ||||||
|         return true; |         return true; | ||||||
| #else | #else | ||||||
| @ -8941,7 +9394,7 @@ void DqnLock_Acquire(DqnLock *lock) | |||||||
| { | { | ||||||
|     if (!lock) return; |     if (!lock) return; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     EnterCriticalSection(&lock->win32Handle); |     EnterCriticalSection(&lock->win32Handle); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -8955,7 +9408,7 @@ void DqnLock_Release(DqnLock *lock) | |||||||
| { | { | ||||||
|     if (!lock) return; |     if (!lock) return; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     LeaveCriticalSection(&lock->win32Handle); |     LeaveCriticalSection(&lock->win32Handle); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -8969,7 +9422,7 @@ void DqnLock_Delete(DqnLock *lock) | |||||||
| { | { | ||||||
|     if (!lock) return; |     if (!lock) return; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     DeleteCriticalSection(&lock->win32Handle); |     DeleteCriticalSection(&lock->win32Handle); | ||||||
| #else | #else | ||||||
|     i32 error = pthread_mutex_destroy(&lock->unixHandle); |     i32 error = pthread_mutex_destroy(&lock->unixHandle); | ||||||
| @ -9017,7 +9470,7 @@ FILE_SCOPE u32 DqnJobQueueInternal_ThreadCreate(usize stackSize, | |||||||
| { | { | ||||||
|     u32 numThreadsCreated = 0; |     u32 numThreadsCreated = 0; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     DQN_ASSERT(stackSize == 0 || !threadCallback); |     DQN_ASSERT(stackSize == 0 || !threadCallback); | ||||||
|     for (u32 i = 0; i < numThreads; i++) |     for (u32 i = 0; i < numThreads; i++) | ||||||
|     { |     { | ||||||
| @ -9058,7 +9511,7 @@ FILE_SCOPE void *DqnJobQueueInternal_ThreadCallback(void *threadParam) | |||||||
|     { |     { | ||||||
|         if (!DqnJobQueue_TryExecuteNextJob(queue)) |         if (!DqnJobQueue_TryExecuteNextJob(queue)) | ||||||
|         { |         { | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|             WaitForSingleObjectEx(queue->semaphore, INFINITE, false); |             WaitForSingleObjectEx(queue->semaphore, INFINITE, false); | ||||||
| #else | #else | ||||||
|             sem_wait(&queue->semaphore); |             sem_wait(&queue->semaphore); | ||||||
| @ -9071,7 +9524,7 @@ FILE_SCOPE bool DqnJobQueueInternal_CreateSemaphore(DqnJobQueue *queue, u32 init | |||||||
| { | { | ||||||
|     if (!queue) return false; |     if (!queue) return false; | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     queue->semaphore = (void *)CreateSemaphoreA(nullptr, initSignalCount, maxSignalCount, nullptr); |     queue->semaphore = (void *)CreateSemaphoreA(nullptr, initSignalCount, maxSignalCount, nullptr); | ||||||
|     DQN_ASSERT(queue->semaphore); |     DQN_ASSERT(queue->semaphore); | ||||||
| 
 | 
 | ||||||
| @ -9093,7 +9546,7 @@ FILE_SCOPE bool DqnJobQueueInternal_ReleaseSemaphore(DqnJobQueue *queue) | |||||||
| { | { | ||||||
|     DQN_ASSERT(queue); |     DQN_ASSERT(queue); | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     DQN_ASSERT(queue->semaphore); |     DQN_ASSERT(queue->semaphore); | ||||||
|     ReleaseSemaphore(queue->semaphore, 1, nullptr); |     ReleaseSemaphore(queue->semaphore, 1, nullptr); | ||||||
| 
 | 
 | ||||||
| @ -9192,14 +9645,14 @@ bool DqnJobQueue::AllJobsComplete  ()                 { return DqnJobQueue_AllJo | |||||||
| // XPlatform > #DqnAtomic
 | // XPlatform > #DqnAtomic
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     DQN_COMPILE_ASSERT(sizeof(LONG) == sizeof(i32)); |     DQN_COMPILE_ASSERT(sizeof(LONG) == sizeof(i32)); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE i32 DqnAtomic_CompareSwap32(i32 volatile *dest, i32 swapVal, i32 compareVal) | DQN_FILE_SCOPE i32 DqnAtomic_CompareSwap32(i32 volatile *dest, i32 swapVal, i32 compareVal) | ||||||
| { | { | ||||||
|     i32 result = 0; |     i32 result = 0; | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     result = (i32)InterlockedCompareExchange((LONG volatile *)dest, (LONG)swapVal, (LONG)compareVal); |     result = (i32)InterlockedCompareExchange((LONG volatile *)dest, (LONG)swapVal, (LONG)compareVal); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -9211,7 +9664,7 @@ DQN_FILE_SCOPE i32 DqnAtomic_CompareSwap32(i32 volatile *dest, i32 swapVal, i32 | |||||||
| DQN_FILE_SCOPE i32 DqnAtomic_Add32(i32 volatile *src, i32 value) | DQN_FILE_SCOPE i32 DqnAtomic_Add32(i32 volatile *src, i32 value) | ||||||
| { | { | ||||||
|     i32 result = 0; |     i32 result = 0; | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
|     result = (i32)InterlockedAdd((LONG volatile *)src, value); |     result = (i32)InterlockedAdd((LONG volatile *)src, value); | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| @ -9223,10 +9676,41 @@ DQN_FILE_SCOPE i32 DqnAtomic_Add32(i32 volatile *src, i32 value) | |||||||
| 
 | 
 | ||||||
| // XPlatform > #DqnOS
 | // XPlatform > #DqnOS
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
|  | #if defined(DQN_IS_UNIX) | ||||||
|  | include <sys/mman.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | void *DqnOS_VAlloc(isize size, void *baseAddress) | ||||||
|  | { | ||||||
|  |     void *result = nullptr; | ||||||
|  | #if defined (DQN_IS_WIN32) | ||||||
|  |     result = VirtualAlloc(baseAddress, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); | ||||||
|  |     DQN_ASSERT(result); | ||||||
|  | #else | ||||||
|  |     result = mmap( | ||||||
|  |         baseAddress, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1 /*fd*/, 0 /*offset into fd*/); | ||||||
|  |     DQN_ASSERT(result != MAP_FAILED); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DqnOS_VFree(void *address, isize size) | ||||||
|  | { | ||||||
|  | #if defined (DQN_IS_WIN32) | ||||||
|  |     BOOL result = VirtualFree(address, 0 /*size*/, MEM_RELEASE); | ||||||
|  |     (void)size; | ||||||
|  |     DQN_ASSERT(result); | ||||||
|  | #else | ||||||
|  |     int result = munmap(address, size); | ||||||
|  |     DQN_ASSERT(result != 0); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #define DQN_OS_GET_THREADS_AND_CORES(name) \ | #define DQN_OS_GET_THREADS_AND_CORES(name) \ | ||||||
|     DQN_FILE_SCOPE void name(u32 *const numCores, u32 *const numThreadsPerCore) |     DQN_FILE_SCOPE void name(u32 *const numCores, u32 *const numThreadsPerCore) | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_UNIX) | #if defined(DQN_IS_UNIX) | ||||||
| DQN_OS_GET_THREADS_AND_CORES(DqnOS_GetThreadsAndCores) | DQN_OS_GET_THREADS_AND_CORES(DqnOS_GetThreadsAndCores) | ||||||
| { | { | ||||||
|     if (!numThreadsPerCore && !numCores) return; |     if (!numThreadsPerCore && !numCores) return; | ||||||
| @ -9289,9 +9773,9 @@ DQN_OS_GET_THREADS_AND_CORES(DqnOS_GetThreadsAndCores) | |||||||
|         DQN_ASSERT(DQN_INVALID_CODE_PATH); |         DQN_ASSERT(DQN_INVALID_CODE_PATH); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| #endif // DQN__IS_UNIX
 | #endif // DQN_IS_UNIX
 | ||||||
| 
 | 
 | ||||||
| #if defined(DQN__IS_WIN32) | #if defined(DQN_IS_WIN32) | ||||||
| DQN_OS_GET_THREADS_AND_CORES(DqnOS_GetThreadsAndCores) | DQN_OS_GET_THREADS_AND_CORES(DqnOS_GetThreadsAndCores) | ||||||
| { | { | ||||||
|     if (numThreadsPerCore) |     if (numThreadsPerCore) | ||||||
| @ -9348,9 +9832,9 @@ DQN_OS_GET_THREADS_AND_CORES(DqnOS_GetThreadsAndCores) | |||||||
|         DqnMem_Free(rawProcInfoArray); |         DqnMem_Free(rawProcInfoArray); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| #endif // DQN__IS_WIN32
 | #endif // DQN_IS_WIN32
 | ||||||
| 
 | 
 | ||||||
| #ifdef DQN__IS_WIN32 | #ifdef DQN_IS_WIN32 | ||||||
| // #DqnWin32
 | // #DqnWin32
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| DQN_FILE_SCOPE i32 DqnWin32_UTF8ToWChar(char const *in, wchar_t *out, i32 outLen) | DQN_FILE_SCOPE i32 DqnWin32_UTF8ToWChar(char const *in, wchar_t *out, i32 outLen) | ||||||
| @ -9460,5 +9944,5 @@ DQN_FILE_SCOPE i32 DqnWin32_GetEXEDirectory(char *buf, u32 bufLen) | |||||||
| 
 | 
 | ||||||
|     return lastSlashIndex; |     return lastSlashIndex; | ||||||
| } | } | ||||||
| #endif // DQN__IS_WIN32
 | #endif // DQN_IS_WIN32
 | ||||||
| #endif // DQN__XPLATFORM_LAYER
 | #endif // DQN__XPLATFORM_LAYER
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user