chore(fmod): add files from Chensne/DragonNest
This commit is contained in:
commit
50fb3c6b1c
544 changed files with 315778 additions and 0 deletions
329
win32/src/MeteredSection.cpp
Executable file
329
win32/src/MeteredSection.cpp
Executable file
|
|
@ -0,0 +1,329 @@
|
|||
/************************************************************
|
||||
Module Name: MeteredSection.c
|
||||
Author: Dan Chou
|
||||
Description: Implements the metered section synchronization object
|
||||
************************************************************/
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include "MeteredSection.h"
|
||||
#include "../../src/fmod_memory.h"
|
||||
|
||||
// Internal function declarations
|
||||
BOOL InitMeteredSection(LPMETERED_SECTION lpMetSect, LONG lInitialCount,
|
||||
LONG lMaximumCount, LPCTSTR lpName, BOOL bOpenOnly);
|
||||
BOOL CreateMetSectEvent(LPMETERED_SECTION lpMetSect, LPCTSTR lpName, BOOL
|
||||
bOpenOnly);
|
||||
BOOL CreateMetSectFileView(LPMETERED_SECTION lpMetSect, LONG lInitialCount,
|
||||
LONG lMaximumCount, LPCTSTR lpName, BOOL bOpenOnly);
|
||||
void GetMeteredSectionLock(LPMETERED_SECTION lpMetSect);
|
||||
void ReleaseMeteredSectionLock(LPMETERED_SECTION lpMetSect);
|
||||
|
||||
/*
|
||||
* CreateMeteredSection
|
||||
*/
|
||||
LPMETERED_SECTION CreateMeteredSection(LONG lInitialCount,
|
||||
LONG lMaximumCount, LPCTSTR lpName)
|
||||
{
|
||||
LPMETERED_SECTION lpMetSect;
|
||||
|
||||
// Verify the parameters
|
||||
if ((lMaximumCount < 1) ||
|
||||
(lInitialCount > lMaximumCount) ||
|
||||
(lInitialCount < 0) ||
|
||||
((lpName) && (_tcslen(lpName) > MAX_METSECT_NAMELEN)))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate memory for the metered section
|
||||
lpMetSect = (LPMETERED_SECTION)FMOD_Memory_Alloc(sizeof(METERED_SECTION));
|
||||
|
||||
// If the memory for the metered section was allocated okay,
|
||||
// initialize it
|
||||
if (lpMetSect)
|
||||
{
|
||||
if (!InitMeteredSection(lpMetSect, lInitialCount,
|
||||
lMaximumCount, lpName, FALSE))
|
||||
{
|
||||
CloseMeteredSection(lpMetSect);
|
||||
lpMetSect = NULL;
|
||||
}
|
||||
}
|
||||
return lpMetSect;
|
||||
}
|
||||
|
||||
/*
|
||||
* OpenMeteredSection
|
||||
*/
|
||||
#ifndef _WIN32_WCE
|
||||
LPMETERED_SECTION OpenMeteredSection(LPCTSTR lpName)
|
||||
{
|
||||
LPMETERED_SECTION lpMetSect = NULL;
|
||||
|
||||
if (lpName)
|
||||
{
|
||||
lpMetSect = (LPMETERED_SECTION)FMOD_Memory_Alloc(sizeof(METERED_SECTION));
|
||||
|
||||
// If the memory for the metered section was allocated okay
|
||||
if (lpMetSect)
|
||||
{
|
||||
if (!InitMeteredSection(lpMetSect, 0, 0, lpName, TRUE))
|
||||
{
|
||||
// Metered section failed to initialize
|
||||
CloseMeteredSection(lpMetSect);
|
||||
lpMetSect = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lpMetSect;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* EnterMeteredSection
|
||||
*/
|
||||
DWORD EnterMeteredSection(LPMETERED_SECTION lpMetSect,
|
||||
DWORD dwMilliseconds)
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
GetMeteredSectionLock(lpMetSect);
|
||||
|
||||
// We have access to the metered section, everything we
|
||||
// do now will be atomic
|
||||
if (lpMetSect->lpSharedInfo->lAvailableCount >= 1)
|
||||
{
|
||||
lpMetSect->lpSharedInfo->lAvailableCount--;
|
||||
ReleaseMeteredSectionLock(lpMetSect);
|
||||
return WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
// Couldn't get in. Wait on the event object
|
||||
lpMetSect->lpSharedInfo->lThreadsWaiting++;
|
||||
ResetEvent(lpMetSect->hEvent);
|
||||
ReleaseMeteredSectionLock(lpMetSect);
|
||||
if (WaitForSingleObject(lpMetSect->hEvent,
|
||||
dwMilliseconds) == WAIT_TIMEOUT)
|
||||
{
|
||||
return WAIT_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LeaveMeteredSection
|
||||
*/
|
||||
BOOL LeaveMeteredSection(LPMETERED_SECTION lpMetSect, LONG lReleaseCount,
|
||||
LPLONG lpPreviousCount)
|
||||
{
|
||||
int iCount;
|
||||
GetMeteredSectionLock(lpMetSect);
|
||||
|
||||
// Save the old value if they want it
|
||||
if (lpPreviousCount)
|
||||
{
|
||||
*lpPreviousCount = lpMetSect->lpSharedInfo->lAvailableCount;
|
||||
}
|
||||
|
||||
// We have access to the metered section,
|
||||
// everything we do now will be atomic
|
||||
if ((lReleaseCount < 0) ||
|
||||
(lpMetSect->lpSharedInfo->lAvailableCount+lReleaseCount >
|
||||
lpMetSect->lpSharedInfo->lMaximumCount))
|
||||
{
|
||||
ReleaseMeteredSectionLock(lpMetSect);
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
lpMetSect->lpSharedInfo->lAvailableCount += lReleaseCount;
|
||||
|
||||
// Set the event the appropriate number of times
|
||||
lReleaseCount =
|
||||
min(lReleaseCount,lpMetSect->lpSharedInfo->lThreadsWaiting);
|
||||
if (lpMetSect->lpSharedInfo->lThreadsWaiting)
|
||||
{
|
||||
for (iCount=0; iCount < lReleaseCount ; iCount++)
|
||||
{
|
||||
lpMetSect->lpSharedInfo->lThreadsWaiting--;
|
||||
SetEvent(lpMetSect->hEvent);
|
||||
}
|
||||
}
|
||||
ReleaseMeteredSectionLock(lpMetSect);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* CloseMeteredSection
|
||||
*/
|
||||
void CloseMeteredSection(LPMETERED_SECTION lpMetSect)
|
||||
{
|
||||
if (lpMetSect)
|
||||
{
|
||||
// Clean up
|
||||
#ifdef FILEMAPPING
|
||||
if (lpMetSect->lpSharedInfo) UnmapViewOfFile(lpMetSect->lpSharedInfo);
|
||||
if (lpMetSect->hFileMap) CloseHandle(lpMetSect->hFileMap);
|
||||
#else
|
||||
DeleteCriticalSection(&lpMetSect->hCrit);
|
||||
#endif
|
||||
|
||||
if (lpMetSect->hEvent) CloseHandle(lpMetSect->hEvent);
|
||||
FMOD_Memory_Free(lpMetSect);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* InitMeteredSection
|
||||
*/
|
||||
BOOL InitMeteredSection(LPMETERED_SECTION lpMetSect,
|
||||
LONG lInitialCount, LONG lMaximumCount,
|
||||
LPCTSTR lpName, BOOL bOpenOnly)
|
||||
{
|
||||
// Try to create the event object
|
||||
if (CreateMetSectEvent(lpMetSect, lpName, bOpenOnly))
|
||||
{
|
||||
#ifdef FILEMAPPING
|
||||
// Try to create the memory mapped file
|
||||
if (CreateMetSectFileView(lpMetSect, lInitialCount, lMaximumCount, lpName, bOpenOnly))
|
||||
#else
|
||||
lpMetSect->lpSharedInfo = &lpMetSect->SharedInfo;
|
||||
lpMetSect->lpSharedInfo->lThreadsWaiting = 0;
|
||||
lpMetSect->lpSharedInfo->lAvailableCount = lInitialCount;
|
||||
lpMetSect->lpSharedInfo->lMaximumCount = lMaximumCount;
|
||||
InitializeCriticalSection(&lpMetSect->hCrit);
|
||||
InterlockedExchange((long *)&(lpMetSect->lpSharedInfo->fInitialized), TRUE);
|
||||
#endif
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Error occured, return FALSE so the caller knows to clean up
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* CreateMetSectEvent
|
||||
*/
|
||||
BOOL CreateMetSectEvent(LPMETERED_SECTION lpMetSect,
|
||||
LPCTSTR lpName, BOOL bOpenOnly)
|
||||
{
|
||||
TCHAR sz[MAX_PATH];
|
||||
if (lpName)
|
||||
{
|
||||
//wsprintf(sz, _TEXT("DKC_MSECT_EVT_%s"), lpName);
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
if (bOpenOnly)
|
||||
{
|
||||
lpMetSect->hEvent = OpenEvent(0, FALSE, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
// Create an auto-reset named event object
|
||||
lpMetSect->hEvent = CreateEvent(NULL, FALSE, FALSE, sz);
|
||||
#ifndef _WIN32_WCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an auto-reset unnamed event object
|
||||
lpMetSect->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
}
|
||||
return (lpMetSect->hEvent ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
#ifdef FILEMAPPING
|
||||
/*
|
||||
* CreateMetSectFileView
|
||||
*/
|
||||
BOOL CreateMetSectFileView(LPMETERED_SECTION lpMetSect,
|
||||
LONG lInitialCount, LONG lMaximumCount,
|
||||
LPCTSTR lpName, BOOL bOpenOnly)
|
||||
{
|
||||
TCHAR sz[MAX_PATH];
|
||||
DWORD dwLastError;
|
||||
|
||||
if (lpName)
|
||||
{
|
||||
//wsprintf(sz, _TEXT("DKC_MSECT_MMF_%s"), lpName);
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
if (bOpenOnly)
|
||||
{
|
||||
lpMetSect->hFileMap = OpenFileMapping(0, FALSE, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
// Create a named file mapping
|
||||
lpMetSect->hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,
|
||||
NULL, PAGE_READWRITE, 0, sizeof(METSECT_SHARED_INFO), sz);
|
||||
#ifndef _WIN32_WCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an unnamed file mapping
|
||||
lpMetSect->hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,
|
||||
NULL, PAGE_READWRITE, 0, sizeof(METSECT_SHARED_INFO), NULL);
|
||||
}
|
||||
|
||||
// Map a view of the file
|
||||
if (lpMetSect->hFileMap)
|
||||
{
|
||||
dwLastError = GetLastError();
|
||||
lpMetSect->lpSharedInfo = (LPMETSECT_SHARED_INFO)
|
||||
MapViewOfFile(lpMetSect->hFileMap, FILE_MAP_WRITE, 0, 0, 0);
|
||||
if (lpMetSect->lpSharedInfo)
|
||||
{
|
||||
if (dwLastError != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
lpMetSect->lpSharedInfo->lSpinLock = 0;
|
||||
lpMetSect->lpSharedInfo->lThreadsWaiting = 0;
|
||||
lpMetSect->lpSharedInfo->lAvailableCount = lInitialCount;
|
||||
lpMetSect->lpSharedInfo->lMaximumCount = lMaximumCount;
|
||||
InterlockedExchange((long *)&(lpMetSect->lpSharedInfo->fInitialized), TRUE);
|
||||
}
|
||||
else
|
||||
{ // Already exists; wait for it to be initialized by the creator
|
||||
while (!lpMetSect->lpSharedInfo->fInitialized) Sleep(0);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GetMeteredSectionLock
|
||||
*/
|
||||
void GetMeteredSectionLock(LPMETERED_SECTION lpMetSect)
|
||||
{
|
||||
#if FILEMAPPING
|
||||
// Spin and get access to the metered section lock
|
||||
while (InterlockedExchange(&(lpMetSect->lpSharedInfo->lSpinLock), 1) != 0)
|
||||
Sleep(1);
|
||||
#else
|
||||
EnterCriticalSection(&lpMetSect->hCrit);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ReleaseMeteredSectionLock
|
||||
*/
|
||||
void ReleaseMeteredSectionLock(LPMETERED_SECTION lpMetSect)
|
||||
{
|
||||
#if FILEMAPPING
|
||||
InterlockedExchange(&(lpMetSect->lpSharedInfo->lSpinLock), 0);
|
||||
#else
|
||||
LeaveCriticalSection(&lpMetSect->hCrit);
|
||||
#endif
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue