|
@@ -1,1202 +0,0 @@
|
|
|
-/****************************************************************************
|
|
|
-
|
|
|
- (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
|
|
|
- www.systec-electronic.com
|
|
|
-
|
|
|
- Project: Project independend shared buffer (linear + circular)
|
|
|
-
|
|
|
- Description: Implementation of platform specific part for the
|
|
|
- shared buffer
|
|
|
- (Implementation for Win32)
|
|
|
-
|
|
|
- License:
|
|
|
-
|
|
|
- Redistribution and use in source and binary forms, with or without
|
|
|
- modification, are permitted provided that the following conditions
|
|
|
- are met:
|
|
|
-
|
|
|
- 1. Redistributions of source code must retain the above copyright
|
|
|
- notice, this list of conditions and the following disclaimer.
|
|
|
-
|
|
|
- 2. Redistributions in binary form must reproduce the above copyright
|
|
|
- notice, this list of conditions and the following disclaimer in the
|
|
|
- documentation and/or other materials provided with the distribution.
|
|
|
-
|
|
|
- 3. Neither the name of SYSTEC electronic GmbH nor the names of its
|
|
|
- contributors may be used to endorse or promote products derived
|
|
|
- from this software without prior written permission. For written
|
|
|
- permission, please contact info@systec-electronic.com.
|
|
|
-
|
|
|
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
- COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
|
- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
- POSSIBILITY OF SUCH DAMAGE.
|
|
|
-
|
|
|
- Severability Clause:
|
|
|
-
|
|
|
- If a provision of this License is or becomes illegal, invalid or
|
|
|
- unenforceable in any jurisdiction, that shall not affect:
|
|
|
- 1. the validity or enforceability in that jurisdiction of any other
|
|
|
- provision of this License; or
|
|
|
- 2. the validity or enforceability in other jurisdictions of that or
|
|
|
- any other provision of this License.
|
|
|
-
|
|
|
- -------------------------------------------------------------------------
|
|
|
-
|
|
|
- 2006/06/27 -rs: V 1.00 (initial version)
|
|
|
-
|
|
|
-****************************************************************************/
|
|
|
-
|
|
|
-#define WINVER 0x0400 // #defines necessary for usage of
|
|
|
-#define _WIN32_WINNT 0x0400 // function <SignalObjectAndWait>
|
|
|
-
|
|
|
-#include <windows.h>
|
|
|
-#include <stdio.h>
|
|
|
-#include "global.h"
|
|
|
-#include "sharedbuff.h"
|
|
|
-#include "shbipc.h"
|
|
|
-
|
|
|
-/***************************************************************************/
|
|
|
-/* */
|
|
|
-/* */
|
|
|
-/* G L O B A L D E F I N I T I O N S */
|
|
|
-/* */
|
|
|
-/* */
|
|
|
-/***************************************************************************/
|
|
|
-
|
|
|
-#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Configuration
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Constant definitions
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-#define MAX_LEN_BUFFER_ID MAX_PATH
|
|
|
-
|
|
|
-#define IDX_EVENT_NEW_DATA 0
|
|
|
-#define IDX_EVENT_TERM_REQU 1
|
|
|
-#define IDX_EVENT_TERM_RESP 2
|
|
|
-
|
|
|
-#define NAME_MUTEX_BUFF_ACCESS "BuffAccess"
|
|
|
-#define NAME_EVENT_NEW_DATA "NewData"
|
|
|
-#define NAME_EVENT_TERM_REQU "TermRequ"
|
|
|
-#define NAME_EVENT_TERM_RESP "TermResp"
|
|
|
-#define NAME_EVENT_JOB_READY "JobReady"
|
|
|
-
|
|
|
-#define TIMEOUT_ENTER_ATOMIC 1000 // for debgging: INFINITE
|
|
|
-#define TIMEOUT_TERM_THREAD 2000
|
|
|
-
|
|
|
-#define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
|
|
|
-#define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Local types
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-// This structure is the common header for the shared memory region used
|
|
|
-// by all processes attached this shared memory. It includes common
|
|
|
-// information to administrate/manage the shared buffer from a couple of
|
|
|
-// separated processes (e.g. the refernce counter). This structure is
|
|
|
-// located at the start of the shared memory region itself and exists
|
|
|
-// consequently only one times per shared memory instance.
|
|
|
-typedef struct {
|
|
|
- unsigned long m_SbhMagicID; // magic ID ("SBH*")
|
|
|
- unsigned long m_ulShMemSize;
|
|
|
- unsigned long m_ulRefCount;
|
|
|
- char m_szBufferID[MAX_LEN_BUFFER_ID];
|
|
|
-
|
|
|
-#ifndef NDEBUG
|
|
|
- unsigned long m_ulOwnerProcID;
|
|
|
-#endif
|
|
|
-
|
|
|
-} tShbMemHeader;
|
|
|
-
|
|
|
-// This structure is the "external entry point" from a separate process
|
|
|
-// to get access to a shared buffer. This structure includes all platform
|
|
|
-// resp. target specific information to administrate/manage the shared
|
|
|
-// buffer from a separate process. Every process attached to the shared
|
|
|
-// buffer has its own runtime instance of this structure with its individual
|
|
|
-// runtime data (e.g. the scope of an event handle is limitted to the
|
|
|
-// owner process only). The structure member <m_pShbMemHeader> points
|
|
|
-// to the (process specific) start address of the shared memory region
|
|
|
-// itself.
|
|
|
-typedef struct {
|
|
|
- unsigned long m_SbiMagicID; // magic ID ("SBI+")
|
|
|
- HANDLE m_hSharedMem;
|
|
|
- HANDLE m_hMutexBuffAccess;
|
|
|
- HANDLE m_hThreadNewData; // thraed to signal that new data are available
|
|
|
- HANDLE m_ahEventNewData[3]; // IDX_EVENT_NEW_DATA + IDX_EVENT_TERM_REQU + ID_EVENT_TERM_RESP
|
|
|
- tSigHndlrNewData m_pfnSigHndlrNewData;
|
|
|
- HANDLE m_hThreadJobReady; // thread to signal that a job/operation is ready now (e.g. reset buffer)
|
|
|
- HANDLE m_hEventJobReady;
|
|
|
- unsigned long m_ulTimeOutJobReady;
|
|
|
- tSigHndlrJobReady m_pfnSigHndlrJobReady;
|
|
|
- tShbMemHeader *m_pShbMemHeader;
|
|
|
-
|
|
|
-#ifndef NDEBUG
|
|
|
- unsigned long m_ulThreadIDNewData;
|
|
|
- unsigned long m_ulThreadIDJobReady;
|
|
|
-#endif
|
|
|
-
|
|
|
-} tShbMemInst;
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Global variables
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Local variables
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Prototypes of internal functions
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Get pointer to process local information structure
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
-
|
|
|
- pShbMemInst = (tShbMemInst *) pShbInstance_p;
|
|
|
- ASSERT(pShbMemInst->m_SbiMagicID == SBI_MAGIC_ID);
|
|
|
-
|
|
|
- return (pShbMemInst);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Get pointer to shared memory header
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbMemHeader *ShbIpcGetShbMemHeader(tShbInstance
|
|
|
- pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- tShbMemHeader *pShbMemHeader;
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
- pShbMemHeader = pShbMemInst->m_pShbMemHeader;
|
|
|
- ASSERT(pShbMemHeader->m_SbhMagicID == SBH_MAGIC_ID);
|
|
|
-
|
|
|
- return (pShbMemHeader);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-// not inlined internal functions
|
|
|
-DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p);
|
|
|
-DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p);
|
|
|
-const char *ShbIpcGetUniformObjectName(const char *pszEventJobName_p,
|
|
|
- const char *pszBufferID_p,
|
|
|
- BOOL fGlobalObject_p);
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#if !defined(SHBIPC_INLINE_ENABLED)
|
|
|
-// true internal functions (not inlined)
|
|
|
-static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p);
|
|
|
-static void ShbIpcReleasePrivateMem(void *pMem_p);
|
|
|
-#endif
|
|
|
-
|
|
|
-//=========================================================================//
|
|
|
-// //
|
|
|
-// P U B L I C F U N C T I O N S //
|
|
|
-// //
|
|
|
-//=========================================================================//
|
|
|
-
|
|
|
-#if !defined(SHBIPC_INLINE_ENABLED)
|
|
|
-// not inlined external functions
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Initialize IPC for Shared Buffer Module
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-tShbError ShbIpcInit(void)
|
|
|
-{
|
|
|
-
|
|
|
- return (kShbOk);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Deinitialize IPC for Shared Buffer Module
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-tShbError ShbIpcExit(void)
|
|
|
-{
|
|
|
-
|
|
|
- return (kShbOk);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Allocate Shared Buffer
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
|
|
|
- const char *pszBufferID_p,
|
|
|
- tShbInstance * ppShbInstance_p,
|
|
|
- unsigned int *pfShbNewCreated_p)
|
|
|
-{
|
|
|
-
|
|
|
- HANDLE hSharedMem;
|
|
|
- LPVOID pSharedMem;
|
|
|
- unsigned long ulShMemSize;
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- tShbMemHeader *pShbMemHeader;
|
|
|
- tShbInstance pShbInstance;
|
|
|
- unsigned int fShMemNewCreated;
|
|
|
- const char *pszObjectName;
|
|
|
- HANDLE hMutexBuffAccess;
|
|
|
- HANDLE hEventNewData;
|
|
|
- HANDLE hEventJobReady;
|
|
|
- tShbError ShbError;
|
|
|
-
|
|
|
- ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
|
|
|
- pSharedMem = NULL;
|
|
|
- pShbInstance = NULL;
|
|
|
- fShMemNewCreated = FALSE;
|
|
|
- ShbError = kShbOk;
|
|
|
-
|
|
|
- //---------------------------------------------------------------
|
|
|
- // (1) open an existing or create a new shared memory
|
|
|
- //---------------------------------------------------------------
|
|
|
- // try to open an already existing shared memory
|
|
|
- // (created by an another process)
|
|
|
- hSharedMem = OpenFileMapping(FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess
|
|
|
- FALSE, // BOOL bInheritHandle
|
|
|
- pszBufferID_p); // LPCTSTR lpName
|
|
|
- if (hSharedMem != NULL) {
|
|
|
- // a shared memory already exists
|
|
|
- fShMemNewCreated = FALSE;
|
|
|
- } else {
|
|
|
- // it seams that this process is the first who wants to use the
|
|
|
- // shared memory, so it has to create a new shared memory
|
|
|
- hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE, // HANDLE hFile
|
|
|
- NULL, // LPSECURITY_ATTRIBUTES lpAttributes
|
|
|
- PAGE_READWRITE, // DWORD flProtect
|
|
|
- 0, // DWORD dwMaximumSizeHigh
|
|
|
- ulShMemSize, // DWORD dwMaximumSizeLow
|
|
|
- pszBufferID_p); // LPCTSTR lpName
|
|
|
-
|
|
|
- fShMemNewCreated = TRUE;
|
|
|
- }
|
|
|
-
|
|
|
- if (hSharedMem == NULL) {
|
|
|
- ShbError = kShbOutOfMem;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- //---------------------------------------------------------------
|
|
|
- // (2) get the pointer to the shared memory
|
|
|
- //---------------------------------------------------------------
|
|
|
- pSharedMem = MapViewOfFile(hSharedMem, // HANDLE hFileMappingObject
|
|
|
- FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess,
|
|
|
- 0, // DWORD dwFileOffsetHigh,
|
|
|
- 0, // DWORD dwFileOffsetLow,
|
|
|
- ulShMemSize); // SIZE_T dwNumberOfBytesToMap
|
|
|
-
|
|
|
- if (pSharedMem == NULL) {
|
|
|
- ShbError = kShbOutOfMem;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- //---------------------------------------------------------------
|
|
|
- // (3) setup or update header and management information
|
|
|
- //---------------------------------------------------------------
|
|
|
- pShbMemHeader = (tShbMemHeader *) pSharedMem;
|
|
|
-
|
|
|
- // allocate a memory block from process specific mempool to save
|
|
|
- // process local information to administrate/manage the shared buffer
|
|
|
- pShbMemInst =
|
|
|
- (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst));
|
|
|
- if (pShbMemInst == NULL) {
|
|
|
- ShbError = kShbOutOfMem;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
- // reset complete header to default values
|
|
|
- pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID;
|
|
|
- pShbMemInst->m_hSharedMem = hSharedMem;
|
|
|
- pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
|
|
|
- pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] =
|
|
|
- INVALID_HANDLE_VALUE;
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] =
|
|
|
- INVALID_HANDLE_VALUE;
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] =
|
|
|
- INVALID_HANDLE_VALUE;
|
|
|
- pShbMemInst->m_pfnSigHndlrNewData = NULL;
|
|
|
- pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
|
|
|
- pShbMemInst->m_hEventJobReady = INVALID_HANDLE_VALUE;
|
|
|
- pShbMemInst->m_ulTimeOutJobReady = 0;
|
|
|
- pShbMemInst->m_pfnSigHndlrJobReady = NULL;
|
|
|
- pShbMemInst->m_pShbMemHeader = pShbMemHeader;
|
|
|
-
|
|
|
-#ifndef NDEBUG
|
|
|
- {
|
|
|
- pShbMemInst->m_ulThreadIDNewData = 0;
|
|
|
- pShbMemInst->m_ulThreadIDJobReady = 0;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- // create mutex for buffer access
|
|
|
- pszObjectName =
|
|
|
- ShbIpcGetUniformObjectName(NAME_MUTEX_BUFF_ACCESS, pszBufferID_p,
|
|
|
- TRUE);
|
|
|
- hMutexBuffAccess = CreateMutex(NULL, // LPSECURITY_ATTRIBUTES lpMutexAttributes
|
|
|
- FALSE, // BOOL bInitialOwner
|
|
|
- pszObjectName); // LPCTSTR lpName
|
|
|
- pShbMemInst->m_hMutexBuffAccess = hMutexBuffAccess;
|
|
|
- ASSERT(pShbMemInst->m_hMutexBuffAccess != NULL);
|
|
|
-
|
|
|
- // The EventNewData is used for signaling of new data after a write
|
|
|
- // operation (SetEvent) as well as for waiting for new data on the
|
|
|
- // reader side (WaitForMultipleObjects). Because it's not known if
|
|
|
- // this process will be read or write data, the event will be
|
|
|
- // always created here.
|
|
|
- pszObjectName =
|
|
|
- ShbIpcGetUniformObjectName(NAME_EVENT_NEW_DATA, pszBufferID_p,
|
|
|
- TRUE);
|
|
|
- hEventNewData = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
|
|
|
- FALSE, // BOOL bManualReset
|
|
|
- FALSE, // BOOL bInitialState
|
|
|
- pszObjectName); // LPCTSTR lpName
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = hEventNewData;
|
|
|
- ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != NULL);
|
|
|
-
|
|
|
- // The EventJobReady is used for signaling that a job is done (SetEvent)
|
|
|
- // as well as for waiting for finishing of a job (WaitForMultipleObjects).
|
|
|
- // Because it's not known if this process will signal or wait, the event
|
|
|
- // will be always created here.
|
|
|
- pszObjectName =
|
|
|
- ShbIpcGetUniformObjectName(NAME_EVENT_JOB_READY, pszBufferID_p,
|
|
|
- TRUE);
|
|
|
- hEventJobReady = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
|
|
|
- FALSE, // BOOL bManualReset
|
|
|
- FALSE, // BOOL bInitialState
|
|
|
- pszObjectName); // LPCTSTR lpName
|
|
|
- pShbMemInst->m_hEventJobReady = hEventJobReady;
|
|
|
- ASSERT(pShbMemInst->m_hEventJobReady != NULL);
|
|
|
-
|
|
|
- if (fShMemNewCreated) {
|
|
|
- // this process was the first who wanted to use the shared memory,
|
|
|
- // so a new shared memory was created
|
|
|
- // -> setup new header information inside the shared memory region
|
|
|
- // itself
|
|
|
- pShbMemHeader->m_SbhMagicID = SBH_MAGIC_ID;
|
|
|
- pShbMemHeader->m_ulShMemSize = ulShMemSize;
|
|
|
- pShbMemHeader->m_ulRefCount = 1;
|
|
|
- strncpy(pShbMemHeader->m_szBufferID, pszBufferID_p,
|
|
|
- sizeof(pShbMemHeader->m_szBufferID) - 1);
|
|
|
-
|
|
|
-#ifndef NDEBUG
|
|
|
- {
|
|
|
- pShbMemHeader->m_ulOwnerProcID = GetCurrentProcessId();
|
|
|
- }
|
|
|
-#endif
|
|
|
- } else {
|
|
|
- // any other process has created the shared memory and this
|
|
|
- // process has only attached to it
|
|
|
- // -> check and update existing header information inside the
|
|
|
- // shared memory region itself
|
|
|
- if (pShbMemHeader->m_ulShMemSize != ulShMemSize) {
|
|
|
- ShbError = kShbOpenMismatch;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-#ifndef NDEBUG
|
|
|
- {
|
|
|
- if (strncmp
|
|
|
- (pShbMemHeader->m_szBufferID, pszBufferID_p,
|
|
|
- sizeof(pShbMemHeader->m_szBufferID) - 1)) {
|
|
|
- ShbError = kShbOpenMismatch;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- pShbMemHeader->m_ulRefCount++;
|
|
|
- }
|
|
|
-
|
|
|
- // set abstarct "handle" for returning to application
|
|
|
- pShbInstance = (tShbInstance *) pShbMemInst;
|
|
|
-
|
|
|
- Exit:
|
|
|
-
|
|
|
- if (ShbError != kShbOk) {
|
|
|
- if (pShbMemInst != NULL) {
|
|
|
- ShbIpcReleasePrivateMem(pShbMemInst);
|
|
|
- }
|
|
|
- if (pSharedMem != NULL) {
|
|
|
- UnmapViewOfFile(pSharedMem);
|
|
|
- }
|
|
|
- if (hSharedMem != NULL) {
|
|
|
- CloseHandle(hSharedMem);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- *pfShbNewCreated_p = fShMemNewCreated;
|
|
|
- *ppShbInstance_p = pShbInstance;
|
|
|
-
|
|
|
- return (ShbError);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Release Shared Buffer
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- tShbMemHeader *pShbMemHeader;
|
|
|
- HANDLE hEventNewData;
|
|
|
- HANDLE hMutexBuffAccess;
|
|
|
- tShbError ShbError;
|
|
|
- tShbError ShbError2;
|
|
|
-
|
|
|
- if (pShbInstance_p == NULL) {
|
|
|
- return (kShbOk);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
- pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
|
|
|
-
|
|
|
- if (!--pShbMemHeader->m_ulRefCount) {
|
|
|
- ShbError = kShbOk;
|
|
|
- } else {
|
|
|
- ShbError = kShbMemUsedByOtherProcs;
|
|
|
- }
|
|
|
-
|
|
|
- ShbError2 = ShbIpcStopSignalingNewData(pShbInstance_p);
|
|
|
- hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
|
|
|
- if (hEventNewData != INVALID_HANDLE_VALUE) {
|
|
|
- CloseHandle(hEventNewData);
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] =
|
|
|
- INVALID_HANDLE_VALUE;
|
|
|
- }
|
|
|
-
|
|
|
- hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
|
|
|
- if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
|
|
|
- CloseHandle(hMutexBuffAccess);
|
|
|
- pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
|
|
|
- }
|
|
|
-
|
|
|
- UnmapViewOfFile(pShbMemHeader);
|
|
|
- if (pShbMemInst->m_hSharedMem != INVALID_HANDLE_VALUE) {
|
|
|
- CloseHandle(pShbMemInst->m_hSharedMem);
|
|
|
- pShbMemInst->m_hSharedMem = INVALID_HANDLE_VALUE;
|
|
|
- }
|
|
|
-
|
|
|
- ShbIpcReleasePrivateMem(pShbMemInst);
|
|
|
-
|
|
|
- if (ShbError == kShbOk) {
|
|
|
- ShbError = ShbError2;
|
|
|
- }
|
|
|
-
|
|
|
- return (ShbError);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-#endif // !defined(SHBIPC_INLINE_ENABLED)
|
|
|
-
|
|
|
-#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Enter atomic section for Shared Buffer access
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- HANDLE hMutexBuffAccess;
|
|
|
- DWORD dwWaitResult;
|
|
|
- tShbError ShbError;
|
|
|
-
|
|
|
- if (pShbInstance_p == NULL) {
|
|
|
- return (kShbInvalidArg);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
- ShbError = kShbOk;
|
|
|
-
|
|
|
- hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
|
|
|
- if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
|
|
|
- dwWaitResult =
|
|
|
- WaitForSingleObject(hMutexBuffAccess, TIMEOUT_ENTER_ATOMIC);
|
|
|
- switch (dwWaitResult) {
|
|
|
- case WAIT_OBJECT_0 + 0:
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- case WAIT_TIMEOUT:
|
|
|
- {
|
|
|
- TRACE0
|
|
|
- ("\nShbIpcEnterAtomicSection(): WAIT_TIMEOUT");
|
|
|
- ASSERT(0);
|
|
|
- ShbError = kShbBufferInvalid;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- case WAIT_ABANDONED:
|
|
|
- {
|
|
|
- TRACE0
|
|
|
- ("\nShbIpcEnterAtomicSection(): WAIT_ABANDONED");
|
|
|
- ASSERT(0);
|
|
|
- ShbError = kShbBufferInvalid;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- case WAIT_FAILED:
|
|
|
- {
|
|
|
- TRACE1
|
|
|
- ("\nShbIpcEnterAtomicSection(): WAIT_FAILED -> LastError=%ld",
|
|
|
- GetLastError());
|
|
|
- ASSERT(0);
|
|
|
- ShbError = kShbBufferInvalid;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- default:
|
|
|
- {
|
|
|
- TRACE1
|
|
|
- ("\nShbIpcEnterAtomicSection(): unknown error -> LastError=%ld",
|
|
|
- GetLastError());
|
|
|
- ASSERT(0);
|
|
|
- ShbError = kShbBufferInvalid;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- ShbError = kShbBufferInvalid;
|
|
|
- }
|
|
|
-
|
|
|
- return (ShbError);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Leave atomic section for Shared Buffer access
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- HANDLE hMutexBuffAccess;
|
|
|
- BOOL fRes;
|
|
|
- tShbError ShbError;
|
|
|
-
|
|
|
- if (pShbInstance_p == NULL) {
|
|
|
- return (kShbInvalidArg);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
- ShbError = kShbOk;
|
|
|
-
|
|
|
- hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
|
|
|
- if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
|
|
|
- fRes = ReleaseMutex(hMutexBuffAccess);
|
|
|
- ASSERT(fRes);
|
|
|
- } else {
|
|
|
- ShbError = kShbBufferInvalid;
|
|
|
- }
|
|
|
-
|
|
|
- return (ShbError);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Start signaling of new data (called from reading process)
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance
|
|
|
- pShbInstance_p,
|
|
|
- tSigHndlrNewData
|
|
|
- pfnSignalHandlerNewData_p,
|
|
|
- tShbPriority
|
|
|
- ShbPriority_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- tShbMemHeader *pShbMemHeader;
|
|
|
- const char *pszObjectName;
|
|
|
- HANDLE hEventTermRequ;
|
|
|
- HANDLE hEventTermResp;
|
|
|
- HANDLE hThreadNewData;
|
|
|
- unsigned long ulThreadIDNewData;
|
|
|
- tShbError ShbError;
|
|
|
- int iPriority;
|
|
|
-
|
|
|
- if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) {
|
|
|
- return (kShbInvalidArg);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
- pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
|
|
|
- ShbError = kShbOk;
|
|
|
-
|
|
|
- if ((pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) ||
|
|
|
- (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] !=
|
|
|
- INVALID_HANDLE_VALUE)
|
|
|
- || (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
|
|
|
- INVALID_HANDLE_VALUE)
|
|
|
- || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) {
|
|
|
- ShbError = kShbAlreadySignaling;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
|
|
|
-
|
|
|
- // Because the event <pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]>
|
|
|
- // is used for signaling of new data after a write operation too (using
|
|
|
- // SetEvent), it is always created here (see <ShbIpcAllocBuffer>).
|
|
|
-
|
|
|
- pszObjectName =
|
|
|
- ShbIpcGetUniformObjectName(NAME_EVENT_TERM_REQU,
|
|
|
- pShbMemHeader->m_szBufferID, FALSE);
|
|
|
- hEventTermRequ = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
|
|
|
- FALSE, // BOOL bManualReset
|
|
|
- FALSE, // BOOL bInitialState
|
|
|
- pszObjectName); // LPCTSTR lpName
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = hEventTermRequ;
|
|
|
- ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != NULL);
|
|
|
-
|
|
|
- pszObjectName =
|
|
|
- ShbIpcGetUniformObjectName(NAME_EVENT_TERM_RESP,
|
|
|
- pShbMemHeader->m_szBufferID, FALSE);
|
|
|
- hEventTermResp = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
|
|
|
- FALSE, // BOOL bManualReset
|
|
|
- FALSE, // BOOL bInitialState
|
|
|
- pszObjectName); // LPCTSTR lpName
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = hEventTermResp;
|
|
|
- ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != NULL);
|
|
|
-
|
|
|
- hThreadNewData = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
|
|
|
- 0, // SIZE_T dwStackSize
|
|
|
- ShbIpcThreadSignalNewData, // LPTHREAD_START_ROUTINE lpStartAddress
|
|
|
- pShbInstance_p, // LPVOID lpParameter
|
|
|
- 0, // DWORD dwCreationFlags
|
|
|
- &ulThreadIDNewData); // LPDWORD lpThreadId
|
|
|
-
|
|
|
- switch (ShbPriority_p) {
|
|
|
- case kShbPriorityLow:
|
|
|
- iPriority = THREAD_PRIORITY_BELOW_NORMAL;
|
|
|
- break;
|
|
|
-
|
|
|
- case kShbPriorityNormal:
|
|
|
- iPriority = THREAD_PRIORITY_NORMAL;
|
|
|
- break;
|
|
|
-
|
|
|
- case kshbPriorityHigh:
|
|
|
- iPriority = THREAD_PRIORITY_ABOVE_NORMAL;
|
|
|
- break;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- ASSERT(pShbMemInst->m_hThreadNewData != NULL);
|
|
|
-
|
|
|
- SetThreadPriority(hThreadNewData, iPriority);
|
|
|
-
|
|
|
- pShbMemInst->m_hThreadNewData = hThreadNewData;
|
|
|
-
|
|
|
-#ifndef NDEBUG
|
|
|
- {
|
|
|
- pShbMemInst->m_ulThreadIDNewData = ulThreadIDNewData;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- Exit:
|
|
|
-
|
|
|
- return (ShbError);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Stop signaling of new data (called from reading process)
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance
|
|
|
- pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- HANDLE hEventTermRequ;
|
|
|
- HANDLE hEventTermResp;
|
|
|
- DWORD dwWaitResult;
|
|
|
-
|
|
|
- if (pShbInstance_p == NULL) {
|
|
|
- return (kShbInvalidArg);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
-
|
|
|
- // terminate new data signaling thread
|
|
|
- // (set event <hEventTermRequ> to wakeup the thread and dispose it
|
|
|
- // to exit, then wait for confirmation using event <hEventTermResp>)
|
|
|
- hEventTermRequ = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU];
|
|
|
- hEventTermResp = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP];
|
|
|
- if ((hEventTermRequ != INVALID_HANDLE_VALUE) &&
|
|
|
- (hEventTermResp != INVALID_HANDLE_VALUE)) {
|
|
|
- TRACE0("\nShbIpcStopSignalingNewData(): enter wait state");
|
|
|
- dwWaitResult = SignalObjectAndWait(hEventTermRequ, // HANDLE hObjectToSignal
|
|
|
- hEventTermResp, // HANDLE hObjectToWaitOn
|
|
|
- TIMEOUT_TERM_THREAD, // DWORD dwMilliseconds
|
|
|
- FALSE); // BOOL bAlertable
|
|
|
- TRACE0
|
|
|
- ("\nShbIpcStopSignalingNewData(): wait state leaved: ---> ");
|
|
|
- switch (dwWaitResult) {
|
|
|
- case WAIT_OBJECT_0 + 0: // event "new data signaling thread terminated"
|
|
|
- {
|
|
|
- TRACE0("Event = WAIT_OBJECT_0+0");
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- default:
|
|
|
- {
|
|
|
- TRACE0("Unhandled Event");
|
|
|
- ASSERT(0);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) {
|
|
|
- CloseHandle(pShbMemInst->m_hThreadNewData);
|
|
|
- pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
|
|
|
- }
|
|
|
-
|
|
|
- if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] !=
|
|
|
- INVALID_HANDLE_VALUE) {
|
|
|
- CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]);
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] =
|
|
|
- INVALID_HANDLE_VALUE;
|
|
|
- }
|
|
|
-
|
|
|
- if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
|
|
|
- INVALID_HANDLE_VALUE) {
|
|
|
- CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
|
|
|
- pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] =
|
|
|
- INVALID_HANDLE_VALUE;
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst->m_pfnSigHndlrNewData = NULL;
|
|
|
-
|
|
|
- return (kShbOk);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Signal new data (called from writing process)
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- HANDLE hEventNewData;
|
|
|
- BOOL fRes;
|
|
|
-
|
|
|
- // TRACE0("\nShbIpcSignalNewData(): enter\n");
|
|
|
-
|
|
|
- if (pShbInstance_p == NULL) {
|
|
|
- return (kShbInvalidArg);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
-
|
|
|
- ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] !=
|
|
|
- INVALID_HANDLE_VALUE);
|
|
|
- hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
|
|
|
- if (hEventNewData != INVALID_HANDLE_VALUE) {
|
|
|
- fRes = SetEvent(hEventNewData);
|
|
|
- // TRACE1("\nShbIpcSignalNewData(): EventNewData set (Result=%d)\n", (int)fRes);
|
|
|
- ASSERT(fRes);
|
|
|
- }
|
|
|
- // TRACE0("\nShbIpcSignalNewData(): leave\n");
|
|
|
- return (kShbOk);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Start signaling for job ready (called from waiting process)
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance
|
|
|
- pShbInstance_p,
|
|
|
- unsigned long
|
|
|
- ulTimeOut_p,
|
|
|
- tSigHndlrJobReady
|
|
|
- pfnSignalHandlerJobReady_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- tShbMemHeader *pShbMemHeader;
|
|
|
- HANDLE hThreadJobReady;
|
|
|
- unsigned long ulThreadIDJobReady;
|
|
|
- tShbError ShbError;
|
|
|
-
|
|
|
- if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) {
|
|
|
- return (kShbInvalidArg);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
- pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
|
|
|
- ShbError = kShbOk;
|
|
|
-
|
|
|
- if ((pShbMemInst->m_hThreadJobReady != INVALID_HANDLE_VALUE) ||
|
|
|
- (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) {
|
|
|
- ShbError = kShbAlreadySignaling;
|
|
|
- goto Exit;
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
|
|
|
- pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
|
|
|
-
|
|
|
- // Because the event <pShbMemInst->m_ahEventJobReady> is used for
|
|
|
- // signaling of a finished job too (using SetEvent), it is always
|
|
|
- // created here (see <ShbIpcAllocBuffer>).
|
|
|
-
|
|
|
- hThreadJobReady = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
|
|
|
- 0, // SIZE_T dwStackSize
|
|
|
- ShbIpcThreadSignalJobReady, // LPTHREAD_START_ROUTINE lpStartAddress
|
|
|
- pShbInstance_p, // LPVOID lpParameter
|
|
|
- 0, // DWORD dwCreationFlags
|
|
|
- &ulThreadIDJobReady); // LPDWORD lpThreadId
|
|
|
-
|
|
|
- pShbMemInst->m_hThreadJobReady = hThreadJobReady;
|
|
|
- ASSERT(pShbMemInst->m_hThreadJobReady != NULL);
|
|
|
-
|
|
|
-#ifndef NDEBUG
|
|
|
- {
|
|
|
- pShbMemInst->m_ulThreadIDJobReady = ulThreadIDJobReady;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- Exit:
|
|
|
-
|
|
|
- return (ShbError);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Signal job ready (called from executing process)
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- HANDLE hEventJobReady;
|
|
|
- BOOL fRes;
|
|
|
-
|
|
|
- // TRACE0("\nShbIpcSignalJobReady(): enter\n");
|
|
|
-
|
|
|
- if (pShbInstance_p == NULL) {
|
|
|
- return (kShbInvalidArg);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
|
|
|
-
|
|
|
- ASSERT(pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE);
|
|
|
- hEventJobReady = pShbMemInst->m_hEventJobReady;
|
|
|
- if (hEventJobReady != INVALID_HANDLE_VALUE) {
|
|
|
- fRes = SetEvent(hEventJobReady);
|
|
|
- // TRACE1("\nShbIpcSignalJobReady(): EventJobReady set (Result=%d)\n", (int)fRes);
|
|
|
- ASSERT(fRes);
|
|
|
- }
|
|
|
- // TRACE0("\nShbIpcSignalJobReady(): leave\n");
|
|
|
- return (kShbOk);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Get pointer to common used share memory area
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbMemHeader *pShbMemHeader;
|
|
|
- void *pShbShMemPtr;
|
|
|
-
|
|
|
- pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
|
|
|
- if (pShbMemHeader != NULL) {
|
|
|
- pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader);
|
|
|
- } else {
|
|
|
- pShbShMemPtr = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- return (pShbShMemPtr);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-//=========================================================================//
|
|
|
-// //
|
|
|
-// P R I V A T E F U N C T I O N S //
|
|
|
-// //
|
|
|
-//=========================================================================//
|
|
|
-
|
|
|
-#if !defined(SHBIPC_INLINE_ENABLED)
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Allocate a memory block from process specific mempool
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)
|
|
|
-{
|
|
|
-
|
|
|
- HGLOBAL hMem;
|
|
|
- void *pMem;
|
|
|
-
|
|
|
- hMem = GlobalAlloc(GMEM_FIXED, ulMemSize_p + sizeof(HGLOBAL));
|
|
|
- pMem = GlobalLock(hMem);
|
|
|
- if (pMem != NULL) {
|
|
|
- *(HGLOBAL *) pMem = hMem;
|
|
|
- (BYTE *) pMem += sizeof(HGLOBAL);
|
|
|
- }
|
|
|
-
|
|
|
-#ifndef NDEBUG
|
|
|
- {
|
|
|
- memset(pMem, 0xaa, ulMemSize_p);
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- return (pMem);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Release a memory block from process specific mempool
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-static void ShbIpcReleasePrivateMem(void *pMem_p)
|
|
|
-{
|
|
|
-
|
|
|
- HGLOBAL hMem;
|
|
|
-
|
|
|
- if (pMem_p == NULL) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- (BYTE *) pMem_p -= sizeof(HGLOBAL);
|
|
|
- hMem = *(HGLOBAL *) pMem_p;
|
|
|
-
|
|
|
- GlobalUnlock(hMem);
|
|
|
- GlobalFree(hMem);
|
|
|
-
|
|
|
- return;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Create uniform object name (needed for inter-process communication)
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-const char *ShbIpcGetUniformObjectName(const char *pszObjectJobName_p,
|
|
|
- const char *pszBufferID_p,
|
|
|
- BOOL fGlobalObject_p)
|
|
|
-{
|
|
|
-
|
|
|
- static char szObjectName[MAX_PATH];
|
|
|
- char szObjectPrefix[MAX_PATH];
|
|
|
-
|
|
|
- if (fGlobalObject_p) {
|
|
|
- strncpy(szObjectPrefix, "Global\\", sizeof(szObjectPrefix));
|
|
|
- } else {
|
|
|
- _snprintf(szObjectPrefix, sizeof(szObjectPrefix), "PID%08lX_",
|
|
|
- (unsigned long)GetCurrentProcessId());
|
|
|
- }
|
|
|
-
|
|
|
- _snprintf(szObjectName, sizeof(szObjectName), "%s%s#%s",
|
|
|
- szObjectPrefix, pszBufferID_p, pszObjectJobName_p);
|
|
|
-
|
|
|
- return (szObjectName);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Thread for new data signaling
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbInstance pShbInstance;
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- DWORD dwWaitResult;
|
|
|
- BOOL fTermRequ;
|
|
|
- int fCallAgain;
|
|
|
-
|
|
|
- TRACE1
|
|
|
- ("\nShbIpcThreadSignalNewData(): SignalThread started (pShbInstance=0x%08lX)\n",
|
|
|
- (DWORD) pvThreadParam_p);
|
|
|
-
|
|
|
- pShbInstance = (tShbMemInst *) pvThreadParam_p;
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
|
|
|
- fTermRequ = FALSE;
|
|
|
-
|
|
|
- do {
|
|
|
- ASSERT((pShbMemInst->m_ahEventNewData[0] !=
|
|
|
- INVALID_HANDLE_VALUE)
|
|
|
- && (pShbMemInst->m_ahEventNewData[0] != NULL));
|
|
|
- ASSERT((pShbMemInst->m_ahEventNewData[1] !=
|
|
|
- INVALID_HANDLE_VALUE)
|
|
|
- && (pShbMemInst->m_ahEventNewData[1] != NULL));
|
|
|
-
|
|
|
- TRACE0("\nShbIpcThreadSignalNewData(): enter wait state");
|
|
|
- dwWaitResult = WaitForMultipleObjects(2, // DWORD nCount
|
|
|
- pShbMemInst->m_ahEventNewData, // const HANDLE* lpHandles
|
|
|
- FALSE, // BOOL bWaitAll
|
|
|
- INFINITE); // DWORD dwMilliseconds
|
|
|
- TRACE0
|
|
|
- ("\nShbIpcThreadSignalNewData(): wait state leaved: ---> ");
|
|
|
- switch (dwWaitResult) {
|
|
|
- case WAIT_OBJECT_0 + 0: // event "new data"
|
|
|
- {
|
|
|
- TRACE0("Event = WAIT_OBJECT_0+0");
|
|
|
- if (pShbMemInst->m_pfnSigHndlrNewData != NULL) {
|
|
|
- TRACE0
|
|
|
- ("\nShbIpcThreadSignalNewData(): calling SignalHandlerNewData");
|
|
|
- do {
|
|
|
- fCallAgain =
|
|
|
- pShbMemInst->
|
|
|
- m_pfnSigHndlrNewData
|
|
|
- (pShbInstance);
|
|
|
- // d.k.: try to run any shared buffer which has higher priority.
|
|
|
- // under Windows this is not really necessary because the Windows scheduler
|
|
|
- // already preempts tasks with lower priority.
|
|
|
- } while (fCallAgain != FALSE);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- case WAIT_OBJECT_0 + 1: // event "terminate"
|
|
|
- {
|
|
|
- TRACE0("Event = WAIT_OBJECT_0+1");
|
|
|
- fTermRequ = TRUE;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- default:
|
|
|
- {
|
|
|
- TRACE0("Unhandled Event");
|
|
|
- ASSERT(0);
|
|
|
- fTermRequ = TRUE;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- while (!fTermRequ);
|
|
|
-
|
|
|
- if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
|
|
|
- INVALID_HANDLE_VALUE) {
|
|
|
- SetEvent(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
|
|
|
- }
|
|
|
-
|
|
|
- TRACE1
|
|
|
- ("\nShbIpcThreadSignalNewData(): SignalThread terminated (pShbInstance=0x%08lX)\n",
|
|
|
- (DWORD) pShbInstance);
|
|
|
-
|
|
|
- ExitThread(0);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-// Thread for new data signaling
|
|
|
-//---------------------------------------------------------------------------
|
|
|
-
|
|
|
-DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p)
|
|
|
-{
|
|
|
-
|
|
|
- tShbInstance *pShbInstance;
|
|
|
- tShbMemInst *pShbMemInst;
|
|
|
- DWORD ulTimeOut;
|
|
|
- DWORD dwWaitResult;
|
|
|
- unsigned int fTimeOut;
|
|
|
-
|
|
|
- TRACE1
|
|
|
- ("\nShbIpcThreadSignalJobReady(): SignalThread started (pShbInstance=0x%08lX)\n",
|
|
|
- (DWORD) pvThreadParam_p);
|
|
|
-
|
|
|
- pShbInstance = (tShbInstance *) pvThreadParam_p;
|
|
|
- pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
|
|
|
- fTimeOut = FALSE;
|
|
|
-
|
|
|
- if (pShbMemInst->m_ulTimeOutJobReady != 0) {
|
|
|
- ulTimeOut = pShbMemInst->m_ulTimeOutJobReady;
|
|
|
- } else {
|
|
|
- ulTimeOut = INFINITE;
|
|
|
- }
|
|
|
-
|
|
|
- ASSERT((pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE)
|
|
|
- && (pShbMemInst->m_hEventJobReady != NULL));
|
|
|
-
|
|
|
- TRACE0("\nShbIpcThreadSignalJobReady(): enter wait state");
|
|
|
- dwWaitResult = WaitForSingleObject(pShbMemInst->m_hEventJobReady, // HANDLE hHandle
|
|
|
- ulTimeOut); // DWORD dwMilliseconds
|
|
|
- TRACE0("\nShbIpcThreadSignalJobReady(): wait state leaved: ---> ");
|
|
|
- switch (dwWaitResult) {
|
|
|
- case WAIT_OBJECT_0 + 0: // event "new data"
|
|
|
- {
|
|
|
- TRACE0("Event = WAIT_OBJECT_0+0");
|
|
|
- fTimeOut = FALSE;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- case WAIT_TIMEOUT:
|
|
|
- {
|
|
|
- TRACE0("\nEvent = WAIT_TIMEOUT");
|
|
|
- fTimeOut = TRUE;
|
|
|
- // ASSERT(0);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- default:
|
|
|
- {
|
|
|
- TRACE0("Unhandled Event");
|
|
|
- fTimeOut = TRUE;
|
|
|
- ASSERT(0);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) {
|
|
|
- TRACE0
|
|
|
- ("\nShbIpcThreadSignalJobReady(): calling SignalHandlerJobReady");
|
|
|
- pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, fTimeOut);
|
|
|
- }
|
|
|
-
|
|
|
- pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
|
|
|
- pShbMemInst->m_pfnSigHndlrJobReady = NULL;
|
|
|
-
|
|
|
- TRACE1
|
|
|
- ("\nShbIpcThreadSignalJobReady(): SignalThread terminated (pShbInstance=0x%08lX)\n",
|
|
|
- (DWORD) pShbInstance);
|
|
|
-
|
|
|
- ExitThread(0);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-// EOF
|