1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: Project independend shared buffer (linear + circular)
8 Description: Implementation of platform specific part for the
10 (Implementation for Win32)
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions
18 1. Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
25 3. Neither the name of SYSTEC electronic GmbH nor the names of its
26 contributors may be used to endorse or promote products derived
27 from this software without prior written permission. For written
28 permission, please contact info@systec-electronic.com.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 POSSIBILITY OF SUCH DAMAGE.
45 If a provision of this License is or becomes illegal, invalid or
46 unenforceable in any jurisdiction, that shall not affect:
47 1. the validity or enforceability in that jurisdiction of any other
48 provision of this License; or
49 2. the validity or enforceability in other jurisdictions of that or
50 any other provision of this License.
52 -------------------------------------------------------------------------
54 2006/06/27 -rs: V 1.00 (initial version)
56 ****************************************************************************/
58 #define WINVER 0x0400 // #defines necessary for usage of
59 #define _WIN32_WINNT 0x0400 // function <SignalObjectAndWait>
64 #include "sharedbuff.h"
71 /***************************************************************************/
74 /* G L O B A L D E F I N I T I O N S */
77 /***************************************************************************/
79 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
81 //---------------------------------------------------------------------------
83 //---------------------------------------------------------------------------
87 //---------------------------------------------------------------------------
88 // Constant definitions
89 //---------------------------------------------------------------------------
91 #define MAX_LEN_BUFFER_ID MAX_PATH
93 #define IDX_EVENT_NEW_DATA 0
94 #define IDX_EVENT_TERM_REQU 1
95 #define IDX_EVENT_TERM_RESP 2
97 #define NAME_MUTEX_BUFF_ACCESS "BuffAccess"
98 #define NAME_EVENT_NEW_DATA "NewData"
99 #define NAME_EVENT_TERM_REQU "TermRequ"
100 #define NAME_EVENT_TERM_RESP "TermResp"
101 #define NAME_EVENT_JOB_READY "JobReady"
103 #define TIMEOUT_ENTER_ATOMIC 1000 // for debgging: INFINITE
104 #define TIMEOUT_TERM_THREAD 2000
106 #define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
107 #define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
111 //---------------------------------------------------------------------------
113 //---------------------------------------------------------------------------
115 // This structure is the common header for the shared memory region used
116 // by all processes attached this shared memory. It includes common
117 // information to administrate/manage the shared buffer from a couple of
118 // separated processes (e.g. the refernce counter). This structure is
119 // located at the start of the shared memory region itself and exists
120 // consequently only one times per shared memory instance.
123 unsigned long m_SbhMagicID; // magic ID ("SBH*")
124 unsigned long m_ulShMemSize;
125 unsigned long m_ulRefCount;
126 char m_szBufferID[MAX_LEN_BUFFER_ID];
129 unsigned long m_ulOwnerProcID;
135 // This structure is the "external entry point" from a separate process
136 // to get access to a shared buffer. This structure includes all platform
137 // resp. target specific information to administrate/manage the shared
138 // buffer from a separate process. Every process attached to the shared
139 // buffer has its own runtime instance of this structure with its individual
140 // runtime data (e.g. the scope of an event handle is limitted to the
141 // owner process only). The structure member <m_pShbMemHeader> points
142 // to the (process specific) start address of the shared memory region
146 unsigned long m_SbiMagicID; // magic ID ("SBI+")
148 HANDLE m_hMutexBuffAccess;
149 HANDLE m_hThreadNewData; // thraed to signal that new data are available
150 HANDLE m_ahEventNewData[3]; // IDX_EVENT_NEW_DATA + IDX_EVENT_TERM_REQU + ID_EVENT_TERM_RESP
151 tSigHndlrNewData m_pfnSigHndlrNewData;
152 HANDLE m_hThreadJobReady; // thread to signal that a job/operation is ready now (e.g. reset buffer)
153 HANDLE m_hEventJobReady;
154 unsigned long m_ulTimeOutJobReady;
155 tSigHndlrJobReady m_pfnSigHndlrJobReady;
156 tShbMemHeader* m_pShbMemHeader;
159 unsigned long m_ulThreadIDNewData;
160 unsigned long m_ulThreadIDJobReady;
167 //---------------------------------------------------------------------------
169 //---------------------------------------------------------------------------
173 //---------------------------------------------------------------------------
175 //---------------------------------------------------------------------------
179 //---------------------------------------------------------------------------
180 // Prototypes of internal functions
181 //---------------------------------------------------------------------------
183 //---------------------------------------------------------------------------
184 // Get pointer to process local information structure
185 //---------------------------------------------------------------------------
187 INLINE_FUNCTION tShbMemInst* ShbIpcGetShbMemInst (
188 tShbInstance pShbInstance_p)
191 tShbMemInst* pShbMemInst;
194 pShbMemInst = (tShbMemInst*)pShbInstance_p;
195 ASSERT (pShbMemInst->m_SbiMagicID == SBI_MAGIC_ID);
197 return (pShbMemInst);
203 //---------------------------------------------------------------------------
204 // Get pointer to shared memory header
205 //---------------------------------------------------------------------------
207 INLINE_FUNCTION tShbMemHeader* ShbIpcGetShbMemHeader (
208 tShbInstance pShbInstance_p)
211 tShbMemInst* pShbMemInst;
212 tShbMemHeader* pShbMemHeader;
215 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
216 pShbMemHeader = pShbMemInst->m_pShbMemHeader;
217 ASSERT(pShbMemHeader->m_SbhMagicID == SBH_MAGIC_ID);
219 return (pShbMemHeader);
224 // not inlined internal functions
225 DWORD WINAPI ShbIpcThreadSignalNewData (LPVOID pvThreadParam_p);
226 DWORD WINAPI ShbIpcThreadSignalJobReady (LPVOID pvThreadParam_p);
227 const char* ShbIpcGetUniformObjectName (const char* pszEventJobName_p, const char* pszBufferID_p, BOOL fGlobalObject_p);
231 #if !defined(SHBIPC_INLINE_ENABLED)
232 // true internal functions (not inlined)
233 static void* ShbIpcAllocPrivateMem (unsigned long ulMemSize_p);
234 static void ShbIpcReleasePrivateMem (void* pMem_p);
237 //=========================================================================//
239 // P U B L I C F U N C T I O N S //
241 //=========================================================================//
243 #if !defined(SHBIPC_INLINE_ENABLED)
244 // not inlined external functions
246 //---------------------------------------------------------------------------
247 // Initialize IPC for Shared Buffer Module
248 //---------------------------------------------------------------------------
250 tShbError ShbIpcInit (void)
259 //---------------------------------------------------------------------------
260 // Deinitialize IPC for Shared Buffer Module
261 //---------------------------------------------------------------------------
263 tShbError ShbIpcExit (void)
272 //---------------------------------------------------------------------------
273 // Allocate Shared Buffer
274 //---------------------------------------------------------------------------
276 tShbError ShbIpcAllocBuffer (
277 unsigned long ulBufferSize_p,
278 const char* pszBufferID_p,
279 tShbInstance* ppShbInstance_p,
280 unsigned int* pfShbNewCreated_p)
285 unsigned long ulShMemSize;
286 tShbMemInst* pShbMemInst;
287 tShbMemHeader* pShbMemHeader;
288 tShbInstance pShbInstance;
289 unsigned int fShMemNewCreated;
290 const char* pszObjectName;
291 HANDLE hMutexBuffAccess;
292 HANDLE hEventNewData;
293 HANDLE hEventJobReady;
297 ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
300 fShMemNewCreated = FALSE;
304 //---------------------------------------------------------------
305 // (1) open an existing or create a new shared memory
306 //---------------------------------------------------------------
307 // try to open an already existing shared memory
308 // (created by an another process)
309 hSharedMem = OpenFileMapping (FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess
310 FALSE, // BOOL bInheritHandle
311 pszBufferID_p); // LPCTSTR lpName
312 if (hSharedMem != NULL)
314 // a shared memory already exists
315 fShMemNewCreated = FALSE;
319 // it seams that this process is the first who wants to use the
320 // shared memory, so it has to create a new shared memory
321 hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE,// HANDLE hFile
322 NULL, // LPSECURITY_ATTRIBUTES lpAttributes
323 PAGE_READWRITE, // DWORD flProtect
324 0, // DWORD dwMaximumSizeHigh
325 ulShMemSize, // DWORD dwMaximumSizeLow
326 pszBufferID_p); // LPCTSTR lpName
328 fShMemNewCreated = TRUE;
331 if (hSharedMem == NULL)
333 ShbError = kShbOutOfMem;
338 //---------------------------------------------------------------
339 // (2) get the pointer to the shared memory
340 //---------------------------------------------------------------
341 pSharedMem = MapViewOfFile (hSharedMem, // HANDLE hFileMappingObject
342 FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess,
343 0, // DWORD dwFileOffsetHigh,
344 0, // DWORD dwFileOffsetLow,
345 ulShMemSize); // SIZE_T dwNumberOfBytesToMap
347 if (pSharedMem == NULL)
349 ShbError = kShbOutOfMem;
354 //---------------------------------------------------------------
355 // (3) setup or update header and management information
356 //---------------------------------------------------------------
357 pShbMemHeader = (tShbMemHeader*)pSharedMem;
359 // allocate a memory block from process specific mempool to save
360 // process local information to administrate/manage the shared buffer
361 pShbMemInst = (tShbMemInst*) ShbIpcAllocPrivateMem (sizeof(tShbMemInst));
362 if (pShbMemInst == NULL)
364 ShbError = kShbOutOfMem;
368 // reset complete header to default values
369 pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID;
370 pShbMemInst->m_hSharedMem = hSharedMem;
371 pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
372 pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
373 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = INVALID_HANDLE_VALUE;
374 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = INVALID_HANDLE_VALUE;
375 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = INVALID_HANDLE_VALUE;
376 pShbMemInst->m_pfnSigHndlrNewData = NULL;
377 pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
378 pShbMemInst->m_hEventJobReady = INVALID_HANDLE_VALUE;
379 pShbMemInst->m_ulTimeOutJobReady = 0;
380 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
381 pShbMemInst->m_pShbMemHeader = pShbMemHeader;
385 pShbMemInst->m_ulThreadIDNewData = 0;
386 pShbMemInst->m_ulThreadIDJobReady = 0;
390 // create mutex for buffer access
391 pszObjectName = ShbIpcGetUniformObjectName (NAME_MUTEX_BUFF_ACCESS, pszBufferID_p, TRUE);
392 hMutexBuffAccess = CreateMutex (NULL, // LPSECURITY_ATTRIBUTES lpMutexAttributes
393 FALSE, // BOOL bInitialOwner
394 pszObjectName); // LPCTSTR lpName
395 pShbMemInst->m_hMutexBuffAccess = hMutexBuffAccess;
396 ASSERT(pShbMemInst->m_hMutexBuffAccess != NULL);
398 // The EventNewData is used for signaling of new data after a write
399 // operation (SetEvent) as well as for waiting for new data on the
400 // reader side (WaitForMultipleObjects). Because it's not known if
401 // this process will be read or write data, the event will be
402 // always created here.
403 pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_NEW_DATA, pszBufferID_p, TRUE);
404 hEventNewData = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
405 FALSE, // BOOL bManualReset
406 FALSE, // BOOL bInitialState
407 pszObjectName); // LPCTSTR lpName
408 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = hEventNewData;
409 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != NULL);
411 // The EventJobReady is used for signaling that a job is done (SetEvent)
412 // as well as for waiting for finishing of a job (WaitForMultipleObjects).
413 // Because it's not known if this process will signal or wait, the event
414 // will be always created here.
415 pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_JOB_READY, pszBufferID_p, TRUE);
416 hEventJobReady = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
417 FALSE, // BOOL bManualReset
418 FALSE, // BOOL bInitialState
419 pszObjectName); // LPCTSTR lpName
420 pShbMemInst->m_hEventJobReady = hEventJobReady;
421 ASSERT(pShbMemInst->m_hEventJobReady != NULL);
423 if ( fShMemNewCreated )
425 // this process was the first who wanted to use the shared memory,
426 // so a new shared memory was created
427 // -> setup new header information inside the shared memory region
429 pShbMemHeader->m_SbhMagicID = SBH_MAGIC_ID;
430 pShbMemHeader->m_ulShMemSize = ulShMemSize;
431 pShbMemHeader->m_ulRefCount = 1;
432 strncpy (pShbMemHeader->m_szBufferID, pszBufferID_p, sizeof(pShbMemHeader->m_szBufferID)-1);
436 pShbMemHeader->m_ulOwnerProcID = GetCurrentProcessId();
442 // any other process has created the shared memory and this
443 // process has only attached to it
444 // -> check and update existing header information inside the
445 // shared memory region itself
446 if (pShbMemHeader->m_ulShMemSize != ulShMemSize)
448 ShbError = kShbOpenMismatch;
454 if ( strncmp(pShbMemHeader->m_szBufferID, pszBufferID_p, sizeof(pShbMemHeader->m_szBufferID)-1) )
456 ShbError = kShbOpenMismatch;
462 pShbMemHeader->m_ulRefCount++;
466 // set abstarct "handle" for returning to application
467 pShbInstance = (tShbInstance*)pShbMemInst;
472 if (ShbError != kShbOk)
474 if (pShbMemInst != NULL)
476 ShbIpcReleasePrivateMem (pShbMemInst);
478 if (pSharedMem != NULL)
480 UnmapViewOfFile (pSharedMem);
482 if (hSharedMem != NULL)
484 CloseHandle (hSharedMem);
488 *pfShbNewCreated_p = fShMemNewCreated;
489 *ppShbInstance_p = pShbInstance;
497 //---------------------------------------------------------------------------
498 // Release Shared Buffer
499 //---------------------------------------------------------------------------
501 tShbError ShbIpcReleaseBuffer (
502 tShbInstance pShbInstance_p)
505 tShbMemInst* pShbMemInst;
506 tShbMemHeader* pShbMemHeader;
507 HANDLE hEventNewData;
508 HANDLE hMutexBuffAccess;
513 if (pShbInstance_p == NULL)
519 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
520 pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p);
523 if ( !--pShbMemHeader->m_ulRefCount )
529 ShbError = kShbMemUsedByOtherProcs;
533 ShbError2 = ShbIpcStopSignalingNewData (pShbInstance_p);
534 hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
535 if (hEventNewData != INVALID_HANDLE_VALUE)
537 CloseHandle (hEventNewData);
538 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = INVALID_HANDLE_VALUE;
541 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
542 if (hMutexBuffAccess != INVALID_HANDLE_VALUE)
544 CloseHandle (hMutexBuffAccess);
545 pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
548 UnmapViewOfFile (pShbMemHeader);
549 if (pShbMemInst->m_hSharedMem != INVALID_HANDLE_VALUE)
551 CloseHandle (pShbMemInst->m_hSharedMem);
552 pShbMemInst->m_hSharedMem = INVALID_HANDLE_VALUE;
555 ShbIpcReleasePrivateMem (pShbMemInst);
558 if (ShbError == kShbOk)
560 ShbError = ShbError2;
567 #endif // !defined(SHBIPC_INLINE_ENABLED)
569 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
571 //---------------------------------------------------------------------------
572 // Enter atomic section for Shared Buffer access
573 //---------------------------------------------------------------------------
575 INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection (
576 tShbInstance pShbInstance_p)
579 tShbMemInst* pShbMemInst;
580 HANDLE hMutexBuffAccess;
585 if (pShbInstance_p == NULL)
587 return (kShbInvalidArg);
591 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
594 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
595 if (hMutexBuffAccess != INVALID_HANDLE_VALUE)
597 dwWaitResult = WaitForSingleObject (hMutexBuffAccess, TIMEOUT_ENTER_ATOMIC);
598 switch (dwWaitResult)
600 case WAIT_OBJECT_0 + 0:
607 TRACE0("\nShbIpcEnterAtomicSection(): WAIT_TIMEOUT");
609 ShbError = kShbBufferInvalid;
615 TRACE0("\nShbIpcEnterAtomicSection(): WAIT_ABANDONED");
617 ShbError = kShbBufferInvalid;
623 TRACE1("\nShbIpcEnterAtomicSection(): WAIT_FAILED -> LastError=%ld", GetLastError());
625 ShbError = kShbBufferInvalid;
631 TRACE1("\nShbIpcEnterAtomicSection(): unknown error -> LastError=%ld", GetLastError());
633 ShbError = kShbBufferInvalid;
640 ShbError = kShbBufferInvalid;
650 //---------------------------------------------------------------------------
651 // Leave atomic section for Shared Buffer access
652 //---------------------------------------------------------------------------
654 INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection (
655 tShbInstance pShbInstance_p)
658 tShbMemInst* pShbMemInst;
659 HANDLE hMutexBuffAccess;
664 if (pShbInstance_p == NULL)
666 return (kShbInvalidArg);
670 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
673 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
674 if (hMutexBuffAccess != INVALID_HANDLE_VALUE)
676 fRes = ReleaseMutex (hMutexBuffAccess);
681 ShbError = kShbBufferInvalid;
691 //---------------------------------------------------------------------------
692 // Start signaling of new data (called from reading process)
693 //---------------------------------------------------------------------------
695 INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData (
696 tShbInstance pShbInstance_p,
697 tSigHndlrNewData pfnSignalHandlerNewData_p,
698 tShbPriority ShbPriority_p)
701 tShbMemInst* pShbMemInst;
702 tShbMemHeader* pShbMemHeader;
703 const char* pszObjectName;
704 HANDLE hEventTermRequ;
705 HANDLE hEventTermResp;
706 HANDLE hThreadNewData;
707 unsigned long ulThreadIDNewData;
711 if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL))
713 return (kShbInvalidArg);
717 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
718 pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p);
721 if ( (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) ||
722 (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != INVALID_HANDLE_VALUE) ||
723 (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != INVALID_HANDLE_VALUE) ||
724 (pShbMemInst->m_pfnSigHndlrNewData != NULL) )
726 ShbError = kShbAlreadySignaling;
731 pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
734 // Because the event <pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]>
735 // is used for signaling of new data after a write operation too (using
736 // SetEvent), it is always created here (see <ShbIpcAllocBuffer>).
738 pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_TERM_REQU, pShbMemHeader->m_szBufferID, FALSE);
739 hEventTermRequ = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
740 FALSE, // BOOL bManualReset
741 FALSE, // BOOL bInitialState
742 pszObjectName); // LPCTSTR lpName
743 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = hEventTermRequ;
744 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != NULL);
746 pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_TERM_RESP, pShbMemHeader->m_szBufferID, FALSE);
747 hEventTermResp = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
748 FALSE, // BOOL bManualReset
749 FALSE, // BOOL bInitialState
750 pszObjectName); // LPCTSTR lpName
751 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = hEventTermResp;
752 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != NULL);
754 hThreadNewData = CreateThread (NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
755 0, // SIZE_T dwStackSize
756 ShbIpcThreadSignalNewData, // LPTHREAD_START_ROUTINE lpStartAddress
757 pShbInstance_p, // LPVOID lpParameter
758 0, // DWORD dwCreationFlags
759 &ulThreadIDNewData); // LPDWORD lpThreadId
761 switch (ShbPriority_p)
763 case kShbPriorityLow:
764 iPriority = THREAD_PRIORITY_BELOW_NORMAL;
767 case kShbPriorityNormal:
768 iPriority = THREAD_PRIORITY_NORMAL;
771 case kshbPriorityHigh:
772 iPriority = THREAD_PRIORITY_ABOVE_NORMAL;
777 ASSERT(pShbMemInst->m_hThreadNewData != NULL);
779 SetThreadPriority(hThreadNewData, iPriority);
781 pShbMemInst->m_hThreadNewData = hThreadNewData;
785 pShbMemInst->m_ulThreadIDNewData = ulThreadIDNewData;
798 //---------------------------------------------------------------------------
799 // Stop signaling of new data (called from reading process)
800 //---------------------------------------------------------------------------
802 INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData (
803 tShbInstance pShbInstance_p)
806 tShbMemInst* pShbMemInst;
807 HANDLE hEventTermRequ;
808 HANDLE hEventTermResp;
812 if (pShbInstance_p == NULL)
814 return (kShbInvalidArg);
817 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
820 // terminate new data signaling thread
821 // (set event <hEventTermRequ> to wakeup the thread and dispose it
822 // to exit, then wait for confirmation using event <hEventTermResp>)
823 hEventTermRequ = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU];
824 hEventTermResp = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP];
825 if ( (hEventTermRequ != INVALID_HANDLE_VALUE) &&
826 (hEventTermResp != INVALID_HANDLE_VALUE) )
828 TRACE0("\nShbIpcStopSignalingNewData(): enter wait state");
829 dwWaitResult = SignalObjectAndWait (hEventTermRequ, // HANDLE hObjectToSignal
830 hEventTermResp, // HANDLE hObjectToWaitOn
831 TIMEOUT_TERM_THREAD, // DWORD dwMilliseconds
832 FALSE); // BOOL bAlertable
833 TRACE0("\nShbIpcStopSignalingNewData(): wait state leaved: ---> ");
834 switch (dwWaitResult)
836 case WAIT_OBJECT_0 + 0: // event "new data signaling thread terminated"
838 TRACE0("Event = WAIT_OBJECT_0+0");
844 TRACE0("Unhandled Event");
852 if (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE)
854 CloseHandle (pShbMemInst->m_hThreadNewData);
855 pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
858 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != INVALID_HANDLE_VALUE)
860 CloseHandle (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]);
861 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = INVALID_HANDLE_VALUE;
864 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != INVALID_HANDLE_VALUE)
866 CloseHandle (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
867 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = INVALID_HANDLE_VALUE;
870 pShbMemInst->m_pfnSigHndlrNewData = NULL;
879 //---------------------------------------------------------------------------
880 // Signal new data (called from writing process)
881 //---------------------------------------------------------------------------
883 INLINE_FUNCTION tShbError ShbIpcSignalNewData (
884 tShbInstance pShbInstance_p)
887 tShbMemInst* pShbMemInst;
888 HANDLE hEventNewData;
892 // TRACE0("\nShbIpcSignalNewData(): enter\n");
894 if (pShbInstance_p == NULL)
896 return (kShbInvalidArg);
900 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
902 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != INVALID_HANDLE_VALUE);
903 hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
904 if (hEventNewData != INVALID_HANDLE_VALUE)
906 fRes = SetEvent (hEventNewData);
907 // TRACE1("\nShbIpcSignalNewData(): EventNewData set (Result=%d)\n", (int)fRes);
911 // TRACE0("\nShbIpcSignalNewData(): leave\n");
918 //---------------------------------------------------------------------------
919 // Start signaling for job ready (called from waiting process)
920 //---------------------------------------------------------------------------
922 INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady (
923 tShbInstance pShbInstance_p,
924 unsigned long ulTimeOut_p,
925 tSigHndlrJobReady pfnSignalHandlerJobReady_p)
928 tShbMemInst* pShbMemInst;
929 tShbMemHeader* pShbMemHeader;
930 HANDLE hThreadJobReady;
931 unsigned long ulThreadIDJobReady;
935 if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL))
937 return (kShbInvalidArg);
941 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
942 pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p);
945 if ( (pShbMemInst->m_hThreadJobReady != INVALID_HANDLE_VALUE) ||
946 (pShbMemInst->m_pfnSigHndlrJobReady != NULL) )
948 ShbError = kShbAlreadySignaling;
953 pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
954 pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
957 // Because the event <pShbMemInst->m_ahEventJobReady> is used for
958 // signaling of a finished job too (using SetEvent), it is always
959 // created here (see <ShbIpcAllocBuffer>).
961 hThreadJobReady = CreateThread (NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
962 0, // SIZE_T dwStackSize
963 ShbIpcThreadSignalJobReady, // LPTHREAD_START_ROUTINE lpStartAddress
964 pShbInstance_p, // LPVOID lpParameter
965 0, // DWORD dwCreationFlags
966 &ulThreadIDJobReady); // LPDWORD lpThreadId
968 pShbMemInst->m_hThreadJobReady = hThreadJobReady;
969 ASSERT(pShbMemInst->m_hThreadJobReady != NULL);
973 pShbMemInst->m_ulThreadIDJobReady = ulThreadIDJobReady;
986 //---------------------------------------------------------------------------
987 // Signal job ready (called from executing process)
988 //---------------------------------------------------------------------------
990 INLINE_FUNCTION tShbError ShbIpcSignalJobReady (
991 tShbInstance pShbInstance_p)
994 tShbMemInst* pShbMemInst;
995 HANDLE hEventJobReady;
999 // TRACE0("\nShbIpcSignalJobReady(): enter\n");
1001 if (pShbInstance_p == NULL)
1003 return (kShbInvalidArg);
1007 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
1009 ASSERT(pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE);
1010 hEventJobReady = pShbMemInst->m_hEventJobReady;
1011 if (hEventJobReady != INVALID_HANDLE_VALUE)
1013 fRes = SetEvent (hEventJobReady);
1014 // TRACE1("\nShbIpcSignalJobReady(): EventJobReady set (Result=%d)\n", (int)fRes);
1018 // TRACE0("\nShbIpcSignalJobReady(): leave\n");
1025 //---------------------------------------------------------------------------
1026 // Get pointer to common used share memory area
1027 //---------------------------------------------------------------------------
1029 INLINE_FUNCTION void* ShbIpcGetShMemPtr (
1030 tShbInstance pShbInstance_p)
1033 tShbMemHeader* pShbMemHeader;
1037 pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p);
1038 if (pShbMemHeader != NULL)
1040 pShbShMemPtr = (BYTE*)pShbMemHeader + sizeof(tShbMemHeader);
1044 pShbShMemPtr = NULL;
1047 return (pShbShMemPtr);
1055 //=========================================================================//
1057 // P R I V A T E F U N C T I O N S //
1059 //=========================================================================//
1061 #if !defined(SHBIPC_INLINE_ENABLED)
1063 //---------------------------------------------------------------------------
1064 // Allocate a memory block from process specific mempool
1065 //---------------------------------------------------------------------------
1067 static void* ShbIpcAllocPrivateMem (
1068 unsigned long ulMemSize_p)
1075 hMem = GlobalAlloc (GMEM_FIXED, ulMemSize_p+sizeof(HGLOBAL));
1076 pMem = GlobalLock (hMem);
1079 *(HGLOBAL*)pMem = hMem;
1080 (BYTE*)pMem += sizeof(HGLOBAL);
1086 memset (pMem, 0xaa, ulMemSize_p);
1097 //---------------------------------------------------------------------------
1098 // Release a memory block from process specific mempool
1099 //---------------------------------------------------------------------------
1101 static void ShbIpcReleasePrivateMem (
1114 (BYTE*)pMem_p -= sizeof(HGLOBAL);
1115 hMem = *(HGLOBAL*)pMem_p;
1117 GlobalUnlock (hMem);
1126 //---------------------------------------------------------------------------
1127 // Create uniform object name (needed for inter-process communication)
1128 //---------------------------------------------------------------------------
1130 const char* ShbIpcGetUniformObjectName (
1131 const char* pszObjectJobName_p,
1132 const char* pszBufferID_p,
1133 BOOL fGlobalObject_p)
1136 static char szObjectName[MAX_PATH];
1137 char szObjectPrefix[MAX_PATH];
1140 if ( fGlobalObject_p )
1142 strncpy (szObjectPrefix, "Global\\", sizeof(szObjectPrefix));
1146 _snprintf (szObjectPrefix, sizeof(szObjectPrefix), "PID%08lX_",
1147 (unsigned long)GetCurrentProcessId());
1151 _snprintf (szObjectName, sizeof(szObjectName), "%s%s#%s",
1152 szObjectPrefix, pszBufferID_p, pszObjectJobName_p);
1155 return (szObjectName);
1161 //---------------------------------------------------------------------------
1162 // Thread for new data signaling
1163 //---------------------------------------------------------------------------
1165 DWORD WINAPI ShbIpcThreadSignalNewData (
1166 LPVOID pvThreadParam_p)
1169 tShbInstance pShbInstance;
1170 tShbMemInst* pShbMemInst;
1176 TRACE1("\nShbIpcThreadSignalNewData(): SignalThread started (pShbInstance=0x%08lX)\n", (DWORD)pvThreadParam_p);
1178 pShbInstance = (tShbMemInst*)pvThreadParam_p;
1179 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance);
1184 ASSERT((pShbMemInst->m_ahEventNewData[0] != INVALID_HANDLE_VALUE) && (pShbMemInst->m_ahEventNewData[0] != NULL));
1185 ASSERT((pShbMemInst->m_ahEventNewData[1] != INVALID_HANDLE_VALUE) && (pShbMemInst->m_ahEventNewData[1] != NULL));
1187 TRACE0("\nShbIpcThreadSignalNewData(): enter wait state");
1188 dwWaitResult = WaitForMultipleObjects (2, // DWORD nCount
1189 pShbMemInst->m_ahEventNewData, // const HANDLE* lpHandles
1190 FALSE, // BOOL bWaitAll
1191 INFINITE); // DWORD dwMilliseconds
1192 TRACE0("\nShbIpcThreadSignalNewData(): wait state leaved: ---> ");
1193 switch (dwWaitResult)
1195 case WAIT_OBJECT_0 + 0: // event "new data"
1197 TRACE0("Event = WAIT_OBJECT_0+0");
1198 if (pShbMemInst->m_pfnSigHndlrNewData != NULL)
1200 TRACE0("\nShbIpcThreadSignalNewData(): calling SignalHandlerNewData");
1203 fCallAgain = pShbMemInst->m_pfnSigHndlrNewData (pShbInstance);
1204 // d.k.: try to run any shared buffer which has higher priority.
1205 // under Windows this is not really necessary because the Windows scheduler
1206 // already preempts tasks with lower priority.
1207 } while (fCallAgain != FALSE);
1212 case WAIT_OBJECT_0 + 1: // event "terminate"
1214 TRACE0("Event = WAIT_OBJECT_0+1");
1221 TRACE0("Unhandled Event");
1228 while ( !fTermRequ );
1231 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != INVALID_HANDLE_VALUE)
1233 SetEvent (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
1236 TRACE1("\nShbIpcThreadSignalNewData(): SignalThread terminated (pShbInstance=0x%08lX)\n", (DWORD)pShbInstance);
1244 //---------------------------------------------------------------------------
1245 // Thread for new data signaling
1246 //---------------------------------------------------------------------------
1248 DWORD WINAPI ShbIpcThreadSignalJobReady (
1249 LPVOID pvThreadParam_p)
1252 tShbInstance* pShbInstance;
1253 tShbMemInst* pShbMemInst;
1256 unsigned int fTimeOut;
1259 TRACE1("\nShbIpcThreadSignalJobReady(): SignalThread started (pShbInstance=0x%08lX)\n", (DWORD)pvThreadParam_p);
1262 pShbInstance = (tShbInstance*)pvThreadParam_p;
1263 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance);
1266 if (pShbMemInst->m_ulTimeOutJobReady != 0)
1268 ulTimeOut = pShbMemInst->m_ulTimeOutJobReady;
1272 ulTimeOut = INFINITE;
1275 ASSERT((pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE) && (pShbMemInst->m_hEventJobReady != NULL));
1277 TRACE0("\nShbIpcThreadSignalJobReady(): enter wait state");
1278 dwWaitResult = WaitForSingleObject (pShbMemInst->m_hEventJobReady, // HANDLE hHandle
1279 ulTimeOut); // DWORD dwMilliseconds
1280 TRACE0("\nShbIpcThreadSignalJobReady(): wait state leaved: ---> ");
1281 switch (dwWaitResult)
1283 case WAIT_OBJECT_0 + 0: // event "new data"
1285 TRACE0("Event = WAIT_OBJECT_0+0");
1292 TRACE0("\nEvent = WAIT_TIMEOUT");
1300 TRACE0("Unhandled Event");
1308 if (pShbMemInst->m_pfnSigHndlrJobReady != NULL)
1310 TRACE0("\nShbIpcThreadSignalJobReady(): calling SignalHandlerJobReady");
1311 pShbMemInst->m_pfnSigHndlrJobReady (pShbInstance, fTimeOut);
1315 pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
1316 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
1319 TRACE1("\nShbIpcThreadSignalJobReady(): SignalThread terminated (pShbInstance=0x%08lX)\n", (DWORD)pShbInstance);