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[email protected]
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.
function TAxThread.NotifyEventToPointer ( Proc : TNotifyEvent ) : Longint;
var
Method : TMethod absolute Proc;
PMethod : ^TMethod;
begin
New( PMethod );
PMethod^ : = Method;
Result : = Longint( PMethod );
end ;
procedure TAxThread.AsyncExecuteParallel ( Proc : TNotifyEvent; ParamSender : TObject );
begin
InterlockedIncrement( FMethodsToExecute );
PostMessageParallel( CM_EXECPROC_WORK_TRHREAD, NotifyEventToPointer ( Proc ), Longint( ParamSender ) );
end ;
procedure TAxThread.ExecProcedure ( var Message : TMessage );
var
PMethod : ^TMethod;
Method : TMethod;
Event : TNotifyEvent absolute Method;
begin
PMethod : = Pointer( message .WParam );
Method : = PMethod^;
Event( TObject( message .LParam ) );Dispose( PMethod ); if FThreadID = GetCurrentThreadId then
InterlockedDecrement( FMethodsToExecute );
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;
procedure TAxThread.Execute;
var
Msg : TMsg;
Done : Boolean;
begin
CreateHandleParallel;
FThreadID : = GetCurrentThreadId;
while not Terminated do
begin
if Done then
begin
FIdleData : = nil ;
WaitMessage;
end ;
while ProcessMessage( Msg ) do { loop } ;
Idle( FIdleData, Done );
end ;
end ;
At first the class has to create handle (CreateHandleParallel).
Loop while waits for messages and handles incomming messages (ProcessMessage ).
function TAxThread.ProcessMessage ( var Msg : TMsg ) : Boolean;
begin
Result : = False;
if PeekMessage( Msg, 0 , 0 , 0 , PM_REMOVE ) then begin
Result : = True;
if Msg.Message <> WM_QUIT then
begin
TranslateMessage( Msg );
DispatchMessage( Msg );
end
else
Terminate;
end ;
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.
// Asynchro execute on parallel thread
procedure TAxThread.AsyncExecuteParallel( Proc : TNotifyEvent;
ParamSender : TObject );
begin
InterlockedIncrement( FMethodsToExecute );
PostMessageParallel( CM_EXECPROC, NotifyEventToPointer( Proc ),
Longint( ParamSender ) );
end ;
// Synchro execute on parallel thread
procedure TAxThread.SyncExecuteParallel( Proc : TNotifyEvent;
ParamSender : TObject );
begin
InterlockedIncrement( FMethodsToExecute );
SendMessageParallel( CM_EXECPROC, NotifyEventToPointer( Proc ),
Longint( ParamSender ) );
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
type
TMainForm = class ( TForm )
btnRandomize : TButton;
imgResult : TImage;
pbProgress : TProgressBar;
btnMulti : TButton;
procedure FormCreate( Sender : TObject );
procedure FormDestroy( Sender : TObject );
procedure btnRandomizeClick( Sender : TObject );
procedure btnMultiClick( Sender : TObject );
private
{ Private declarations }
FExecutingThread : TAxThread;
public
{ Public declarations }
procedure RandomizeBMP( Data : TObject );
procedure DoUpdate( Data : TObject );
procedure Progress( Data : TObject );
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).
procedure TMainForm.btnRandomizeClick( Sender : TObject );
var
PomBMP : TBitmap;
begin
if FExecutingThread = nil then
FExecutingThread : = TAxThread.Create;
PomBMP : = TBitmap.Create;
PomBMP.Width : = 200 ;
PomBMP.Height : = 200 ;
PomBMP.PixelFormat : = pf24bit;
FExecutingThread.AsyncExecuteParallel ( RandomizeBMP , PomBMP );
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 .
procedure TMainForm.RandomizeBMP( Data : TObject );
var
CurrentThread : TAxThread;
PomBMP : TBitmap;
I : Longint;
X : Longint;
Y : Longint;
Color : Longint;
begin
if not ( Data is TBitmap ) then
Exit;
PomBMP : = Data as TBitmap;
CurrentThread : = TAxThread.GetCurrentThread;
I : = 0 ;
try
PomBMP.Canvas.Lock;
while not CurrentThread.Terminated do
begin
Inc( I );
if I > MaxPoints then
Break;
X : = Random( 200 );
Y : = Random( 200 );
Color : = Random( 256 ) * 256 * 256 + Random( 256 ) * 256 + Random( 256 );
if ( I mod ( MaxPoints div 100 ) ) = 0 then
CurrentThread.SyncExecuteMain ( Progress, TObject( I ) );
// slow for demonstration
PomBMP.Canvas.Pixels[ X, Y ] : = Color;
end ;
finally
PomBMP.Canvas.Unlock;
CurrentThread.AsyncExecuteMain ( DoUpdate, PomBMP );
end ;
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 := 0 ;
110 end ;
111
112 constructor TAxThread.Create;
113 begin
114 // this must by synchonized because of MainThread Context
115 FMethodsToExecute := 0 ;
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 := 0 ;
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 = 0 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 = 0 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, 0 , 0 , 0 , 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( 0 , 0 , 0 );
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( 0 , 0 , 0 );
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 := 0 to PomList.Count - 1 do
321 begin
322 Result := TAxThread( PomList[ PomIndex ] );
323
六六分期app的软件客服如何联系?不知道吗?加qq群【895510560】即可!标题:六六分期
阅读:19234| 2023-10-27
今天小编告诉大家如何处理win10系统火狐flash插件总是崩溃的问题,可能很多用户都不知
阅读:10000| 2022-11-06
今天小编告诉大家如何对win10系统删除桌面回收站图标进行设置,可能很多用户都不知道
阅读:8331| 2022-11-06
今天小编告诉大家如何对win10系统电脑设置节能降温的设置方法,想必大家都遇到过需要
阅读:8701| 2022-11-06
我们在使用xp系统的过程中,经常需要对xp系统无线网络安装向导设置进行设置,可能很多
阅读:8646| 2022-11-06
今天小编告诉大家如何处理win7系统玩cf老是与主机连接不稳定的问题,可能很多用户都不
阅读:9668| 2022-11-06
电脑对日常生活的重要性小编就不多说了,可是一旦碰到win7系统设置cf烟雾头的问题,很
阅读:8632| 2022-11-06
我们在日常使用电脑的时候,有的小伙伴们可能在打开应用的时候会遇见提示应用程序无法
阅读:8005| 2022-11-06
今天小编告诉大家如何对win7系统打开vcf文件进行设置,可能很多用户都不知道怎么对win
阅读:8666| 2022-11-06
今天小编告诉大家如何对win10系统s4开启USB调试模式进行设置,可能很多用户都不知道怎
阅读:7540| 2022-11-06
请发表评论