-
Metered Section
Hello,
I have read in the MSDN about metered sections and it seems like the right way to synchronise between a few applications I have.
I tried using the CreateMeteredSection function but I got the following compilation error: d:\Projects\MyProject\MeterSec.cpp(1174): error C3861: 'CreateMeteredSection': identifier not found, even with argument-dependent lookup
I have no idea which include to add I also don't find this function in the MSDN indexing, I saw it only in an article from 1998 'A Quick and Versatile Synchronization Object'
Anyone knows about this Meterd Section, or maybe anyone has anothe way for fast synchronisation between 2 process?
Thanks
avi
-
the msdn contains the full source of meteredsection.h:
Code:
/************************************************************
Module Name: MeteredSection.h
Author: Dan Chou
Description: Defines the metered section synchronization object
************************************************************/
#ifndef _METERED_SECTION_H_
#define _METERED_SECTION_H_
#define MAX_METSECT_NAMELEN 128
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
// Shared info needed for metered section
typedef struct _METSECT_SHARED_INFO {
BOOL fInitialized; // Is the metered section initialized?
LONG lSpinLock; // Used to gain access to this structure
LONG lThreadsWaiting; // Count of threads waiting
LONG lAvailableCount; // Available resource count
LONG lMaximumCount; // Maximum resource count
} METSECT_SHARED_INFO, *LPMETSECT_SHARED_INFO;
// The opaque Metered Section data structure
typedef struct _METERED_SECTION {
HANDLE hEvent; // Handle to a kernel event object
HANDLE hFileMap; // Handle to memory mapped file
LPMETSECT_SHARED_INFO lpSharedInfo;
} METERED_SECTION, *LPMETERED_SECTION;
// Interface functions
LPMETERED_SECTION
CreateMeteredSection(LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);
#ifndef _WIN32_WCE
LPMETERED_SECTION OpenMeteredSection(LPCTSTR lpName);
#endif
DWORD EnterMeteredSection(LPMETERED_SECTION lpMetSect,
DWORD dwMilliseconds);
BOOL LeaveMeteredSection(LPMETERED_SECTION lpMetSect,
LONG lReleaseCount, LPLONG lpPreviousCount);
void CloseMeteredSection(LPMETERED_SECTION lpMetSect);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _METERED_SECTION_H_
-
and meteredsection.c:
Code:
/************************************************************
Module Name: MeteredSection.c
Author: Dan Chou
Description: Implements the metered section synchronization object
************************************************************/
#include <windows.h>
#include <tchar.h>
#include "MeteredSection.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)malloc(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)malloc(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
if (lpMetSect->lpSharedInfo)
UnmapViewOfFile(lpMetSect->lpSharedInfo);
if (lpMetSect->hFileMap) CloseHandle(lpMetSect->hFileMap);
if (lpMetSect->hEvent) CloseHandle(lpMetSect->hEvent);
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))
{
// Try to create the memory mapped file
if (CreateMetSectFileView(lpMetSect,
lInitialCount, lMaximumCount, lpName, bOpenOnly))
{
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);
}
/*
* 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(&(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;
}
/*
* GetMeteredSectionLock
*/
void GetMeteredSectionLock(LPMETERED_SECTION lpMetSect)
{
// Spin and get access to the metered section lock
while (InterlockedExchange(&(lpMetSect->lpSharedInfo->lSpinLock), 1) != 0)
Sleep(0);
}
/*
* ReleaseMeteredSectionLock
*/
void ReleaseMeteredSectionLock(LPMETERED_SECTION lpMetSect)
{
InterlockedExchange(&(lpMetSect->lpSharedInfo->lSpinLock), 0);
}
-
just create those files and add them to your project ...
taken from: Here
-
this link might be some interest to you....
CreateMeteredSection in MSDN
[edit]... nohero posted it already :)