http://www.cybletter.com/index.php?id=3

http://www.cybletter.com/index.php?id=30

Source Code

http://www.cybletter.com/index.php?s=file_download&id=3

Full Paper

www.cybletter.com/index.php?s=file_download&id=4

Alexandr Štefek
Military Academy in Brno
alexandr@stefek.cz

Abstract

This paper present implementation of parallel execution.

If we use parallel proces in programs we have to solve synchronization.

We show the effective implementation of parallel execution without using critical sections, semaphores, mutexes or events.

Thread

The thread is system object defined on platform Win32.

SDK defines some method for thread creating and handling.

In real implementation must be defined the procedure for all parallel procedures.

If in system Win32 thread create new window handle then all messages are handled by this thread.

For this fact commes the idea of problem solution.

We can simply create window handle on executing thread.

When this thread executes loop for message handling it is possible to send special message to thread window handle.

The parameters of message can be method to execute and parameter for this method.

But method has 8 bytes and the message parameter only 4.

So we have allocate memory block, copy method to this block and send adress of allocated block.

Coding the method

We want to create class that has method for sync parallel and async parallel execution of methods.

Now we show, how to code the 8 byte method to 4 byte adress of method.

  1. function TAxThread.NotifyEventToPointer( Proc : TNotifyEvent ) : Longint;
  2. var
  3. Method : TMethod absolute Proc;
  4. PMethod : ^TMethod;
  5. begin
  6. New( PMethod );
  7. PMethod^ := Method;
  8. Result := Longint( PMethod );
  9. end;
  10.  
  11. procedure TAxThread.AsyncExecuteParallel( Proc : TNotifyEvent; ParamSender : TObject );
  12. begin
  13. InterlockedIncrement( FMethodsToExecute );
  14. PostMessageParallel( CM_EXECPROC_WORK_TRHREAD, NotifyEventToPointer( Proc ), Longint( ParamSender ) );
  15. end;
  16.  
  17. procedure TAxThread.ExecProcedure( var Message : TMessage );
  18. var
  19. PMethod : ^TMethod;
  20. Method : TMethod;
  21. Event : TNotifyEvent absolute Method;
  22. begin
  23. PMethod := Pointer( message.WParam );
  24. Method := PMethod^;
  25. Event( TObject( message.LParam ) );
  26. Dispose( PMethod );
  27. if FThreadID = GetCurrentThreadId then
  28. InterlockedDecrement( FMethodsToExecute );
  29. end;

NotifyEventToPointer is method for copying method to memory block.

Result of this method is adress of memory block.

Method ExeProcedure takes WParam of message, convert it back to method

and call decoded method with parametr defined by LParam of message.

Thread loop

We have to define thread message loop.

Delphi define basic thread class TThread.

This class has virtual method execute.

Defined class TAxThread is inherited from TThread.

Method TAxThread.Execute is overrided;

  1. procedure TAxThread.Execute;
  2. var
  3. Msg : TMsg;
  4. Done : Boolean;
  5. begin
  6. CreateHandleParallel;
  7. FThreadID := GetCurrentThreadId;
  8. while not Terminated do
  9. begin
  10. if Done then
  11. begin
  12. FIdleData := nil;
  13. WaitMessage;
  14. end;
  15. while ProcessMessage( Msg ) do { loop };
  16. Idle( FIdleData, Done );
  17. end;
  18. end;

At first the class has to create handle (CreateHandleParallel).

Loop while waits for messages and handles incomming messages (ProcessMessage).

  1. function TAxThread.ProcessMessage( var Msg : TMsg ) : Boolean;
  2. begin
  3. Result := False;
  4. if PeekMessage( Msg, , , , PM_REMOVE ) thenbegin
  5. Result := True;
  6. if Msg.Message <> WM_QUIT then
  7. begin
  8. TranslateMessage( Msg );
  9. DispatchMessage( Msg );
  10. end
  11. else
  12. Terminate;
  13. end;
  14. end;

Calling DispatchMessage dispatch current message to objects for execution.

If incomming method is CM_EXECUTE (defined in Delphi), then method ExecProcedure is called.

Sync and async execution

All parallel processing is sended to execution by message.

If we use for sending the API function SendMessage then the execution is synchronized

(actual thread is suspend, the context is switched, message is immediately handled and control is returned to sending thread).

The API function PostMessage puts the message to message queue and continue in execution.

When the message is peek from queue, is handled and method is executed.

  1. // Asynchro execute on parallel thread
  2. procedure TAxThread.AsyncExecuteParallel( Proc : TNotifyEvent;
  3. ParamSender : TObject );
  4. begin
  5. InterlockedIncrement( FMethodsToExecute );
  6. PostMessageParallel( CM_EXECPROC, NotifyEventToPointer( Proc ),
  7. Longint( ParamSender ) );
  8. end;
  9.  
  10. // Synchro execute on parallel thread
  11. procedure TAxThread.SyncExecuteParallel( Proc : TNotifyEvent;
  12. ParamSender : TObject );
  13. begin
  14. InterlockedIncrement( FMethodsToExecute );
  15. SendMessageParallel( CM_EXECPROC, NotifyEventToPointer( Proc ),
  16. Longint( ParamSender ) );
  17. end;

Introduced method AsyncExecuteParallel is used for async parallel execution

(execution on selected thread) of method Proc with parameter ParamSender.

Method SyncExecuteParallel runs method Proc with parameter ParamSender synchronously (waits for execution).

The thread defines method for execution on main thread (AsyncExecuteMain, SyncExecuteMain).

Using

For example of using define class

  1. type
  2. TMainForm = class( TForm )
  3. btnRandomize : TButton;
  4. imgResult : TImage;
  5. pbProgress : TProgressBar;
  6. btnMulti : TButton;
  7. procedure FormCreate( Sender : TObject );
  8. procedure FormDestroy( Sender : TObject );
  9. procedure btnRandomizeClick( Sender : TObject );
  10. procedure btnMultiClick( Sender : TObject );
  11. private
  12. { Private declarations }
  13. FExecutingThread : TAxThread;
  14. public
  15. { Public declarations }
  16. procedure RandomizeBMP( Data : TObject );
  17. procedure DoUpdate( Data : TObject );
  18. procedure Progress( Data : TObject );
  19. end;

Private variable FExecutingThread is thread on witch the metods will be executed.

There are three public method in form of TNotifyEvent (can be executed on selected thread).

  1. procedure TMainForm.btnRandomizeClick( Sender : TObject );
  2. var
  3. PomBMP : TBitmap;
  4. begin
  5. if FExecutingThread = nil then
  6. FExecutingThread := TAxThread.Create;
  7. PomBMP := TBitmap.Create;
  8. PomBMP.Width := ;
  9. PomBMP.Height := ;
  10. PomBMP.PixelFormat := pf24bit;
  11. FExecutingThread.AsyncExecuteParallel( RandomizeBMP, PomBMP );
  12. end;

When user clicked on button then method btnRandomizeClick is called.

Method calls AsyncExecuteParallel.

Main thread continue in responsing to user interaction.

When the thread contrext is switched, FExecutingThread begins execute then method RandomizeBMP.

  1. procedure TMainForm.RandomizeBMP( Data : TObject );
  2. var
  3. CurrentThread : TAxThread;
  4. PomBMP : TBitmap;
  5. I : Longint;
  6. X : Longint;
  7. Y : Longint;
  8. Color : Longint;
  9. begin
  10. if not( Data is TBitmap ) then
  11. Exit;
  12. PomBMP := Data as TBitmap;
  13. CurrentThread := TAxThread.GetCurrentThread;
  14. I := ;
  15. try
  16. PomBMP.Canvas.Lock;
  17. while not CurrentThread.Terminated do
  18. begin
  19. Inc( I );
  20. if I > MaxPoints then
  21. Break;
  22. X := Random( );
  23. Y := Random( );
  24. Color := Random( ) * * + Random( ) * + Random( );
  25. if ( I mod ( MaxPoints div ) ) = then
  26. CurrentThread.SyncExecuteMain( Progress, TObject( I ) );
  27. // slow for demonstration
  28. PomBMP.Canvas.Pixels[ X, Y ] := Color;
  29. end;
  30. finally
  31. PomBMP.Canvas.Unlock;
  32. CurrentThread.AsyncExecuteMain( DoUpdate, PomBMP );
  33. end;
  34. end;

Method RandomizeBMP decode parameter as Bitmap and fills it with some random points.

When randomize is finished, the thread notify main thread (CurrentThread.AsyncExecuteMain).

Conclusion

We present implementation of thread class for async (sync) execution.

The designed library has very effective method for developing of parallel computing.

  1. unit AxThreads2;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Classes, SysUtils, Controls, Forms, Messages;
  7.  
  8. const
  9. CM_EXECPROC = $8FFF;
  10.  
  11. type
  12. TIdleEvent = procedure( var Data : TObject; var Done : Boolean ) of object;
  13.  
  14. TAxThread = class( TThread )
  15. private
  16. FThreadID : Longint;
  17. FOnIdle : TIdleEvent;
  18. FIdleData : TObject;
  19. FWndHandleParallel : LongWord;
  20. FWndHandleMain : LongWord;
  21.  
  22. FMethodsToExecute : Longint;
  23. procedure SetOnIdle( const Value : TIdleEvent );
  24. protected
  25. procedure CreateHandleParallel;
  26. procedure DestroyHandleParallel;
  27. procedure CreateHandleMain;
  28. procedure DestroyHandleMain;
  29.  
  30. procedure MessageProcedure( var Message : TMessage ); virtual;
  31.  
  32. procedure ExecProcedure( var Message : TMessage ); message CM_EXECPROC;
  33. procedure Execute; override;
  34. procedure Idle( var Data : TObject; var Done : Boolean ); virtual;
  35.  
  36. function ProcessMessage( var Msg : TMsg ) : Boolean;
  37.  
  38. function NotifyEventToPointer( Proc : TNotifyEvent ) : Longint;
  39. public
  40. constructor Create;
  41. destructor Destroy; override;
  42.  
  43. // Posts a null message to parallel thread
  44. procedure WakeUp;
  45.  
  46. class function GetCurrentThread : TAxThread;
  47. // sends a message to main thread
  48. function SendMessageMain( Msg, WParam, LParam : LongWord ) : Longint;
  49. // posts a message to main thread
  50. function PostMessageMain( Msg, WParam, LParam : LongWord ) : LongBool;
  51.  
  52. // sends a message to parallel thread
  53. function SendMessageParallel( Msg, WParam, LParam : LongWord ) : Longint;
  54. // posts a message to parallel thread
  55. function PostMessageParallel( Msg, WParam, LParam : LongWord ) : LongBool;
  56.  
  57. // for compatibility
  58. function SendMessage( Msg, WParam, LParam : LongWord ) : Longint;
  59. function PostMessage( Msg, WParam, LParam : LongWord ) : LongBool;
  60.  
  61. // Synchro execute on parallel thread
  62. procedure SyncExecuteParallel( Proc : TNotifyEvent; ParamSender : TObject );
  63. // Asynchro execute on parallel thread
  64. procedure AsyncExecuteParallel( Proc : TNotifyEvent;
  65. ParamSender : TObject );
  66.  
  67. // Synchro execute on main thread
  68. procedure SyncExecuteMain( Proc : TNotifyEvent; ParamSender : TObject );
  69. // Asynchro execute on main thread
  70. procedure AsyncExecuteMain( Proc : TNotifyEvent; ParamSender : TObject );
  71.  
  72. // for compatibility
  73. procedure SyncExecute( Proc : TNotifyEvent; ParamSender : TObject );
  74. procedure AsyncExecute( Proc : TNotifyEvent; ParamSender : TObject );
  75.  
  76. // handle for main thread
  77. property WndHandleMain : LongWord read FWndHandleMain;
  78.  
  79. // handle for parallel thread
  80. property WndHandleParallel : LongWord read FWndHandleParallel;
  81.  
  82. // idle event for parallel thread
  83. property OnIdle : TIdleEvent read FOnIdle write SetOnIdle;
  84.  
  85. property MethodsToExecute : Longint read FMethodsToExecute;
  86.  
  87. property Terminated;
  88. end;
  89.  
  90. implementation
  91.  
  92. { TAxThread }
  93. var
  94. AxThreads : TThreadList;
  95.  
  96. procedure TAxThread.CreateHandleParallel;
  97. begin
  98. FWndHandleParallel := AllocateHWnd( MessageProcedure );
  99. end;
  100.  
  101. procedure TAxThread.MessageProcedure( var Message : TMessage );
  102. begin
  103. Dispatch( message );
  104. end;
  105.  
  106. procedure TAxThread.DestroyHandleParallel;
  107. begin
  108. DeallocateHWnd( FWndHandleParallel );
  109. FWndHandleParallel := ;
  110. end;
  111.  
  112. constructor TAxThread.Create;
  113. begin
  114. // this must by synchonized because of MainThread Context
  115. FMethodsToExecute := ;
  116.  
  117. inherited Create( False );
  118. Synchronize( CreateHandleMain );
  119.  
  120. if AxThreads = nil then
  121. AxThreads := TThreadList.Create;
  122.  
  123. AxThreads.Add( Self );
  124. end;
  125.  
  126. destructor TAxThread.Destroy;
  127. begin
  128. Terminate;
  129. WakeUp;
  130. inherited;
  131. DestroyHandleParallel;
  132. DestroyHandleMain;
  133.  
  134. AxThreads.Remove( Self );
  135. end;
  136.  
  137. procedure TAxThread.AsyncExecuteParallel( Proc : TNotifyEvent;
  138. ParamSender : TObject );
  139. begin
  140. InterlockedIncrement( FMethodsToExecute );
  141. PostMessageParallel( CM_EXECPROC, NotifyEventToPointer( Proc ),
  142. Longint( ParamSender ) );
  143. end;
  144.  
  145. procedure TAxThread.SyncExecuteParallel( Proc : TNotifyEvent;
  146. ParamSender : TObject );
  147. begin
  148. InterlockedIncrement( FMethodsToExecute );
  149. SendMessageParallel( CM_EXECPROC, NotifyEventToPointer( Proc ),
  150. Longint( ParamSender ) );
  151. end;
  152.  
  153. procedure TAxThread.ExecProcedure( var Message : TMessage );
  154. var
  155. PMethod : ^TMethod;
  156. Method : TMethod;
  157. Event : TNotifyEvent absolute Method;
  158. begin
  159. PMethod := Pointer( message.WParam );
  160.  
  161. Method := PMethod^;
  162. Event( TObject( message.LParam ) );
  163.  
  164. Dispose( PMethod );
  165. if FThreadID = GetCurrentThreadId then
  166. InterlockedDecrement( FMethodsToExecute );
  167. end;
  168.  
  169. procedure TAxThread.Execute;
  170. var
  171. Msg : TMsg;
  172. Done : Boolean;
  173. begin
  174. CreateHandleParallel;
  175. FThreadID := GetCurrentThreadId;
  176.  
  177. while not Terminated do
  178. begin
  179. if Done then
  180. begin
  181. FIdleData := nil;
  182. WaitMessage;
  183. end;
  184. while ProcessMessage( Msg ) do { loop };
  185. Idle( FIdleData, Done );
  186. end;
  187. end;
  188.  
  189. procedure TAxThread.CreateHandleMain;
  190. begin
  191. FWndHandleMain := AllocateHWnd( MessageProcedure );
  192. end;
  193.  
  194. procedure TAxThread.DestroyHandleMain;
  195. begin
  196. DeallocateHWnd( FWndHandleMain );
  197. FWndHandleMain := ;
  198. end;
  199.  
  200. procedure TAxThread.AsyncExecuteMain( Proc : TNotifyEvent;
  201. ParamSender : TObject );
  202. begin
  203. PostMessageMain( CM_EXECPROC, NotifyEventToPointer( Proc ),
  204. Longint( ParamSender ) );
  205. end;
  206.  
  207. procedure TAxThread.SyncExecuteMain( Proc : TNotifyEvent;
  208. ParamSender : TObject );
  209. begin
  210. SendMessageMain( CM_EXECPROC, NotifyEventToPointer( Proc ),
  211. Longint( ParamSender ) );
  212. end;
  213.  
  214. function TAxThread.PostMessageMain( Msg, WParam, LParam : LongWord ) : LongBool;
  215. begin
  216. Result := Windows.PostMessage( FWndHandleMain, Msg, WParam, LParam );
  217. end;
  218.  
  219. function TAxThread.PostMessageParallel( Msg, WParam, LParam : LongWord )
  220. : LongBool;
  221. begin
  222. while FWndHandleParallel = do
  223. SwitchToThread;
  224.  
  225. Result := Windows.PostMessage( FWndHandleParallel, Msg, WParam, LParam );
  226. end;
  227.  
  228. function TAxThread.SendMessageMain( Msg, WParam, LParam : LongWord ) : Longint;
  229. begin
  230. Result := Windows.SendMessage( FWndHandleMain, Msg, WParam, LParam );
  231. end;
  232.  
  233. function TAxThread.SendMessageParallel( Msg, WParam, LParam : LongWord )
  234. : Longint;
  235. begin
  236. while FWndHandleParallel = do
  237. SwitchToThread;
  238.  
  239. Result := Windows.SendMessage( FWndHandleParallel, Msg, WParam, LParam );
  240. end;
  241.  
  242. procedure TAxThread.Idle( var Data : TObject; var Done : Boolean );
  243. begin
  244. if Assigned( FOnIdle ) then
  245. FOnIdle( Data, Done )
  246. else
  247. Done := True;
  248. end;
  249.  
  250. function TAxThread.ProcessMessage( var Msg : TMsg ) : Boolean;
  251. begin
  252. Result := False;
  253. if PeekMessage( Msg, , , , PM_REMOVE ) then
  254. begin
  255. Result := True;
  256. if Msg.Message <> WM_QUIT then
  257. begin
  258. TranslateMessage( Msg );
  259. DispatchMessage( Msg );
  260. end
  261. else
  262. Terminate;
  263. end;
  264. end;
  265.  
  266. procedure TAxThread.SetOnIdle( const Value : TIdleEvent );
  267. begin
  268. FOnIdle := Value;
  269. SendMessageParallel( , , );
  270. end;
  271.  
  272. procedure TAxThread.AsyncExecute( Proc : TNotifyEvent; ParamSender : TObject );
  273. begin
  274. AsyncExecuteParallel( Proc, ParamSender );
  275. end;
  276.  
  277. procedure TAxThread.SyncExecute( Proc : TNotifyEvent; ParamSender : TObject );
  278. begin
  279. SyncExecuteParallel( Proc, ParamSender );
  280. end;
  281.  
  282. function TAxThread.PostMessage( Msg, WParam, LParam : LongWord ) : LongBool;
  283. begin
  284. Result := PostMessageParallel( Msg, WParam, LParam );
  285. end;
  286.  
  287. function TAxThread.SendMessage( Msg, WParam, LParam : LongWord ) : Longint;
  288. begin
  289. Result := SendMessageParallel( Msg, WParam, LParam );
  290. end;
  291.  
  292. function TAxThread.NotifyEventToPointer( Proc : TNotifyEvent ) : Longint;
  293. var
  294. Method : TMethod absolute Proc;
  295. PMethod : ^TMethod;
  296. begin
  297. New( PMethod );
  298. PMethod^ := Method;
  299. Result := Longint( PMethod );
  300. end;
  301.  
  302. procedure TAxThread.WakeUp;
  303. begin
  304. PostMessageParallel( , , );
  305. end;
  306.  
  307. class function TAxThread.GetCurrentThread : TAxThread;
  308. var
  309. PomList : TList;
  310. PomIndex : Longint;
  311. ThreadID : Longint;
  312. begin
  313. Result := nil;
  314. if AxThreads = nil then
  315. Exit;
  316.  
  317. ThreadID := GetCurrentThreadId;
  318. PomList := AxThreads.LockList;
  319. try
  320. for PomIndex := to PomList.Count - do
  321. begin
  322. Result := TAxThread( PomList[ PomIndex ] );
  323. if Result.FThreadID = ThreadID then
  324. Break;
  325. Result := nil;
  326. end;
  327. finally
  328. AxThreads.UnlockList;
  329. end;
  330. end;
  331.  
  332. end.

TAxThread - Inter thread message based communication - Delphi的更多相关文章

  1. Thread message loop for a thread with a hidden window? Make AllocateHwnd safe

    Thread message loop for a thread with a hidden window? I have a Delphi 6 application that has a thre ...

  2. WCF学习之旅—WCF中传统的异常处理(十六)

    WCF中的异常处理 在软件开发过程中,不可能没有异常的出现,所以在开发过程中,对不可预知的异常进行解决时,异常处理显得尤为重要.对于一般的.NET系统来说,我们简单地借助try/catch可以很容易地 ...

  3. 【转】《我的WCF之旅》博文系列汇总

    转自:http://www.cnblogs.com/artech/archive/2007/09/15/893838.html WCF是构建和运行互联系统的一系列技术的总称,它是建立在Web Serv ...

  4. REST is not the Best for Micro-Services GRPC and Docker makes a compelling case

    原文:https://hackernoon.com/rest-in-peace-grpc-for-micro-service-and-grpc-for-the-web-a-how-to-908cc05 ...

  5. Four Ways to Create a Thread

    Blaise Pascal Magazine Rerun #5: Four Ways to Create a Thread   This article was originally written ...

  6. Inter-process Communication (IPC)

    For Developers‎ > ‎Design Documents‎ > ‎ Inter-process Communication (IPC) 目录 1 Overview 1.1 I ...

  7. [Delphi] Delphi版本号对照

    VER300    Delphi Seattle / C++Builder Seattle    23    230    (Delphi:Win32/Win64/OSX/iOS32/iOS64/An ...

  8. Android Non-UI to UI Thread Communications(Part 2 of 5)

    Original:http://www.intertech.com/Blog/android-non-ui-to-ui-thread-communications-part-2-of-5/ his i ...

  9. TMsgThread, TCommThread -- 在delphi线程中实现消息循环

    http://delphi.cjcsoft.net//viewthread.php?tid=635 在delphi线程中实现消息循环 在delphi线程中实现消息循环 Delphi的TThread类使 ...

随机推荐

  1. ueditor-百度编辑器插件

    1.官网地址:http://ueditor.baidu.com/website/index.html 2.定制化工具栏:(1)修改ueditor.config.js的toolsbar(2)在创建编辑器 ...

  2. OFBIZ文章

    0. OFBIZ Tutorials 1. A Tour of OFBiz 2. Entities and Services - Data Models and Business Logic in O ...

  3. ORACLE TM锁

    Oracle的TM锁类型 锁模式 锁描述 解释 SQL操作 0 none 1 NULL 空 Select 2 SS(Row-S) 行级共享锁,其他对象只能查询这些数据行 Select for upda ...

  4. C.xml

    pre{ line-height:1; color:#1e1e1e; background-color:#f0f0f0; font-size:16px;}.sysFunc{color:#627cf6; ...

  5. Tomcat启动报错:Failed to initialize end point associated with ProtocolHandler ["http-apr-8080"]

    在用MyEclipse做开发,启动Tomcat的时候,控制台老是报错Failed to initialize end point associated with ProtocolHandler [&q ...

  6. java 开发环境

    jdk:包括jre,自己下载即可. 客户端只需安装jre即可. 安装路径:C:\jdk7.0\jdk1.7.0_25\bin (适时更改) 环境变量是从前往后找 测试成功:cmd      java ...

  7. ios8 下请求读取通讯录权限 (网上众多资料漏下得一个坑)

    读取通讯录权限网上都有,不再叙述. 当第一次授权时用户假如拒绝授权, 第二次就无法再次弹出提示框授权. 刚开始时完全按照网上例子写的,第一次拒绝授权后,在设置里面无法找到对应的更改读取权限的选项. 后 ...

  8. postsharp初体验

    首先,有必要先介绍下,什么叫做AOP(Aspect-Oriented Programming,面向切面编程).下图是百度的词条解释 用图来解释可能更直接了当些: ps:图片来自http://www.c ...

  9. 一个相当好的状态机(DFA, 确定有限状态机)的编码实现,相当简洁漂亮

    从jsoup而来,文章见: https://github.com/code4craft/jsoup-learning/blob/master/blogs/jsoup4.md 状态机 Jsoup的词法分 ...

  10. html5 base64基础

    base64常见的编码形式,二进制文件.图片.视频等     如何弄出来一个base64?     a). FileReader         readAsDataURL();     b). 工具 ...