본문 바로가기
  • ^ __________ ^ ㄷ ㅜ ㄹ ㅜ ㅁ ㅜ ㄹ
TechTree(IT|Dev|SW)/C | C++ | VC++

[소스공개] IPC간 즉시 시그널

by DURUMUL 2025. 10. 11.

공유메모리에 쓰고 즉시,이벤트 시그널전송 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
*  Module:     SHMSiseAPI.H
*  Delta:      1.0.0 (05/18/2019 11:48:34)
*  Filename:   SHMSiseAPI.h
*  $Author: krkim $
*  $Id: SHMSiseAPI.h 7995 2025-06-29 11:27:20Z krkim $
*  $Revision: 7995 $
*  Contacts: https://durumul.com durumul@gmail.com 
*  주식시세공유메모리 관리자  
*/
 
#ifndef SHMTOOL__H
#define SHMTOOL__H
#define BUILDOPT_ATS
#include <list>
#include <string>
#include <map>
#include <unordered_map>
#include <STSise.h>
using namespace std;
#pragma pack( push, 1 )
#pragma once
using namespace NSHomi_Common;
 
//시세변동 시그널이벤트 20251007
//#define SHMSIGNAL_EVENTNAME L"SHMSiseUpdateEvent"
const LPCSTR szSHMSIGNAL_EVENTNAME = TEXT("SHMSiseSigEvent");
 
namespace ns_SHMSiseAPI
{
    
#define MYUNSORTEDMAP unordered_map  //hash_map이 C++11 에서 없어지고 unordered_map로 표준화됨
#define MYSORTEDMAP   map
 
#define SHMSISE_WINDOWCLASSNAME     "SHMSise"
#define SHMSISE_WINDOWEXENAME       "SHMSise.exe"
#define SHMSISE_MAPNAME             "SHMSise-Map"
#define SHMSISE_MUTEXNAME           "SHMSise-Mutex"
#define SHMSISE_WINDOW                "SHMSise" //window class and title name
#define WM_SHMSISE WM_USER + 3003//message 
 
#define SHMSISE_CLEAR            0//subcommand in wParam
#define SHMSISE_GETDATA        1//subcommand in wParam
#define SHMSISE_SETDATA        2//subcommand in wParam
#define SHMSISE_SETCMD        3
#define SHMSISE_SYSTEMID    999
 
#define SHMSISE_CMD_ATTACH      "ATTACH"
#define SHMSISE_CMD_DETACH      "DETACH"
 
 
//공유매핑파일 종목인덱스영역
typedef struct    _SHMSISECODE
{
    char shtcode[8];//etf,etn은 영문자 섞여있어 int는 배제
}SHMSISECODE, FAR* LPSHMSISECODE;
 
//typedef vector<pair<string, LONG>>  MYVECTOR_LONG;//입력순으로 저장(음수양수포함한 단순flag값소트위해)
typedef vector<SHMSISECODE>  MYVECTOR_SHTCODE;//입력순으로 저장(음수양수포함한 단순flag값소트위해)
 
//공유매핑파일 데이터영역
typedef struct    _SHMSISEITEM
{
    char mode[1+1];
    char who[12];
    STStockInfo si;     //종목마스터 정보
    STTickSise  ts;     //현재시세(틱이 아니라 당일일시세임) 20250403
    STHogaSise  hs;     //현재수신또는보정된호가  20250403
    LPARAM param;
    int setcount;
}SHMSISEITEM, FAR* LPSHMSISEITEM;
 
//외부호출자(Caller) 정보
typedef struct    _SHMSISEAPP
{
    int id;
    string keyname;
    string logdir;
    HWND hWnd;
 
}SHMSISEAPP, FAR* LPSHMSISEAPP;
 
typedef vector<pair<string, SHMSISEITEM>> MYVECTOR_SHMSISEITEM;
typedef MYUNSORTEDMAP<string, SHMSISEAPP> SHMSISE_APPMAP;
typedef int (CALLBACK* FP_REALTIMEPROC)(string, WPARAM, LPARAM);
 
//공유매핑파일(MMF) 해더정보
typedef struct _SHMSISEHEADER
{
    int mapsize;
    int maxitems;  //최대제한갯수
    int itemcount;     //실제저장된 갯수
    int offset2write;
    int offset2read;
    int rollback;
    int writecount;
    int readcount;
    int lastwriteindex; //마지막 기록인덱스
    int lastupdateindex;
    int lastreadindex;  //마지막 읽은인덱스
    bool bFirstCreated;
    int lasttime;   //마지막 기록시간 hhmmss
    _SHMSISEHEADER() {
        mapsize = 0;
        maxitems = 0,
        itemcount = 0;
        offset2write = 0;
        offset2read = 0;
        rollback = 0;//쓰기위치를 0포인트로 이동
        writecount = 0;
        readcount = 0;
        lastwriteindex = 0;
        lastupdateindex = 0;
        lastreadindex = 0;
        lasttime = 0;
        bFirstCreated = false;
    };
}SHMSISEHEADER, FAR* LPSHMSISEHEADER;
 
//환경설정
typedef struct _SHMSISECONF
{
    HANDLE hFileMap;
    LPVOID mapping;  //pointer to shared memory
    SHMSISEHEADER* pmapheader;
    HANDLE hMutex;   //Lock Unlock
    int nMaxItems;   //공유메모리 데이타수 shared memory max count
    int nTotalMapSize;
    bool bFirstCreated;
    LPVOID m_pUIWnd;
    HANDLE m_hSigEvent; //시세업데이트 시그널이벤트
    FP_REALTIMEPROC m_fnRealtime;//셋팅과 동시에 gui 화면즉시갱신 20251004
    //MYVECTOR_SHTCODE vecindex;//sort가정하에
    MYVECTOR_SHMSISEITEM vecitems;
    LPVOID pdata;   //실제데이타 시작위치(realdata entry point) 20250928
    _SHMSISECONF() {
        hFileMap = NULL;
        mapping = NULL;
        pmapheader = NULL;
        hMutex = NULL;
        nTotalMapSize = 0;
        bFirstCreated = false;
        nMaxItems = 2000;
        pdata = NULL;
        m_pUIWnd = NULL;
        m_fnRealtime = NULL;
        m_hSigEvent = NULL;
 
    };
}SHMSISECONF, FAR* LPSHMSISECONF;
 
class SHMSiseAPI
{
public:
    SHMSiseAPI(int maxitem = 5000);
    virtual ~SHMSiseAPI();
protected:
    SYSTEMTIME uptime;
    char lastupdate[8 + 1];//일자
    LPVOID m_pUIWnd;
    FP_REALTIMEPROC m_fnRealtime;//셋팅과 동시에 gui 화면즉시갱신 20251004
protected:
    int AttachSHM(); //공유메모리에 접근
    int my_lower_bound(MYVECTOR_SHMSISEITEM& items, string key, int beginint endint* recursive = NULL);
 
public:
    void SetUIWnd(LPVOID pWnd) {
        m_pUIWnd = pWnd;
    };
    LPSHMSISEHEADER GetSHMHeader();
    int GetSHMHeader(LPSHMSISEHEADER lpHeader);
    int GetSHMData(int index, LPSHMSISEITEM lpItem, int unmapeverytime = 0);
    LPSHMSISEITEM GetSHMData(char* shtcode, int unmapeverytime = 0);
    LPSHMSISEITEM GetSHMData(int index, int unmapeverytime = 0);
    //void SetSHMData(LPCSTR szMapName, LPCSTR szMutexName, LPSHMSISEITEM lpData, int unmapeverytime = 0);
    int DestroySharedMemory();
    int CreateSharedMemory(LPCSTR szMapName, LPCSTR szMutexName,int nMaxItems = 0);
    
    CString GetFormatMessageString(DWORD dwError);
    long SetSiseCmd(int index, LPSHMSISEITEM lpItem, LPARAM param);
    void GoRangLog(LPCSTR szkeyname, LPCSTR szbuff, LPARAM hWnd = NULL);
    int  AddSHMData(LPSHMSISEITEM lpItem, int unmapeverytime = 0);
    int  SetSHMData(int index, LPSHMSISEITEM lpItem, int unmapeverytime = 0);
    int  SetSHMData(char*shtcode, LPSHMSISEITEM lpItem, int unmapeverytime = 0);
    void SHUnMap();
    int SearchCode(MYVECTOR_SHMSISEITEM& items, string key, int beginint endint* recursive = NULL);
    //입력된 데이터로 벡터정보생성
    int BuildKeyIndex();
    //LPARAM에 외부메모리 할당시 외부호출자에게 해제를 위해 콜백
    void SetRealtimeProc(FP_REALTIMEPROC fnCallBack);
    BOOL SetEventSignal();//시세변경됨을 즉시 알린다.
    BOOL ResetEventSignal();
    //return 
    //WAIT_TIMEOUT  TIMEOUT시
    //WAIT_FAILED HANDLE이 Invalid 할 경우
    //WAIT_OBJECT_0 시그널온
    //WAIT_ABANDONED :이벤트 재설정후 Wait상태
    DWORD WaitEventSignal(DWORD dwMiliseconds = INFINITE);
public:
    SHMSISECONF m_siseconf;
    HWND m_hSHMSiseWnd;
};
 
}
 
#endif
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
/*
*  Module:     SHMSiseAPI.cpp
*  Delta:      1.0.0 (05/18/2019 11:48:34)
*  Filename:   SHMSiseAPI.cpp
*  $Author: krkim $
*  $Id: SHMSiseAPI.cpp 7995 2025-06-29 11:27:20Z krkim $
*  $Revision: 7995 $
*  Contacts: https://durumul.com durumul@gmail.com
*  주식시세공유메모리 관리자
*/
 
//이파일은 외부프로그램에서 included disable. 
#include "stdafx.h"
#include <SHMSiseAPI.h>
#include <stdio.h>
#include <afxmt.h>
#include <iostream>
#include <vector>
#include <algorithm> // For std::copy and std::back_inserter
#include <iterator>  // For std::back_inserter
 
#pragma warning(disable : 4996)
#pragma warning(disable : 6305)
using namespace std;
using namespace ns_SHMSiseAPI;
 
#ifndef HHMMSS2INT
#define HHMMSS2INT(hh,mm,ss) ((hh * 10000+ (mm * 100+ (ss % 60))
#endif
 
//SHMSISECONF SHMSiseAPI::m_siseconf;
//
//int my_lower_bound(MYVECTOR_SHTCODE& index, SHMSISECODE key, int begin, int end,int *recursive = NULL)
//{
//    int findex = -1;
//    string s1, s2;
//    if (begin > end)
//        return -1;
//    if (end >= index.size())
//        end = index.size() - 1;
//    if (begin > end) return -1;
//    int m = (begin + end) / 2;
//    s1 = index[m].shtcode;
//    s2 = key.shtcode;
//    if (s1 == s2) return m;
//    if(recursive) (*recursive)++;
//    if (s1 > s2) 
//        findex = my_lower_bound(index, key, begin, m - 1, recursive);
//    else findex = my_lower_bound(index, key, m+1, end, recursive);
//    return findex;
//}
 
int SHMSiseAPI::SearchCode(MYVECTOR_SHMSISEITEM& items, string key, int beginint endint* recursive)
{
    int findex = -1;
    findex = my_lower_bound(items, key, beginend, recursive);
    return findex;
}
 
//binary_search
int SHMSiseAPI::my_lower_bound(MYVECTOR_SHMSISEITEM& items, string key, int beginint endint* recursive)
{
    int findex = -1;
    string s1;
    if (begin > end)
        return -1;
    if (end >= items.size())
        end = items.size() - 1;
    if (begin > endreturn -1;
    int m = (begin + end/ 2;
    s1 = items[m].first;
    if (s1 == key) return m;
    if (recursive) (*recursive)++;
    if (s1 > key)
        findex = my_lower_bound(items, key, begin, m - 1, recursive);
    else findex = my_lower_bound(items, key, m + 1end, recursive);
    return findex;
}
 
SHMSiseAPI::SHMSiseAPI(int maxitem)
{
    memset(&uptime, 0sizeof(SYSTEMTIME));
#if 0
    marketid = (int)ENUM_MARKETID::NONE;
    memset(marketgb, 0sizeof(marketgb));
    ncode = 0;
    memset(shtcode, 0sizeof(shtcode));
    memset(excode, 0sizeof(excode));
    memset(hname, 0sizeof(hname));
    memset(shtname, 0sizeof(shtname));
    memset(upname, 0sizeof(upname));
    memset(category, 0sizeof(category));
#endif
    //lastupdate[0] = 0x00;
    memset(&lastupdate, 0sizeof(lastupdate));
    //noerror = 0;
    //psi = NULL;
    m_hSHMSiseWnd = NULL;
    m_fnRealtime = NULL;
    //pjan = NULL;
    if(maxitem > 0)
        m_siseconf.nMaxItems = maxitem;
    m_pUIWnd = NULL;
}
 
SHMSiseAPI::~SHMSiseAPI()
{
 
}
 
//CMutex g_mutex(FALSE, "testmutex");
CString SHMSiseAPI::GetFormatMessageString(DWORD dwError)
{
    LPVOID lpMsgBuf;
 
    /*
    FormatMessage( DWORD dwFlags,
    LPCVOID lpSource,
    DWORD dwMessageId,
    DWORD dwLanguageId,
    LPTSTR lpBuffer,
    DWORD nDataSize,
    va_list *Arguments )
    */
 
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
        | FORMAT_MESSAGE_FROM_SYSTEM
        | FORMAT_MESSAGE_IGNORE_INSERTS
        , NULL
        , dwError
        , MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
        , (LPTSTR)&lpMsgBuf
        , 0
        , NULL
    );
 
    CString str;
    str.Format(_T("%s"), lpMsgBuf);
 
    LocalFree(lpMsgBuf);
    return str;
}
 
int SHMSiseAPI::CreateSharedMemory(LPCSTR szMapName,LPCSTR szMutexName,int nMaxItems)
{
    int rc = 0;
    BOOL fInit;
    HANDLE hMapObject = NULL;  // handle to file mapping
    int nIndexSize = 0;
    int nDataSize = 0;
    int nItemSize = sizeof(SHMSISEITEM);
    int nCodeSize = sizeof(SHMSISECODE);//8
    int ordinary = 3;
    SHMSISEITEM *pRootItem = NULL*pItem = NULL;
#ifdef _DEBUG
    //SHMSISEITEM *pItemList[4300] = { 0, };
#endif
    LPSHMSISEITEM lpNeTraceData = NULL;
    if (nMaxItems <= 0)
        nMaxItems = m_siseconf.nMaxItems;
    nIndexSize = sizeof(SHMSISECODE) * nMaxItems;
    nDataSize = sizeof(SHMSISEITEM) * (nMaxItems+ordinary);
    m_siseconf.nTotalMapSize = sizeof(SHMSISEHEADER) + nIndexSize + nDataSize;
    //static LPVOID lpvMem = NULL; // pointer to shared memory
 
    SetLastError(ERROR_SUCCESS);
    //Create a named file mapping object.
    //use paging file,no security attributes,RW attr,size:high 32-bits&low 32-bits,name of map object
    hMapObject = CreateFileMapping((HANDLE)0xFFFFFFFFNULL, PAGE_READWRITE, 0,
        m_siseconf.nTotalMapSize, szMapName);// SHMSISE_TRACEMAP);
    if (hMapObject == NULL)
        return -1;
    m_siseconf.hFileMap = hMapObject;
 
    DWORD dwError = GetLastError();
    // The first process to attach initializes memory.
    bool bFirstCreated = fInit = (dwError != ERROR_ALREADY_EXISTS);
    m_siseconf.bFirstCreated = bFirstCreated;
    //Get a pointer to the file-mapped shared memory.
    //m_mapping = MapViewOfFile(hMapObject,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);//default: map entire file
    m_siseconf.mapping = MapViewOfFile(hMapObject, FILE_MAP_READ | FILE_MAP_WRITE,
        00, m_siseconf.nTotalMapSize);//default: map entire file
    if (m_siseconf.mapping == NULL)
        return -2;
    m_siseconf.hMutex = CreateMutex(NULL, FALSE, szMutexName);
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        rc = -3;
    }
    // Initialize memory if this is the first process.
    if (fInit)
        memset((LPVOID)m_siseconf.mapping, 0, m_siseconf.nTotalMapSize);
    else
        rc = -4;
    //프로세스간 이벤트 시그널 공유위해 이름을 지정한다.20251011
    //쓰레드간은 필요없음.
    m_siseconf.m_hSigEvent = CreateEvent(NULL, TRUE, FALSE, szSHMSIGNAL_EVENTNAME);
    SHMSISEHEADER *pmapheader;
    pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    pmapheader->bFirstCreated = fInit;
    SYSTEMTIME curtime;
    GetLocalTime(&curtime);
    if (fInit) {
        pmapheader->offset2read = sizeof(SHMSISEHEADER);
        pmapheader->offset2write = sizeof(SHMSISEHEADER);
        pmapheader->mapsize = m_siseconf.nTotalMapSize;
        pmapheader->maxitems = nMaxItems;
        pmapheader->lasttime = HHMMSS2INT(curtime.wHour, curtime.wMinute, curtime.wSecond);
        pmapheader->itemcount = 0;
    }
    m_siseconf.pmapheader = pmapheader;
    //LPVOID pData = (LPVOID)(pmapheader + sizeof(SHMSISEHEADER) + nIndexSize);
    m_siseconf.pdata = (byte*)(pmapheader + sizeof(SHMSISEHEADER));
    if (fInit) {
        int ii = 0;
        pRootItem = (SHMSISEITEM*)m_siseconf.pdata;
        for (ii = 0; ii < m_siseconf.nMaxItems; ii++) {
            pItem = (SHMSISEITEM*)&pRootItem[ii];
            pItem->setcount = 0;
            //pItemList[ii] = pItem;
        }
    }
    return rc;//0 = 성공
}
 
int SHMSiseAPI::DestroySharedMemory()
{
    BOOL fIgnore;
    if(m_siseconf.mapping != NULL)
        fIgnore = UnmapViewOfFile(m_siseconf.mapping);// Unmap shared memory from the process's address space. 
    if (m_siseconf.hFileMap)
        fIgnore = CloseHandle(m_siseconf.hFileMap);// Close the process's handle to the file-mapping object.
 
    if(m_siseconf.hMutex)
        CloseHandle(m_siseconf.hMutex);
    if (m_siseconf.m_hSigEvent)
    CloseHandle(m_siseconf.m_hSigEvent);
    m_siseconf.mapping = NULL;
    m_siseconf.hFileMap = NULL;
    m_siseconf.hMutex = NULL;
    m_siseconf.m_hSigEvent = NULL;
    m_siseconf.pdata = NULL;
    m_siseconf.bFirstCreated = false;
    return TRUE;
}
 
//이미생성된 공유메모리에 접근한다.
int SHMSiseAPI::AttachSHM()
{
    int rc = 0;
    if (m_siseconf.hFileMap == NULL)
        m_siseconf.hFileMap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, SHMSISE_MAPNAME);// SHMSISE_TRACEMAP);
    if (m_siseconf.hFileMap == NULL)
        return -2;
    if (m_siseconf.hMutex == NULL) {
        m_siseconf.hMutex = CreateMutex(NULL, TRUE, SHMSISE_MUTEXNAME);// "Gorang-Mutex");
        if (GetLastError() == ERROR_ALREADY_EXISTS) {
            int aa = 0;
            aa = 1;
        }
    }
    if (m_siseconf.hMutex == NULL)
        return -3;
 
    if (m_siseconf.mapping == NULL) {
        m_siseconf.mapping = MapViewOfFile(m_siseconf.hFileMap,
            FILE_MAP_READ | FILE_MAP_WRITE, 00, m_siseconf.nTotalMapSize);
    }
    if (m_siseconf.mapping == NULL)
        return -4;
    SHMSISEITEM* pRootItem = (SHMSISEITEM*)m_siseconf.pdata;
    SHMSISEHEADER* pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    m_siseconf.pmapheader = pmapheader;
#if 0 //low speed
    if(pmapheader && pmapheader->itemcount != m_siseconf.vecitems.size())
        BuildKeyIndex();
#endif
    return rc;
}
 
BOOL SHMSiseAPI::SetEventSignal()
{
    return SetEvent(m_siseconf.m_hSigEvent);
}
 
BOOL SHMSiseAPI::ResetEventSignal()
{
    return ResetEvent(m_siseconf.m_hSigEvent);
}
 
//return 
//WAIT_TIMEOUT  TIMEOUT시
//WAIT_FAILED HANDLE이 Invalid 할 경우
//WAIT_OBJECT_0 시그널온
//WAIT_ABANDONED :이벤트 재설정후 Wait상태
DWORD SHMSiseAPI::WaitEventSignal(DWORD dwMiliseconds)
{
    if (dwMiliseconds < 0 || dwMiliseconds == INFINITE)
        dwMiliseconds = INFINITE;
    return WaitForSingleObject(m_siseconf.m_hSigEvent, dwMiliseconds);
}
 
//20210403
int SHMSiseAPI::AddSHMData(LPSHMSISEITEM lpItem, int unmapeverytime)
{
    int rc = 0;
    SHMSISEITEM* pRootItem = NULL* pItem = NULL;
    SHMSISECODE* pCode = NULL;
    //SHMSISEITEM* pItemList[4800] = { 0, };
    SHMSISEHEADER* pmapheader;
    LPVOID lpSharedData;
    int attach_error = AttachSHM();
    if (attach_error)
        return -1;
 
    pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    if (!pmapheader) {
        return -3;
    }
    int index = pmapheader->itemcount;
    //if (pmapheader->offset2write >= pmapheader->mapsize) {
    //    pmapheader->offset2write = sizeof(SHMSISEHEADER);
    //    pmapheader->rollback = 1;
    //}
    //lpSharedData = (char*)m_siseconf.mapping + pmapheader->offset2write;
    //memcpy(lpSharedData, lpData, sizeof(SHMSISEITEM));
    //pmapheader->offset2write += sizeof(SHMSISEITEM);
    //pmapheader->writecount++;
    if (pmapheader->itemcount >= pmapheader->maxitems - 1) {
        return -4;
    }
    WaitForSingleObject(m_siseconf.hMutex, INFINITE); //뮤텍스락(진입점)
    pmapheader->lastwriteindex = index;
    pmapheader->itemcount++;
    pRootItem = (SHMSISEITEM*)m_siseconf.pdata;
    pItem = (SHMSISEITEM*)&pRootItem[index];
    *pItem = *lpItem;
    pItem->setcount = 1;
    if (unmapeverytime) {
        SHUnMap();
    }
exit_now:
    ReleaseMutex(m_siseconf.hMutex); //뮤텍스 언락
    return index;
}
 
int SHMSiseAPI::BuildKeyIndex()
{
    SHMSISEITEM* pItem = NULL;
    SHMSISEITEM* pRootItem = (SHMSISEITEM*)m_siseconf.pdata;
    SHMSISEHEADER* pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    if (!pmapheader) {
        return -3;
    }
    m_siseconf.pmapheader = pmapheader;
    MYVECTOR_SHMSISEITEM vecitems;
    for (int i = 0; i < pmapheader->itemcount; i++) {
        pItem = (SHMSISEITEM*)&pRootItem[i];
        vecitems.push_back(std::make_pair(pItem->si.shtcode,*pItem));
    }
    // Sort using default behavior (ascending by first, then second)
    std::sort(vecitems.begin(), vecitems.end(),
        [](const std::pair<string, SHMSISEITEM>& left, const std::pair<string, SHMSISEITEM>& right) {
        return left.first < right.first;
    });
    //rearrange itemdata
    for (int i = 0; i < vecitems.size(); i++) {
        pItem = (SHMSISEITEM*)&pRootItem[i];
        *pItem = vecitems[i].second;
    }
 
    //std::copy(pRootItem, pRootItem + pmapheader->itemcount, myVector.begin()); // Copy elements
    //m_siseconf.vecitems.assign(pRootItem, pRootItem + pmapheader->itemcount);
    m_siseconf.vecitems.assign(vecitems.begin(), vecitems.end());
    int vcount = m_siseconf.vecitems.size();
    SetEventSignal();
    return vcount;
}
 
void SHMSiseAPI::SetRealtimeProc(FP_REALTIMEPROC fnCallBack)
{
    m_fnRealtime = fnCallBack;
    m_siseconf.m_fnRealtime = fnCallBack;
}
 
int SHMSiseAPI::SetSHMData(char* shtcode, LPSHMSISEITEM lpItem, int unmapeverytime)
{
    int rc = 0;
    //int nSize = sizeof(SHMSISEITEM) * m_siseconf.nMaxItems;
    SHMSISEITEM* pRootItem = NULL* pItem = NULL;
    //SHMSISEITEM* pItemList[4800] = { 0, };
    SHMSISEHEADER* pmapheader = NULL;
    LPVOID lpSharedData;
    int attach_error = AttachSHM();
    if (attach_error)
        return -1;
    pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    if (!pmapheader)
        return -3;
 
    if (pmapheader->itemcount == 0) {
        return -4;
    }
    WaitForSingleObject(m_siseconf.hMutex, INFINITE); //뮤텍스락(진입점)
    if (pmapheader && pmapheader->itemcount != m_siseconf.vecitems.size())
        BuildKeyIndex();
    pRootItem = (SHMSISEITEM*)m_siseconf.pdata;
    int recursive = 0;
    int findex = -1;
    findex = my_lower_bound(m_siseconf.vecitems, shtcode, 0, m_siseconf.vecitems.size(), &recursive);
    if (findex >= 0) {
        pItem = (SHMSISEITEM*)&pRootItem[findex];
        if (strnicmp(pItem->si.shtcode, shtcode, 6)) {
            int error = 1;
        }
        *pItem = *lpItem;//memcpy(pItem, lpItem, sizeof(SHMSISEITEM));
        pItem->setcount++;
        m_siseconf.vecitems[findex].second = *pItem;
        pmapheader->lastupdateindex = findex;
        SetEventSignal();
        if (m_siseconf.m_fnRealtime) {
            int rc = m_siseconf.m_fnRealtime(shtcode,(WPARAM)m_pUIWnd, (LPARAM)pItem);
        }
    }
    if (unmapeverytime) {
        SHUnMap();
    }
exit_now:
    ReleaseMutex(m_siseconf.hMutex); //뮤텍스 언락
    return findex;
}
 
//20210403
int SHMSiseAPI::SetSHMData(int index, LPSHMSISEITEM lpItem, int unmapeverytime)
{
    int rc = 0;
    //int nSize = sizeof(SHMSISEITEM) * m_siseconf.nMaxItems;
    SHMSISEITEM* pRootItem = NULL* pItem = NULL;
    //SHMSISEITEM* pItemList[4800] = { 0, };
    SHMSISEHEADER* pmapheader;
    LPVOID lpSharedData;
    int attach_error = AttachSHM();
    if (attach_error)
        return -1;
    pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    if (!pmapheader)
        return -3;
 
    if (index < 0 || pmapheader->itemcount == 0 || index >= pmapheader->itemcount) {
        return -4;
    }
    WaitForSingleObject(m_siseconf.hMutex, INFINITE); //뮤텍스락(진입점)
    pmapheader->lastupdateindex = index;
    pRootItem = (SHMSISEITEM*)m_siseconf.pdata;
    pItem = (SHMSISEITEM*)&pRootItem[index];
    *pItem = *lpItem;
    pItem->setcount++;
 
    m_siseconf.vecitems[index].second = *pItem;
    SetEventSignal();
    if (m_siseconf.m_fnRealtime) {
        int rc = m_siseconf.m_fnRealtime(pItem->si.shtcode, (WPARAM)m_pUIWnd, (LPARAM)pItem);
    }
    if (unmapeverytime) {
        SHUnMap();
    }
exit_now:
    ReleaseMutex(m_siseconf.hMutex); //뮤텍스 언락
    return index;
}
 
LPSHMSISEHEADER SHMSiseAPI::GetSHMHeader()
{
    SHMSISEHEADER* pmapheader = NULL;
    WaitForSingleObject(m_siseconf.hMutex, INFINITE); //뮤텍스의 진입점
    pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    m_siseconf.pmapheader = pmapheader;
    ReleaseMutex(m_siseconf.hMutex);
    return pmapheader;
}
 
int SHMSiseAPI::GetSHMHeader(LPSHMSISEHEADER lpHeader)
{
    int rc = -1;
    LPVOID lpSharedData;
    SHMSISEHEADER *pmapheader;
    WaitForSingleObject(m_siseconf.hMutex, INFINITE); //뮤텍스의 진입점 ReleaseMutex와 pair짝
    pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    m_siseconf.pmapheader = pmapheader;
    if (pmapheader) {
        memcpy(lpHeader, pmapheader, sizeof(SHMSISEHEADER));
        rc = 0;
    }
    ReleaseMutex(m_siseconf.hMutex);
    return rc;
}
 
int SHMSiseAPI::GetSHMData(int index,LPSHMSISEITEM lpItem, int unmapeverytime)
{
    int rc = 0;
    LPSHMSISEITEM pItem = GetSHMData(index, unmapeverytime);
    if (pItem) {
        *lpItem = *pItem;
        return 0;
    }
    return -1;
}
 
LPSHMSISEITEM SHMSiseAPI::GetSHMData(int index, int unmapeverytime)
{
    int rc = 0;
    SHMSISEHEADER* pmapheader;
    SHMSISEITEM* pRootItem = NULL* pItem = NULL;
    //뮤텍스를 걸어서 프로세스간(쓰레드는 기본) 공유메모리 상호배제 역할을 한다!
    //크리티컬 세션은 한 프로세스 내에서 쓰레드 끼리 동기화 위한 것이고,
    //프로세스끼리 동기화는 안된다.]
    if (index < 0)
        return NULL;
    if (m_siseconf.mapping == NULL) {
        rc = AttachSHM();
        if (rc) return NULL;
    }
 
    WaitForSingleObject(m_siseconf.hMutex, INFINITE); //뮤텍스의 진입점
    pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    if (pmapheader == NULL) {
        rc = -2;
        goto exit_now;
    }
    int nMaxItems = pmapheader->maxitems;// m_siseconf.nMaxItems;
    int nIndexSize = sizeof(SHMSISECODE) * nMaxItems;
    if (!m_siseconf.pdata)
        m_siseconf.pdata = (byte*)(pmapheader + sizeof(SHMSISEHEADER));
 
    if (pmapheader->itemcount == 0 || index >= pmapheader->itemcount) {
        rc = -3;
        goto exit_now;
    }
    
#if 0
    DWORD dwFileSize = GetFileSize(m_hFileMap, NULL); //무용지물
    MEMORY_BASIC_INFORMATION mbi = { 0 };//페이지 블록크기임(실데이타 크기아님)
    VirtualQueryEx(GetCurrentProcess(), m_mapping, &mbi, sizeof(mbi));
#endif
    pRootItem = (SHMSISEITEM*)m_siseconf.pdata;
    pItem = (SHMSISEITEM*)&pRootItem[index];
    pmapheader->lastreadindex = index;
    if (pmapheader->rollback) {
        pmapheader->rollback = 0;
    }
    pmapheader->readcount++;
    if (unmapeverytime) {
        SHUnMap();
    }
exit_now:
    ReleaseMutex(m_siseconf.hMutex);
    return pItem;
}
 
LPSHMSISEITEM SHMSiseAPI::GetSHMData(char* shtcode, int unmapeverytime)
{
    int rc = 0;
    int findex = -1;
    MYVECTOR_SHTCODE vecindex;
    SHMSISEHEADER* pmapheader;
    SHMSISEITEM* pRootItem = NULL* pItem = NULL;
    vector<SHMSISEITEM> myVector;
    //뮤텍스를 걸어서 프로세스간(쓰레드는 기본) 공유메모리 상호배제 역할을 한다!
    //크리티컬 세션은 한 프로세스 내에서 쓰레드 끼리 동기화 위한 것이고,
    //프로세스끼리 동기화는 안된다.
    if (m_siseconf.mapping == NULL) {
        rc = AttachSHM();
        if (rc) return NULL;
    }
    WaitForSingleObject(m_siseconf.hMutex, INFINITE); //뮤텍스의 진입점
    pmapheader = (LPSHMSISEHEADER)m_siseconf.mapping;
    if (pmapheader == NULL) {
        rc = -1;
        goto exit_now;
    }
    int nMaxItems = pmapheader->maxitems;// m_siseconf.nMaxItems;
    int nIndexSize = sizeof(SHMSISECODE) * nMaxItems;
    if (!m_siseconf.pdata)
        m_siseconf.pdata = (byte*)(pmapheader + sizeof(SHMSISEHEADER));
 
    if (pmapheader->itemcount == 0) {
        rc = -3;
        goto exit_now;
    }
    if (pmapheader && pmapheader->itemcount != m_siseconf.vecitems.size())
        BuildKeyIndex();
#if 0
    DWORD dwFileSize = GetFileSize(m_hFileMap, NULL); //무용지물
    MEMORY_BASIC_INFORMATION mbi = { 0 };//페이지 블록크기임(실데이타 크기아님)
    VirtualQueryEx(GetCurrentProcess(), m_mapping, &mbi, sizeof(mbi));
#endif
    pRootItem = (SHMSISEITEM*)m_siseconf.pdata;
 
    int recursive = 0;
    //findex = my_lower_bound(m_siseconf.vecindex, findcode, 0, m_siseconf.vecindex.size(), &recursive);
    ////
    ////std::copy(pRootItem, pRootItem + pmapheader->itemcount, myVector.begin()); // Copy elements
    //myVector.assign(pRootItem, pRootItem + pmapheader->itemcount);
    findex = my_lower_bound(m_siseconf.vecitems, shtcode, 0, m_siseconf.vecitems.size(), &recursive);
    if (findex >= 0) {
        pItem = (SHMSISEITEM*)&pRootItem[findex];
        pmapheader->lastupdateindex = findex;
        pmapheader->readcount++;
 
        if (strnicmp(shtcode, pItem->si.shtcode, 6)) {
            int error = 1;
        }
    }
    if (unmapeverytime) {
        SHUnMap();
    }
exit_now:
    ReleaseMutex(m_siseconf.hMutex);
    return pItem;
}
 
void SHMSiseAPI::SHUnMap()
{
    if (m_siseconf.mapping)
        BOOL flag = UnmapViewOfFile(m_siseconf.mapping);
    if (m_siseconf.hFileMap)
        CloseHandle(m_siseconf.hFileMap);
    m_siseconf.mapping = NULL;
    m_siseconf.hFileMap = NULL;
}
 
long SHMSiseAPI::SetSiseCmd(int index, LPSHMSISEITEM lpItem, LPARAM param)
{
    SHMSISEITEM tData = { 0, };
    if (m_hSHMSiseWnd == NULL)
        m_hSHMSiseWnd = ::FindWindow(NULL, SHMSISE_WINDOWCLASSNAME);
    else if(!IsWindow(m_hSHMSiseWnd)){
            m_hSHMSiseWnd = ::FindWindow(NULL, SHMSISE_WINDOWCLASSNAME);
    }
    if (m_hSHMSiseWnd == NULL)
    {
        DWORD dwerr = GetLastError();
        return 0;
    }
    tData.param = param;
    SetSHMData(index, lpItem);
    //::SendMessage(m_hSHMSiseWnd, WM_BATGORANG, (WPARAM)SHMSISE_SETCMD, (LPARAM)0L);
    ////::PostMessage(m_hSHMSiseWnd, WM_BATGORANG, (WPARAM)SHMSISE_SETCMD, (LPARAM)0L);
    //if (!strnicmp(tData.szCmd, SHMSISE_CMD_DETACH, 6)) {
    //    SHUnMap();
    //}
 
    return 1;
}
 
void SHMSiseAPI::GoRangLog(LPCSTR szkeyname, LPCSTR szbuff, LPARAM hWnd)
{
    SHMSISEITEM tData = { 0, };
    if (m_hSHMSiseWnd == NULL)
        m_hSHMSiseWnd = ::FindWindow(NULL, SHMSISE_WINDOWCLASSNAME);
    else if (!IsWindow(m_hSHMSiseWnd)) {
        m_hSHMSiseWnd = ::FindWindow(NULL, SHMSISE_WINDOWCLASSNAME);
    }
    if (m_hSHMSiseWnd == NULL)
    {
        DWORD dwerr = GetLastError();
        return;
    }
#if 0
    strncpy(tData.szKeyName,szkeyname,sizeof(tData.szKeyName));
    strncpy(tData.szParam,szbuff,sizeof(tData.szParam));
    tData.param2 = hWnd;
    SetSHMData(SHMSISE_MAPNAME, SHMSISE_MUTEXNAME ,&tData);
    ////Set Shared Memory of NETracer
    ////Nofity to NETracer Window
    ////::PostMessage(m_hSHMSiseWnd, WM_BATGORANG, (WPARAM)SHMSISE_SETDATA, (LPARAM)0L);
    //::SendMessage(m_hSHMSiseWnd, WM_BATGORANG, (WPARAM)SHMSISE_SETDATA, (LPARAM)0L);
#endif
}
 
 
cs

 

리눅스 vs MS-Windows

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
On Linux 
pthread_cond_broadcast
pthread_cond_wait
 
like as
    BOOL SetEventSignal();//시세변경됨을 즉시 알린다.
    BOOL ResetEventSignal();
 
만약 여러개의 ipc process 라면,
 
        while (flag && m_gatheron) {
            dwSigStatus = g_shmtool.WaitEventSignal(1000);
            if (dwSigStatus == WAIT_TIMEOUT) {
                idle++;
                if (idle % 10 == 0 && refresh == 0) {
                    if (pmapheader && 
                        (pmapheader->itemcount > 0 && nRows <= pmapheader->itemcount))
                    {
                        m_forcerefresh = 1;
                    }
                }
                break;
            }
            if (dwSigStatus == WAIT_ABANDONED) {
                g_shmtool.ResetEventSignal();
            }
            else if (dwSigStatus == WAIT_OBJECT_0) { //signaled
                flag = GatheringSHMData();
                if (flag)
                    cnt++;
                ////g_shmtool.ResetEventSignal();
            }
            if (flag == 0 && cnt >= 100) {
                break;
*/            }
 
여기에서
//return 
//WAIT_TIMEOUT  TIMEOUT시
//WAIT_FAILED HANDLE이 Invalid 할 경우
//WAIT_OBJECT_0 시그널온
//WAIT_ABANDONED :이벤트 재설정후 Wait상태
DWORD SHMSiseAPI::WaitEventSignal(DWORD dwMiliseconds)
{
    if (dwMiliseconds < 0 || dwMiliseconds == INFINITE)
        dwMiliseconds = INFINITE;
    return WaitForSingleObject(m_siseconf.m_hSigEvent, dwMiliseconds);
}
 
WaitForSingleObject 대신에 WaitForMultiObject 로
 
cs

도움이 되었다면, 여기로 기부 합니다.

풀소스코드

SHMSiseAPI.cpp
0.02MB
SHMSiseAPI.h
0.01MB
SiseWnd.cpp
0.06MB
SiseWnd.h
0.01MB

도움이 되었다면, 두루에디트(duruedit) 여기로 기부 합니다.