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"
67 /***************************************************************************/
70 /* G L O B A L D E F I N I T I O N S */
73 /***************************************************************************/
75 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
77 //---------------------------------------------------------------------------
79 //---------------------------------------------------------------------------
81 //---------------------------------------------------------------------------
82 // Constant definitions
83 //---------------------------------------------------------------------------
85 #define MAX_LEN_BUFFER_ID MAX_PATH
87 #define IDX_EVENT_NEW_DATA 0
88 #define IDX_EVENT_TERM_REQU 1
89 #define IDX_EVENT_TERM_RESP 2
91 #define NAME_MUTEX_BUFF_ACCESS "BuffAccess"
92 #define NAME_EVENT_NEW_DATA "NewData"
93 #define NAME_EVENT_TERM_REQU "TermRequ"
94 #define NAME_EVENT_TERM_RESP "TermResp"
95 #define NAME_EVENT_JOB_READY "JobReady"
97 #define TIMEOUT_ENTER_ATOMIC 1000 // for debgging: INFINITE
98 #define TIMEOUT_TERM_THREAD 2000
100 #define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
101 #define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
103 //---------------------------------------------------------------------------
105 //---------------------------------------------------------------------------
107 // This structure is the common header for the shared memory region used
108 // by all processes attached this shared memory. It includes common
109 // information to administrate/manage the shared buffer from a couple of
110 // separated processes (e.g. the refernce counter). This structure is
111 // located at the start of the shared memory region itself and exists
112 // consequently only one times per shared memory instance.
114 unsigned long m_SbhMagicID; // magic ID ("SBH*")
115 unsigned long m_ulShMemSize;
116 unsigned long m_ulRefCount;
117 char m_szBufferID[MAX_LEN_BUFFER_ID];
120 unsigned long m_ulOwnerProcID;
125 // This structure is the "external entry point" from a separate process
126 // to get access to a shared buffer. This structure includes all platform
127 // resp. target specific information to administrate/manage the shared
128 // buffer from a separate process. Every process attached to the shared
129 // buffer has its own runtime instance of this structure with its individual
130 // runtime data (e.g. the scope of an event handle is limitted to the
131 // owner process only). The structure member <m_pShbMemHeader> points
132 // to the (process specific) start address of the shared memory region
135 unsigned long m_SbiMagicID; // magic ID ("SBI+")
137 HANDLE m_hMutexBuffAccess;
138 HANDLE m_hThreadNewData; // thraed to signal that new data are available
139 HANDLE m_ahEventNewData[3]; // IDX_EVENT_NEW_DATA + IDX_EVENT_TERM_REQU + ID_EVENT_TERM_RESP
140 tSigHndlrNewData m_pfnSigHndlrNewData;
141 HANDLE m_hThreadJobReady; // thread to signal that a job/operation is ready now (e.g. reset buffer)
142 HANDLE m_hEventJobReady;
143 unsigned long m_ulTimeOutJobReady;
144 tSigHndlrJobReady m_pfnSigHndlrJobReady;
145 tShbMemHeader *m_pShbMemHeader;
148 unsigned long m_ulThreadIDNewData;
149 unsigned long m_ulThreadIDJobReady;
154 //---------------------------------------------------------------------------
156 //---------------------------------------------------------------------------
158 //---------------------------------------------------------------------------
160 //---------------------------------------------------------------------------
162 //---------------------------------------------------------------------------
163 // Prototypes of internal functions
164 //---------------------------------------------------------------------------
166 //---------------------------------------------------------------------------
167 // Get pointer to process local information structure
168 //---------------------------------------------------------------------------
170 INLINE_FUNCTION tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)
173 tShbMemInst *pShbMemInst;
175 pShbMemInst = (tShbMemInst *) pShbInstance_p;
176 ASSERT(pShbMemInst->m_SbiMagicID == SBI_MAGIC_ID);
178 return (pShbMemInst);
182 //---------------------------------------------------------------------------
183 // Get pointer to shared memory header
184 //---------------------------------------------------------------------------
186 INLINE_FUNCTION tShbMemHeader *ShbIpcGetShbMemHeader(tShbInstance
190 tShbMemInst *pShbMemInst;
191 tShbMemHeader *pShbMemHeader;
193 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
194 pShbMemHeader = pShbMemInst->m_pShbMemHeader;
195 ASSERT(pShbMemHeader->m_SbhMagicID == SBH_MAGIC_ID);
197 return (pShbMemHeader);
201 // not inlined internal functions
202 DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p);
203 DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p);
204 const char *ShbIpcGetUniformObjectName(const char *pszEventJobName_p,
205 const char *pszBufferID_p,
206 BOOL fGlobalObject_p);
210 #if !defined(SHBIPC_INLINE_ENABLED)
211 // true internal functions (not inlined)
212 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p);
213 static void ShbIpcReleasePrivateMem(void *pMem_p);
216 //=========================================================================//
218 // P U B L I C F U N C T I O N S //
220 //=========================================================================//
222 #if !defined(SHBIPC_INLINE_ENABLED)
223 // not inlined external functions
225 //---------------------------------------------------------------------------
226 // Initialize IPC for Shared Buffer Module
227 //---------------------------------------------------------------------------
229 tShbError ShbIpcInit(void)
236 //---------------------------------------------------------------------------
237 // Deinitialize IPC for Shared Buffer Module
238 //---------------------------------------------------------------------------
240 tShbError ShbIpcExit(void)
247 //---------------------------------------------------------------------------
248 // Allocate Shared Buffer
249 //---------------------------------------------------------------------------
251 tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
252 const char *pszBufferID_p,
253 tShbInstance * ppShbInstance_p,
254 unsigned int *pfShbNewCreated_p)
259 unsigned long ulShMemSize;
260 tShbMemInst *pShbMemInst;
261 tShbMemHeader *pShbMemHeader;
262 tShbInstance pShbInstance;
263 unsigned int fShMemNewCreated;
264 const char *pszObjectName;
265 HANDLE hMutexBuffAccess;
266 HANDLE hEventNewData;
267 HANDLE hEventJobReady;
270 ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
273 fShMemNewCreated = FALSE;
276 //---------------------------------------------------------------
277 // (1) open an existing or create a new shared memory
278 //---------------------------------------------------------------
279 // try to open an already existing shared memory
280 // (created by an another process)
281 hSharedMem = OpenFileMapping(FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess
282 FALSE, // BOOL bInheritHandle
283 pszBufferID_p); // LPCTSTR lpName
284 if (hSharedMem != NULL) {
285 // a shared memory already exists
286 fShMemNewCreated = FALSE;
288 // it seams that this process is the first who wants to use the
289 // shared memory, so it has to create a new shared memory
290 hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE, // HANDLE hFile
291 NULL, // LPSECURITY_ATTRIBUTES lpAttributes
292 PAGE_READWRITE, // DWORD flProtect
293 0, // DWORD dwMaximumSizeHigh
294 ulShMemSize, // DWORD dwMaximumSizeLow
295 pszBufferID_p); // LPCTSTR lpName
297 fShMemNewCreated = TRUE;
300 if (hSharedMem == NULL) {
301 ShbError = kShbOutOfMem;
305 //---------------------------------------------------------------
306 // (2) get the pointer to the shared memory
307 //---------------------------------------------------------------
308 pSharedMem = MapViewOfFile(hSharedMem, // HANDLE hFileMappingObject
309 FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess,
310 0, // DWORD dwFileOffsetHigh,
311 0, // DWORD dwFileOffsetLow,
312 ulShMemSize); // SIZE_T dwNumberOfBytesToMap
314 if (pSharedMem == NULL) {
315 ShbError = kShbOutOfMem;
319 //---------------------------------------------------------------
320 // (3) setup or update header and management information
321 //---------------------------------------------------------------
322 pShbMemHeader = (tShbMemHeader *) pSharedMem;
324 // allocate a memory block from process specific mempool to save
325 // process local information to administrate/manage the shared buffer
327 (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst));
328 if (pShbMemInst == NULL) {
329 ShbError = kShbOutOfMem;
332 // reset complete header to default values
333 pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID;
334 pShbMemInst->m_hSharedMem = hSharedMem;
335 pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
336 pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
337 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] =
338 INVALID_HANDLE_VALUE;
339 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] =
340 INVALID_HANDLE_VALUE;
341 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] =
342 INVALID_HANDLE_VALUE;
343 pShbMemInst->m_pfnSigHndlrNewData = NULL;
344 pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
345 pShbMemInst->m_hEventJobReady = INVALID_HANDLE_VALUE;
346 pShbMemInst->m_ulTimeOutJobReady = 0;
347 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
348 pShbMemInst->m_pShbMemHeader = pShbMemHeader;
352 pShbMemInst->m_ulThreadIDNewData = 0;
353 pShbMemInst->m_ulThreadIDJobReady = 0;
357 // create mutex for buffer access
359 ShbIpcGetUniformObjectName(NAME_MUTEX_BUFF_ACCESS, pszBufferID_p,
361 hMutexBuffAccess = CreateMutex(NULL, // LPSECURITY_ATTRIBUTES lpMutexAttributes
362 FALSE, // BOOL bInitialOwner
363 pszObjectName); // LPCTSTR lpName
364 pShbMemInst->m_hMutexBuffAccess = hMutexBuffAccess;
365 ASSERT(pShbMemInst->m_hMutexBuffAccess != NULL);
367 // The EventNewData is used for signaling of new data after a write
368 // operation (SetEvent) as well as for waiting for new data on the
369 // reader side (WaitForMultipleObjects). Because it's not known if
370 // this process will be read or write data, the event will be
371 // always created here.
373 ShbIpcGetUniformObjectName(NAME_EVENT_NEW_DATA, pszBufferID_p,
375 hEventNewData = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
376 FALSE, // BOOL bManualReset
377 FALSE, // BOOL bInitialState
378 pszObjectName); // LPCTSTR lpName
379 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = hEventNewData;
380 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != NULL);
382 // The EventJobReady is used for signaling that a job is done (SetEvent)
383 // as well as for waiting for finishing of a job (WaitForMultipleObjects).
384 // Because it's not known if this process will signal or wait, the event
385 // will be always created here.
387 ShbIpcGetUniformObjectName(NAME_EVENT_JOB_READY, pszBufferID_p,
389 hEventJobReady = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
390 FALSE, // BOOL bManualReset
391 FALSE, // BOOL bInitialState
392 pszObjectName); // LPCTSTR lpName
393 pShbMemInst->m_hEventJobReady = hEventJobReady;
394 ASSERT(pShbMemInst->m_hEventJobReady != NULL);
396 if (fShMemNewCreated) {
397 // this process was the first who wanted to use the shared memory,
398 // so a new shared memory was created
399 // -> setup new header information inside the shared memory region
401 pShbMemHeader->m_SbhMagicID = SBH_MAGIC_ID;
402 pShbMemHeader->m_ulShMemSize = ulShMemSize;
403 pShbMemHeader->m_ulRefCount = 1;
404 strncpy(pShbMemHeader->m_szBufferID, pszBufferID_p,
405 sizeof(pShbMemHeader->m_szBufferID) - 1);
409 pShbMemHeader->m_ulOwnerProcID = GetCurrentProcessId();
413 // any other process has created the shared memory and this
414 // process has only attached to it
415 // -> check and update existing header information inside the
416 // shared memory region itself
417 if (pShbMemHeader->m_ulShMemSize != ulShMemSize) {
418 ShbError = kShbOpenMismatch;
424 (pShbMemHeader->m_szBufferID, pszBufferID_p,
425 sizeof(pShbMemHeader->m_szBufferID) - 1)) {
426 ShbError = kShbOpenMismatch;
432 pShbMemHeader->m_ulRefCount++;
435 // set abstarct "handle" for returning to application
436 pShbInstance = (tShbInstance *) pShbMemInst;
440 if (ShbError != kShbOk) {
441 if (pShbMemInst != NULL) {
442 ShbIpcReleasePrivateMem(pShbMemInst);
444 if (pSharedMem != NULL) {
445 UnmapViewOfFile(pSharedMem);
447 if (hSharedMem != NULL) {
448 CloseHandle(hSharedMem);
452 *pfShbNewCreated_p = fShMemNewCreated;
453 *ppShbInstance_p = pShbInstance;
459 //---------------------------------------------------------------------------
460 // Release Shared Buffer
461 //---------------------------------------------------------------------------
463 tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)
466 tShbMemInst *pShbMemInst;
467 tShbMemHeader *pShbMemHeader;
468 HANDLE hEventNewData;
469 HANDLE hMutexBuffAccess;
473 if (pShbInstance_p == NULL) {
477 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
478 pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
480 if (!--pShbMemHeader->m_ulRefCount) {
483 ShbError = kShbMemUsedByOtherProcs;
486 ShbError2 = ShbIpcStopSignalingNewData(pShbInstance_p);
487 hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
488 if (hEventNewData != INVALID_HANDLE_VALUE) {
489 CloseHandle(hEventNewData);
490 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] =
491 INVALID_HANDLE_VALUE;
494 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
495 if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
496 CloseHandle(hMutexBuffAccess);
497 pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
500 UnmapViewOfFile(pShbMemHeader);
501 if (pShbMemInst->m_hSharedMem != INVALID_HANDLE_VALUE) {
502 CloseHandle(pShbMemInst->m_hSharedMem);
503 pShbMemInst->m_hSharedMem = INVALID_HANDLE_VALUE;
506 ShbIpcReleasePrivateMem(pShbMemInst);
508 if (ShbError == kShbOk) {
509 ShbError = ShbError2;
516 #endif // !defined(SHBIPC_INLINE_ENABLED)
518 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
520 //---------------------------------------------------------------------------
521 // Enter atomic section for Shared Buffer access
522 //---------------------------------------------------------------------------
524 INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)
527 tShbMemInst *pShbMemInst;
528 HANDLE hMutexBuffAccess;
532 if (pShbInstance_p == NULL) {
533 return (kShbInvalidArg);
536 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
539 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
540 if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
542 WaitForSingleObject(hMutexBuffAccess, TIMEOUT_ENTER_ATOMIC);
543 switch (dwWaitResult) {
544 case WAIT_OBJECT_0 + 0:
552 ("\nShbIpcEnterAtomicSection(): WAIT_TIMEOUT");
554 ShbError = kShbBufferInvalid;
561 ("\nShbIpcEnterAtomicSection(): WAIT_ABANDONED");
563 ShbError = kShbBufferInvalid;
570 ("\nShbIpcEnterAtomicSection(): WAIT_FAILED -> LastError=%ld",
573 ShbError = kShbBufferInvalid;
580 ("\nShbIpcEnterAtomicSection(): unknown error -> LastError=%ld",
583 ShbError = kShbBufferInvalid;
588 ShbError = kShbBufferInvalid;
595 //---------------------------------------------------------------------------
596 // Leave atomic section for Shared Buffer access
597 //---------------------------------------------------------------------------
599 INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)
602 tShbMemInst *pShbMemInst;
603 HANDLE hMutexBuffAccess;
607 if (pShbInstance_p == NULL) {
608 return (kShbInvalidArg);
611 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
614 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
615 if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
616 fRes = ReleaseMutex(hMutexBuffAccess);
619 ShbError = kShbBufferInvalid;
626 //---------------------------------------------------------------------------
627 // Start signaling of new data (called from reading process)
628 //---------------------------------------------------------------------------
630 INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance
633 pfnSignalHandlerNewData_p,
638 tShbMemInst *pShbMemInst;
639 tShbMemHeader *pShbMemHeader;
640 const char *pszObjectName;
641 HANDLE hEventTermRequ;
642 HANDLE hEventTermResp;
643 HANDLE hThreadNewData;
644 unsigned long ulThreadIDNewData;
648 if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) {
649 return (kShbInvalidArg);
652 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
653 pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
656 if ((pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) ||
657 (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] !=
658 INVALID_HANDLE_VALUE)
659 || (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
660 INVALID_HANDLE_VALUE)
661 || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) {
662 ShbError = kShbAlreadySignaling;
666 pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
668 // Because the event <pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]>
669 // is used for signaling of new data after a write operation too (using
670 // SetEvent), it is always created here (see <ShbIpcAllocBuffer>).
673 ShbIpcGetUniformObjectName(NAME_EVENT_TERM_REQU,
674 pShbMemHeader->m_szBufferID, FALSE);
675 hEventTermRequ = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
676 FALSE, // BOOL bManualReset
677 FALSE, // BOOL bInitialState
678 pszObjectName); // LPCTSTR lpName
679 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = hEventTermRequ;
680 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != NULL);
683 ShbIpcGetUniformObjectName(NAME_EVENT_TERM_RESP,
684 pShbMemHeader->m_szBufferID, FALSE);
685 hEventTermResp = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
686 FALSE, // BOOL bManualReset
687 FALSE, // BOOL bInitialState
688 pszObjectName); // LPCTSTR lpName
689 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = hEventTermResp;
690 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != NULL);
692 hThreadNewData = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
693 0, // SIZE_T dwStackSize
694 ShbIpcThreadSignalNewData, // LPTHREAD_START_ROUTINE lpStartAddress
695 pShbInstance_p, // LPVOID lpParameter
696 0, // DWORD dwCreationFlags
697 &ulThreadIDNewData); // LPDWORD lpThreadId
699 switch (ShbPriority_p) {
700 case kShbPriorityLow:
701 iPriority = THREAD_PRIORITY_BELOW_NORMAL;
704 case kShbPriorityNormal:
705 iPriority = THREAD_PRIORITY_NORMAL;
708 case kshbPriorityHigh:
709 iPriority = THREAD_PRIORITY_ABOVE_NORMAL;
714 ASSERT(pShbMemInst->m_hThreadNewData != NULL);
716 SetThreadPriority(hThreadNewData, iPriority);
718 pShbMemInst->m_hThreadNewData = hThreadNewData;
722 pShbMemInst->m_ulThreadIDNewData = ulThreadIDNewData;
732 //---------------------------------------------------------------------------
733 // Stop signaling of new data (called from reading process)
734 //---------------------------------------------------------------------------
736 INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance
740 tShbMemInst *pShbMemInst;
741 HANDLE hEventTermRequ;
742 HANDLE hEventTermResp;
745 if (pShbInstance_p == NULL) {
746 return (kShbInvalidArg);
749 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
751 // terminate new data signaling thread
752 // (set event <hEventTermRequ> to wakeup the thread and dispose it
753 // to exit, then wait for confirmation using event <hEventTermResp>)
754 hEventTermRequ = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU];
755 hEventTermResp = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP];
756 if ((hEventTermRequ != INVALID_HANDLE_VALUE) &&
757 (hEventTermResp != INVALID_HANDLE_VALUE)) {
758 TRACE0("\nShbIpcStopSignalingNewData(): enter wait state");
759 dwWaitResult = SignalObjectAndWait(hEventTermRequ, // HANDLE hObjectToSignal
760 hEventTermResp, // HANDLE hObjectToWaitOn
761 TIMEOUT_TERM_THREAD, // DWORD dwMilliseconds
762 FALSE); // BOOL bAlertable
764 ("\nShbIpcStopSignalingNewData(): wait state leaved: ---> ");
765 switch (dwWaitResult) {
766 case WAIT_OBJECT_0 + 0: // event "new data signaling thread terminated"
768 TRACE0("Event = WAIT_OBJECT_0+0");
774 TRACE0("Unhandled Event");
781 if (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) {
782 CloseHandle(pShbMemInst->m_hThreadNewData);
783 pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
786 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] !=
787 INVALID_HANDLE_VALUE) {
788 CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]);
789 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] =
790 INVALID_HANDLE_VALUE;
793 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
794 INVALID_HANDLE_VALUE) {
795 CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
796 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] =
797 INVALID_HANDLE_VALUE;
800 pShbMemInst->m_pfnSigHndlrNewData = NULL;
806 //---------------------------------------------------------------------------
807 // Signal new data (called from writing process)
808 //---------------------------------------------------------------------------
810 INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p)
813 tShbMemInst *pShbMemInst;
814 HANDLE hEventNewData;
817 // TRACE0("\nShbIpcSignalNewData(): enter\n");
819 if (pShbInstance_p == NULL) {
820 return (kShbInvalidArg);
823 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
825 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] !=
826 INVALID_HANDLE_VALUE);
827 hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
828 if (hEventNewData != INVALID_HANDLE_VALUE) {
829 fRes = SetEvent(hEventNewData);
830 // TRACE1("\nShbIpcSignalNewData(): EventNewData set (Result=%d)\n", (int)fRes);
833 // TRACE0("\nShbIpcSignalNewData(): leave\n");
838 //---------------------------------------------------------------------------
839 // Start signaling for job ready (called from waiting process)
840 //---------------------------------------------------------------------------
842 INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance
847 pfnSignalHandlerJobReady_p)
850 tShbMemInst *pShbMemInst;
851 tShbMemHeader *pShbMemHeader;
852 HANDLE hThreadJobReady;
853 unsigned long ulThreadIDJobReady;
856 if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) {
857 return (kShbInvalidArg);
860 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
861 pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
864 if ((pShbMemInst->m_hThreadJobReady != INVALID_HANDLE_VALUE) ||
865 (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) {
866 ShbError = kShbAlreadySignaling;
870 pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
871 pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
873 // Because the event <pShbMemInst->m_ahEventJobReady> is used for
874 // signaling of a finished job too (using SetEvent), it is always
875 // created here (see <ShbIpcAllocBuffer>).
877 hThreadJobReady = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
878 0, // SIZE_T dwStackSize
879 ShbIpcThreadSignalJobReady, // LPTHREAD_START_ROUTINE lpStartAddress
880 pShbInstance_p, // LPVOID lpParameter
881 0, // DWORD dwCreationFlags
882 &ulThreadIDJobReady); // LPDWORD lpThreadId
884 pShbMemInst->m_hThreadJobReady = hThreadJobReady;
885 ASSERT(pShbMemInst->m_hThreadJobReady != NULL);
889 pShbMemInst->m_ulThreadIDJobReady = ulThreadIDJobReady;
899 //---------------------------------------------------------------------------
900 // Signal job ready (called from executing process)
901 //---------------------------------------------------------------------------
903 INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p)
906 tShbMemInst *pShbMemInst;
907 HANDLE hEventJobReady;
910 // TRACE0("\nShbIpcSignalJobReady(): enter\n");
912 if (pShbInstance_p == NULL) {
913 return (kShbInvalidArg);
916 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
918 ASSERT(pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE);
919 hEventJobReady = pShbMemInst->m_hEventJobReady;
920 if (hEventJobReady != INVALID_HANDLE_VALUE) {
921 fRes = SetEvent(hEventJobReady);
922 // TRACE1("\nShbIpcSignalJobReady(): EventJobReady set (Result=%d)\n", (int)fRes);
925 // TRACE0("\nShbIpcSignalJobReady(): leave\n");
930 //---------------------------------------------------------------------------
931 // Get pointer to common used share memory area
932 //---------------------------------------------------------------------------
934 INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)
937 tShbMemHeader *pShbMemHeader;
940 pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
941 if (pShbMemHeader != NULL) {
942 pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader);
947 return (pShbShMemPtr);
953 //=========================================================================//
955 // P R I V A T E F U N C T I O N S //
957 //=========================================================================//
959 #if !defined(SHBIPC_INLINE_ENABLED)
961 //---------------------------------------------------------------------------
962 // Allocate a memory block from process specific mempool
963 //---------------------------------------------------------------------------
965 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)
971 hMem = GlobalAlloc(GMEM_FIXED, ulMemSize_p + sizeof(HGLOBAL));
972 pMem = GlobalLock(hMem);
974 *(HGLOBAL *) pMem = hMem;
975 (BYTE *) pMem += sizeof(HGLOBAL);
980 memset(pMem, 0xaa, ulMemSize_p);
988 //---------------------------------------------------------------------------
989 // Release a memory block from process specific mempool
990 //---------------------------------------------------------------------------
992 static void ShbIpcReleasePrivateMem(void *pMem_p)
997 if (pMem_p == NULL) {
1001 (BYTE *) pMem_p -= sizeof(HGLOBAL);
1002 hMem = *(HGLOBAL *) pMem_p;
1011 //---------------------------------------------------------------------------
1012 // Create uniform object name (needed for inter-process communication)
1013 //---------------------------------------------------------------------------
1015 const char *ShbIpcGetUniformObjectName(const char *pszObjectJobName_p,
1016 const char *pszBufferID_p,
1017 BOOL fGlobalObject_p)
1020 static char szObjectName[MAX_PATH];
1021 char szObjectPrefix[MAX_PATH];
1023 if (fGlobalObject_p) {
1024 strncpy(szObjectPrefix, "Global\\", sizeof(szObjectPrefix));
1026 _snprintf(szObjectPrefix, sizeof(szObjectPrefix), "PID%08lX_",
1027 (unsigned long)GetCurrentProcessId());
1030 _snprintf(szObjectName, sizeof(szObjectName), "%s%s#%s",
1031 szObjectPrefix, pszBufferID_p, pszObjectJobName_p);
1033 return (szObjectName);
1037 //---------------------------------------------------------------------------
1038 // Thread for new data signaling
1039 //---------------------------------------------------------------------------
1041 DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p)
1044 tShbInstance pShbInstance;
1045 tShbMemInst *pShbMemInst;
1051 ("\nShbIpcThreadSignalNewData(): SignalThread started (pShbInstance=0x%08lX)\n",
1052 (DWORD) pvThreadParam_p);
1054 pShbInstance = (tShbMemInst *) pvThreadParam_p;
1055 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
1059 ASSERT((pShbMemInst->m_ahEventNewData[0] !=
1060 INVALID_HANDLE_VALUE)
1061 && (pShbMemInst->m_ahEventNewData[0] != NULL));
1062 ASSERT((pShbMemInst->m_ahEventNewData[1] !=
1063 INVALID_HANDLE_VALUE)
1064 && (pShbMemInst->m_ahEventNewData[1] != NULL));
1066 TRACE0("\nShbIpcThreadSignalNewData(): enter wait state");
1067 dwWaitResult = WaitForMultipleObjects(2, // DWORD nCount
1068 pShbMemInst->m_ahEventNewData, // const HANDLE* lpHandles
1069 FALSE, // BOOL bWaitAll
1070 INFINITE); // DWORD dwMilliseconds
1072 ("\nShbIpcThreadSignalNewData(): wait state leaved: ---> ");
1073 switch (dwWaitResult) {
1074 case WAIT_OBJECT_0 + 0: // event "new data"
1076 TRACE0("Event = WAIT_OBJECT_0+0");
1077 if (pShbMemInst->m_pfnSigHndlrNewData != NULL) {
1079 ("\nShbIpcThreadSignalNewData(): calling SignalHandlerNewData");
1083 m_pfnSigHndlrNewData
1085 // d.k.: try to run any shared buffer which has higher priority.
1086 // under Windows this is not really necessary because the Windows scheduler
1087 // already preempts tasks with lower priority.
1088 } while (fCallAgain != FALSE);
1093 case WAIT_OBJECT_0 + 1: // event "terminate"
1095 TRACE0("Event = WAIT_OBJECT_0+1");
1102 TRACE0("Unhandled Event");
1111 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
1112 INVALID_HANDLE_VALUE) {
1113 SetEvent(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
1117 ("\nShbIpcThreadSignalNewData(): SignalThread terminated (pShbInstance=0x%08lX)\n",
1118 (DWORD) pShbInstance);
1124 //---------------------------------------------------------------------------
1125 // Thread for new data signaling
1126 //---------------------------------------------------------------------------
1128 DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p)
1131 tShbInstance *pShbInstance;
1132 tShbMemInst *pShbMemInst;
1135 unsigned int fTimeOut;
1138 ("\nShbIpcThreadSignalJobReady(): SignalThread started (pShbInstance=0x%08lX)\n",
1139 (DWORD) pvThreadParam_p);
1141 pShbInstance = (tShbInstance *) pvThreadParam_p;
1142 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
1145 if (pShbMemInst->m_ulTimeOutJobReady != 0) {
1146 ulTimeOut = pShbMemInst->m_ulTimeOutJobReady;
1148 ulTimeOut = INFINITE;
1151 ASSERT((pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE)
1152 && (pShbMemInst->m_hEventJobReady != NULL));
1154 TRACE0("\nShbIpcThreadSignalJobReady(): enter wait state");
1155 dwWaitResult = WaitForSingleObject(pShbMemInst->m_hEventJobReady, // HANDLE hHandle
1156 ulTimeOut); // DWORD dwMilliseconds
1157 TRACE0("\nShbIpcThreadSignalJobReady(): wait state leaved: ---> ");
1158 switch (dwWaitResult) {
1159 case WAIT_OBJECT_0 + 0: // event "new data"
1161 TRACE0("Event = WAIT_OBJECT_0+0");
1168 TRACE0("\nEvent = WAIT_TIMEOUT");
1176 TRACE0("Unhandled Event");
1183 if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) {
1185 ("\nShbIpcThreadSignalJobReady(): calling SignalHandlerJobReady");
1186 pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, fTimeOut);
1189 pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
1190 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
1193 ("\nShbIpcThreadSignalJobReady(): SignalThread terminated (pShbInstance=0x%08lX)\n",
1194 (DWORD) pShbInstance);