Alternate e697dbe9c5997e35395fe158628dd8c5209481da
for Visual Studio 2022 and Windows 11.
読み取り中…
検索中…
一致する文字列を見つけられません
PipelineFactoryMethod.cpp
[詳解]
1#include "pch.h"
3
4using namespace alt;
5using namespace alt::FactoryMethod;
6
7#define MAX_PRODUCT 10
8#define CONTAINER_WEIGHT (1024 * 1024 * 10) // 10MB
9
10typedef struct _container
11{
16
17// -- ByteData ------------------------------------------------------
18
20{
21 _lpbyChunkData = nullptr;
22 _chunkSize = 0;
23}
24
25ByteData::ByteData (int seqNo, LPBYTE lpbyChunkData, size_t chunkSize)
26 :IData (seqNo)
27{
28 _lpbyChunkData = new BYTE[chunkSize];
29 CopyMemory (_lpbyChunkData, lpbyChunkData, chunkSize);
30 _chunkSize = chunkSize;
31}
32
34{
35 if (_lpbyChunkData != nullptr)
36 {
37 delete[] _lpbyChunkData;
38 }
39}
40
41// -- Config =------------------------------------------------------
42
44 :IConfig ()
45{
46 _interval = -1;
48}
49
51{
52
53}
54
55bool Config::Load (LPCTSTR lpctszConfigPath)
56{
57 _configPath = lpctszConfigPath;
58
59 _interval = ::GetPrivateProfileInt (
62 -1,
63 _configPath.Ctr ());
64 if (_interval == -1)
65 {
66 return false;
67 }
68
69 _dummyProcessTime = ::GetPrivateProfileInt (
72 -1,
73 _configPath.Ctr ());
74 if (_dummyProcessTime == -1)
75 {
76 return false;
77 }
78
79 return true;
80}
81
83{
84 int _interval = ::GetPrivateProfileInt (
87 0,
88 _configPath.Ctr ());
89 if (_interval == 0)
90 {
91 return false;
92 }
93
94 int _dummyProcessTime = ::GetPrivateProfileInt (
97 -1,
98 _configPath.Ctr ());
99 if (_interval == -1)
100 {
101 return false;
102 }
103
104 return true;
105}
106
107// -- ClockElement -------------------------------------------------
108
110 :IElement (elementName)
111{
112 _seqNo = 0;
113 _stop = false;
114 _watchdog = nullptr;
115 _thread = nullptr;
116 _dwInterval = 0;
117 _logger.Init (LogLevel::Trace, elementName.Ctr (), 10, 1024 * 1024 * 10);
118}
119
121{
122
123}
124
126{
127 _seqNo = 0;
128 _stop = false;
129 _watchdog = nullptr;
130 _thread = nullptr;
131 _dwInterval = 0;
132}
133
135{
136 _logger.Info (_T ("ClockElement::Init()"));
137
138 _watchdog = new WatchDogTimer (nullptr);
139 _watchdog->InitTimer (this->GetName ().Ctr ());
140 _thread = new Thread (this);
141}
142
143void ClockElement::Start (DWORD dwInterval)
144{
145 _logger.Info (_T ("ClockElement::Start()"));
146 OutputDebugString (_T ("ClockElement::Start() IN.\n"));
147
148 _stop = false;
149 _dwInterval = dwInterval;
150 _thread->Create ();
151
152 OutputDebugString (_T ("ClockElement::Start() OUT.\n"));
153}
154
156{
157 _logger.Info (_T ("ClockElement::Stop()"));
158 OutputDebugString (_T ("ClockElement::Stop() IN.\n"));
159
161 _stop = true;
162
163 OutputDebugString (_T ("ClockElement::Stop() OUT.\n"));
164}
165
166DWORD ClockElement::Invoke (LPVOID lpvParam)
167{
168 _logger.Info (_T ("ClockElement::Invoke()"));
169 OutputDebugString (_T ("ClockElement::Invoke() IN.\n"));
170
171 pContainer container = new Container;
173 double dPastTick = 0;
174 TString msg;
175
177
178 while (!_stop)
179 {
180 Q.Start ();
181 DWORD dwReason = _watchdog->WaitTimer ();
182
183 if (dwReason == WAIT_OBJECT_0)
184 {
185 ByteData* byteData = new ByteData (_seqNo++, (LPBYTE)container, sizeof (Container));
186 SYSTEMTIME& localTime = byteData->GetCreateTime ();
187
188 GetLocalTime (&localTime);
189 Notify (byteData);
190
191 Q.Stop ();
192 dPastTick = Q.PastTime () * 1000;
193
194 msg.Format (_T ("ClockTime %3u Past=%5u Diff=%7d %02d:%02d:%02d.%03d"),
195 byteData->GetSeqNo (), static_cast<UINT>(dPastTick),
196 static_cast<INT>(dPastTick - (double)_dwInterval * 1000),
197 localTime.wHour, localTime.wMinute, localTime.wSecond,
198 localTime.wMilliseconds);
199 OutputDebugString (msg.Ctr ());
200 _logger.Info (msg.Ctr ());
201 }
202 }
203
204 delete container;
205
206 OutputDebugString (_T ("ClockElement::Invoke() OUT.\n"));
207 return 0;
208}
209
210// -- SyncElement -------------------------------------------------
211
213 :IElement (elementName)
214{
215 _product = nullptr;
216}
217
219{
220
221}
222
224 :IElement ()
225{
226 _product = nullptr;
227}
228
230{
231 IData* result = _product->Process (data);
232 this->Notify (result);
233}
234
235// -- QueueElement ------------------------------------------------
236
238 :IElement (elementName)
239{
240 _product = nullptr;
241 _thread = nullptr;
242}
243
245{
246 delete _thread;
247}
248
250{
251 _event.Create (this->GetName ().Ptr (), TRUE, FALSE);
252 _thread = new Thread (this);
253 _thread->Create ();
254}
255
257{
258 _exclusive.Enter ();
259 _queue.push (data);
260 _event.Set ();
261 _exclusive.Leave ();
262}
263
264DWORD QueueElement::Invoke (LPVOID lpvParam)
265{
266 Event event;
267 event.Open (this->GetName ().Ctr ());
268
269 for (;;)
270 {
271 event.Wait ();
272 _exclusive.Enter ();
273
274 if (!_queue.empty ())
275 {
276 IData* data = _queue.front ();
277 _queue.pop ();
278 IData* result = _product->Process (data);
279 this->Notify (result);
280 }
281
282 event.Reset ();
283 _exclusive.Leave ();
284 }
285}
286
287// -- TerminateElement ----------------------------------------------
288
290 :IElement (elementName)
291{
292 _logger.Init (LogLevel::Trace, elementName.Ctr (), 10, 1024 * 1024 * 10);
293}
294
296{
297
298}
299
301{}
302
303//
304// @sa https://ameblo.jp/sgl00044/entry-12463939983.html
305//
307{
308 OutputDebugString (_T ("TerminateElement::Update()"));
309
310 ByteData* byteData = dynamic_cast<ByteData*>(data);
311 pContainer container = (pContainer)(byteData->GetChunk ());
312
313 TString message;
314
315 for (int i = 0; i < MAX_PRODUCT; i++)
316 {
317 message.Format (_T ("Product(%u) Seq(%02u) Start(%u) ProcessTick(%u)"),
318 i, byteData->GetSeqNo (), container->ProcessStartTick[i],
319 static_cast<UINT>(container->ProcessTick[i]));
320
321 OutputDebugString (message.Ctr ());
322 _logger.Info (message.Ctr ());
323 }
324
325 delete data;
326}
327
328// -- DummyProduct --------------------------------------------------
329
331 :IProduct (id, productName)
332{
333 TString msg = _T ("DummyProduct::DummyProduct(");
334 msg += productName;
335 msg += _T (")\n");
336 OutputDebugString (msg.Ctr ());
337
338 _config = nullptr;
339}
340
342 :IProduct ()
343{
344 _config = nullptr;
345}
346
348{
349 TString msg = _T ("DummyProduct::Init(");
350 msg += _productName;
351 msg += _T (")\n");
352 OutputDebugString (msg.Ctr ());
353
354 _config = dynamic_cast<Config*>(config);
355
356 return true;
357}
358
360{
361 TString msg = _T ("DummyProduct::Start(");
362 msg += _productName;
363 msg += _T (")\n");
364 OutputDebugString (msg.Ctr ());
365
366 return true;
367}
368
370{
372 Q.Start ();
373
374 TString msg = _T ("DummyProduct::Process(");
375 msg += _productName;
376 msg += _T (")\n");
377 OutputDebugString (msg.Ctr ());
378
379 ByteData* byteData = dynamic_cast<ByteData*>(data);
380 Container* container = (pContainer)(byteData->GetChunk ());
381
382 Sleep (_config->GetDummyProcessTime ());
383
384 if (data->GetSeqNo () % 10 == 0)
385 {
386 IMessage message;
387 message.SetParam (0, this->GetID (), 0);
388 this->Notify (&message);
389 }
390
391 Q.Stop ();
392 container->ProcessTick[_id] = Q.PastTime ();
393 container->ProcessStartTick[_id] = Q.GetStartTick ().LowPart;
394 return data;
395}
396
398{
399 TString msg = _T ("DummyProduct::Stop(");
400 msg += _productName;
401 msg += _T (")\n");
402 OutputDebugString (msg.Ctr ());
403
404 return true;
405}
406
408{
409 TString msg = _T ("DummyProduct::Exit(");
410 msg += _productName;
411 msg += _T (")\n");
412 OutputDebugString (msg.Ctr ());
413
414 return true;
415}
416
418{
419 TString msg = _T ("DummyProduct::Update(");
420 msg += _productName;
421 msg += _T (")\n");
422 OutputDebugString (msg.Ctr ());
423
424 TString msgString;
425 msgString.Format (_T ("Response From(%d) To(%d) Command(%d)\n"),
426 message->GetFrom (), message->GetTo (), message->GetCommand ());
427 OutputDebugString (msgString.Ctr ());
428}
429
430// -- Creator -------------------------------------------------------
431
433{
434
435}
436
438{
439
440}
441
443{
444 IProduct* product;
445
446 if (target.Substring (0, 5) == _T ("Dummy"))
447 {
448 product = new DummyProduct (id, fullName);
449 }
450 else
451 {
452 throw _T ("Invalid argument "), target.Ctr ();
453 }
454
455 return product;
456}
457
459{
460 IElement* element;
461
462 if (target == _T ("Clock"))
463 {
464 element = new ClockElement (fullName);
465 }
466 else if (target == _T ("Sync"))
467 {
468 element = new SyncElement (fullName);
469 }
470 else if (target == _T ("Queue"))
471 {
472 element = new QueueElement (fullName);
473 }
474 else if (target == _T ("Terminate"))
475 {
476 element = new TerminateElement (fullName);
477 }
478 else
479 {
480 throw _T ("Invalid argument "), target.Ctr ();
481 }
482
483 return element;
484}
485
486// -- ProductManager ------------------------------------------------
487
489{
490 _config = nullptr;
491}
492
494{
495
496}
497
499{
500 _config = config;
501
502 for (auto product : _products)
503 {
504 product.second->Init (config);
505 }
506
507 ClockElement* clockElement = dynamic_cast<ClockElement*>(this->GetElement (_T ("Clock")));
508 clockElement->Init ();
509
510 return true;
511}
512
514{
515 bool ret;
516
517 for (auto product : _products)
518 {
519 ret = product.second->Start ();
520 if (ret == false)
521 {
522 return false;
523 }
524 }
525
526 ClockElement* clockElement = dynamic_cast<ClockElement*>(this->GetElement (_T ("Clock")));
527 clockElement->Start (dynamic_cast<Config*>(_config)->GetInterval ());
528
529 return true;
530}
531
533{
534 ClockElement* clockElement = dynamic_cast<ClockElement*>(this->GetElement (_T ("Clock")));
535 clockElement->Stop ();
536
537 for (auto product : _products)
538 {
539 product.second->Stop ();
540 }
541
542 return true;
543}
544
546{
547 for (auto product : _products)
548 {
549 product.second->Exit ();
550 }
551
552 return true;
553}
554
556{
557 TString msgString;
558 msgString.Format (_T ("Response From(%d) To(%d) Command(%d)\n"),
559 message->GetFrom (), message->GetTo (), message->GetCommand ());
560 OutputDebugString (msgString.Ctr ());
561}
562
564{
565 auto pair = std::pair<TString, IProduct*> (name, product);
566 _products.insert (pair);
567}
568
570{
571 return _products[name];
572}
573
575{
576 auto pair = std::pair<TString, IElement*> (name, element);
577 _elements.insert (pair);
578}
579
581{
582 return _elements[name];
583}
584
585// -- PipelineFactoryMethod -----------------------------------------
586
588{
589 auto manager = new ProductManager ();
590 auto creator = new Creator ();
591
592 TString prefixNames[] = { _T ("TEST1_"), _T ("TEST2_"), _T ("TEST3_"), _T ("TEST4_"), _T ("TEST5_") };
593 TString objectNames[] = { _T ("Dummy1"), _T ("Dummy2") };
594 // MAX_PRODUCTになるように調整(現在10)
595
596 IElement* previousElement = creator->CreateElement (_T ("Clock"), _T ("ClockGenerator"));
597 manager->AddElement (_T ("Clock"), previousElement);
598
599 TString fullName;
600 int id = 0;
601
602 for (TString prefixName : prefixNames)
603 {
604 for (TString objectName : objectNames)
605 {
606 fullName = prefixName + objectName;
607
608 IProduct* product = creator->CreateProduct (id++, objectName, fullName);
609 manager->AddProduct (fullName, product);
610 manager->Add (product);
611 product->Add (manager);
612
613 IElement* element = creator->CreateElement (_T ("Queue"), fullName);
614 manager->AddElement (fullName, element);
615
616 element->SetProduct (product);
617 element->Setup ();
618
619 previousElement->Add (element);
620 previousElement = element;
621 }
622
623 }
624
625 IElement* terminateElement = creator->CreateElement (_T ("Terminate"), _T ("Terminater"));
626 previousElement->Add (terminateElement);
627 manager->AddElement (_T ("Terminate"), terminateElement);
628
629 return manager;
630}
#define SECTION_PIPELINE_FACTORY
Definition: ConsoleDriver.h:15
struct _container Container
#define MAX_PRODUCT
#define CONTAINER_WEIGHT
struct _container * pContainer
#define KEYWORD_DUMMY_PROCESS_TIME
#define KEYWORD_INTERVAL
プリコンパイル済みヘッダー ファイルです。
VOID APIENTRY Enter()
排他処理開始
VOID APIENTRY Leave()
排他処理終了
イベントに関するWindowsAPIを集約したクラス
Definition: Event.h:16
BOOL APIENTRY Create(LPCTSTR lpctszName, BOOL bManualReset, BOOL bInitialState)
イベントを作成します。
Definition: Event.cpp:12
BOOL APIENTRY Open(LPCTSTR lpctszName)
イベントをオープンします。
Definition: Event.cpp:27
BOOL APIENTRY Set() const
イベントをセット(シグナル状態に)します。
Definition: Event.cpp:40
virtual void Start(DWORD dwInterval)
virtual DWORD Invoke(LPVOID lpvParam)
コールバック関数プレースホルダ
virtual bool Load(LPCTSTR lpctszConfigPath)
virtual IProduct * CreateProduct(int id, TString target, TString fullName)
virtual IElement * CreateElement(TString target, TString fullName)
virtual IData * Process(IData *data)
virtual bool Init(IConfig *config)
virtual void Update(IMessage *message)
SYSTEMTIME & GetCreateTime()
virtual void SetProduct(IProduct *product)
virtual TString & GetName()
void SetParam(int to, int from, int command)
virtual IData * Process(IData *data)=0
std::map< TString, IElement * > _elements
virtual void Update(IMessage *message)
virtual void AddProduct(TString name, IProduct *product)
virtual IElement * GetElement(TString name)
virtual bool Init(IConfig *config)
virtual IProduct * GetProduct(TString name)
std::map< TString, IProduct * > _products
virtual void AddElement(TString name, IElement *element)
virtual DWORD Invoke(LPVOID lpvParam)
コールバック関数プレースホルダ
BOOL APIENTRY Init(LogLevel logLevel, LPCTSTR fileName, SHORT sRotation, DWORD dwFileSize)
初期化
Definition: Log.cpp:32
VOID APIENTRY Info(LPCTSTR message, DWORD dwThreadID=GetCurrentThreadId())
情報ログの出力
Definition: Log.cpp:209
高分解能時間計測クラス
VOID APIENTRY Start()
計測を開始します。
LARGE_INTEGER APIENTRY GetStartTick() const
Start()時のカウンター値を取得します。
double APIENTRY PastTime() const
計測開始〜計測終了までの時間を出力します。
VOID APIENTRY Stop()
計測を終了します。
文字列に関するWindowsAPIを集約したクラス
Definition: TString.h:17
TString &APIENTRY Format(LPCTSTR format,...)
フォーマットに従ってパラメータを文字列化します。
Definition: TString.cpp:333
LPCTSTR APIENTRY Ctr() const
内部で確保している文字列ポインタを取得します。
Definition: TString.h:46
TString APIENTRY Substring(int startPos, int length=0)
文字列を切り出します。
Definition: TString.cpp:219
スレッドに関するWindowsAPIを集約したクラス
Definition: Thread.h:43
BOOL APIENTRY Create(PTHREAD_START_ROUTINE function=NULL, LPVOID lpvParam=NULL, DWORD dwCreationFlag=0)
スレッドを作成します。
Definition: Thread.cpp:24
タイマーに関するWindowsAPIを集約したクラス
Definition: WatchDogTimer.h:18
BOOL APIENTRY InitTimer(LPCTSTR lpctszName=NULL)
初期化
DWORD APIENTRY WaitTimer() const
タイムアップ待機
BOOL APIENTRY StopTimer() const
タイマー停止
BOOL APIENTRY StartTimer(DWORD dwTime) const
タイマー開始
virtual void Add(IObserver< Data > *observer)
IObserver<Data>*を引数とする関数 Add()
virtual void Notify(IData * data)
Dataを引数とする関数 Notify()
Definition: DBLibrary.h:12
@ Trace
(5)トレース
DWORD ProcessStartTick[MAX_PRODUCT]
BYTE byDummy[CONTAINER_WEIGHT]
double ProcessTick[MAX_PRODUCT]