source: trunk/ab5.0/ablib/src/Classes/System/Threading/Thread.ab@ 597

Last change on this file since 597 was 597, checked in by イグトランス (egtra), 16 years ago

ThreadStartを引数に取るThreadコンストラクタを追加。

File size: 12.0 KB
RevLine 
[400]1'Thread.ab
[1]2
[577]3Namespace System
[495]4
5/*タイプ*/
6TypeDef LocalDataStoreSlot = Long
7
8
[577]9Namespace Threading
[495]10
11/*列挙体*/
[1]12Enum ThreadPriority
[19]13 Highest = 2
14 AboveNormal = 1
15 Normal = 0
16 BelowNormal = -1
17 Lowest = -2
[1]18End Enum
19
[495]20Enum ThreadState
[536]21 'スレッド状態に AbortRequested が含まれ、そのスレッドは停止していますが、状態はまだ Stopped に変わっていません。
[495]22 Aborted
[536]23 'スレッド上で Thread.Abort メソッドを呼び出しますが、そのスレッドの終了を試みる保留中の System.Threading.ThreadAbortException をスレッドが受け取っていません。
[495]24 AbortRequested
[536]25 'スレッドは、フォアグラウンド スレッドではなく、バックグランド スレッドとして実行します。この状態は、Thread.IsBackground プロパティを設定して制御されます。
[495]26 Background
[536]27 'スレッドをブロックせずに起動します。保留中の ThreadAbortException もありません。
[495]28 Running
[536]29 'スレッドを停止します。
[495]30 Stopped
[536]31 'スレッドの停止を要求します。これは、内部でだけ使用します。
[495]32 StopRequested
[536]33 'スレッドを中断します。
[495]34 Suspended
[536]35 'スレッドの中断を要求します。
[495]36 SuspendRequested
[536]37 'スレッド上に Thread.Start メソッドを呼び出しません。
[495]38 Unstarted
[536]39 'スレッドがブロックされています。これは、Thread.Sleep または Thread.Join の呼び出し、ロックの要求 (たとえば、Monitor.Enter や Monitor.Wait の呼び出しによる)、または ManualResetEvent などのスレッド同期オブジェクトの待機の結果である可能性があります。
[495]40 WaitSleepJoin
41End Enum
42
43/*
44デリゲート
45*/
46Delegate Sub ThreadStart()
47
48/*
49関数ポインタ
50*/
[1]51TypeDef PTHREAD_START_ROUTINE = *Function(args As VoidPtr) As DWord
52
[495]53/*
54クラス
55*/
[1]56Class Thread
57 m_hThread As HANDLE
[19]58 m_dwThreadId As DWord
[1]59 m_Priority As ThreadPriority
60
61 m_fp As PTHREAD_START_ROUTINE
[495]62 m_dg As ThreadStart
[1]63 m_args As VoidPtr
[330]64 name As String
[495]65 state As ThreadState
[58]66
[374]67 isThrowing As Boolean
68 throwingParamObject As Object
69
[480]70 needFreeStructurePointers As *VoidPtr
71 countOfNeedFreeStructurePointers As Long
72
[1]73Public
74 Sub Thread()
75 m_hThread=0
[19]76 m_dwThreadId=0
[1]77 m_Priority=ThreadPriority.Normal
78
79 m_fp=0
[330]80
81 name = "sub thread"
[495]82 state = ThreadState.Unstarted
[374]83
84 isThrowing = False
85 throwingParamObject = Nothing
[1]86 End Sub
87 Sub Thread(fp As PTHREAD_START_ROUTINE, args As VoidPtr)
88 m_hThread=0
[19]89 m_dwThreadId=0
[1]90 m_Priority=ThreadPriority.Normal
91
92 m_fp=fp
93 m_args=args
[330]94
95 name = "sub thread"
[495]96 state = ThreadState.Unstarted
[374]97
98 isThrowing = False
99 throwingParamObject = Nothing
[1]100 End Sub
[597]101 Sub Thread(threadStart As ThreadStart)
102 m_hThread=0
103 m_dwThreadId=0
104 m_Priority=ThreadPriority.Normal
[1]105
[597]106 m_fp=AddressOf(threadStartEntry)
107 m_args=ActiveBasic.AllocObjectHandle(threadStart) As VoidPtr
108
109 name = "sub thread"
110 state = ThreadState.Unstarted
111
112 isThrowing = False
113 throwingParamObject = Nothing
114 End Sub
[249]115 Sub Thread(obj As Thread)
[19]116 m_hThread=obj.m_hThread
117 m_dwThreadId=obj.m_dwThreadId
118 m_Priority=obj.m_Priority
119 m_fp=obj.m_fp
120 m_args=obj.m_args
[330]121
122 name = "sub thread"
[495]123 state = ThreadState.Unstarted
[374]124
125 isThrowing = False
126 throwingParamObject = Nothing
[19]127 End Sub
[1]128
[237]129 Sub Thread(hThread As HANDLE, dwThreadId As DWord, dummy As Long)
[19]130 m_hThread=hThread
131 m_dwThreadId=dwThreadId
[330]132
133 name = "sub thread"
[495]134 state = ThreadState.Unstarted
[374]135
136 isThrowing = False
137 throwingParamObject = Nothing
[19]138 End Sub
139
140 Sub ~Thread()
141 End Sub
142
[237]143 Function Equals(thread As Thread) As Boolean
144 Return m_dwThreadId = thread.m_dwThreadId
[19]145 End Function
146
[495]147Public 'public property
[493]148 Function IsAlive() As Boolean
149 Dim code As DWord
150 GetExitCodeThread(m_hThread,code)
151 If code=STILL_ACTIVE Then
152 Return True
153 Else
154 Return False
155 End If
156 End Function
[536]157
[19]158 'Priority Property
[1]159 Sub Priority(value As ThreadPriority)
160 m_Priority=value
[19]161 SetThreadPriority(m_hThread,value)
[1]162 End Sub
163 Function Priority() As ThreadPriority
164 Return m_Priority
165 End Function
166
[19]167 'ThreadId
168 Function ThreadId() As DWord
169 Return m_dwThreadId
170 End Function
[1]171
[495]172 Function ThreadState() As System.Threading.ThreadState
173 Return This.state
174 End Function
175
[330]176 Function Name() As String
177 Return name
178 End Function
179 Sub Name( name As String )
180 This.name = name
181 End Sub
[19]182
[495]183Public 'public method
184/* Sub Abort()
185 TODO '実装のためにはかなり検討が必要
186 'This.__Throw(New ThreadAbortException)
187 End Sub*/
188
[1]189 Sub Start()
[536]190 Dim pfn = AddressOf(_run) As LONG_PTR
[546]191 m_hThread=CreateThread(NULL,0,pfn As LPTHREAD_START_ROUTINE,ObjPtr(This),CREATE_SUSPENDED,m_dwThreadId)
[1]192 SetThreadPriority(m_hThread,m_Priority)
[495]193 This.Resume()
[1]194 End Sub
195
[495]196 Virtual Function Run() As Long
197 If m_fp Then
198 Run=m_fp(m_args)
199 End If
200 End Function
201
202 Sub Suspend()
203 This.state = ThreadState.SuspendRequested
204 If SuspendThread(m_hThread) = &HFFFFFFFF Then
205 This.state = ThreadState.Unstarted
206 Debug 'Throw New ThreadStateException
207 End If
208 This.state = ThreadState.Suspended
209 End Sub
210 Sub Resume()
211 If ResumeThread(m_hThread) = &HFFFFFFFF Then
212 state = ThreadState.Unstarted
213 Debug 'Throw New ThreadStateException
214 End If
215 This.state = ThreadState.Running
216 End Sub
217
218/* Function GetData(LocalDataStoreSlot)
219 End Function
220 Sub SetData(LocalDataStoreSlot)
221 End Sub*/
222
223 Static Function CurrentThread() As Thread
224 Return _System_pobj_AllThreads->CurrentThread()
225 End Function
226
227 /*------------------------ クラス内部用 --------------------------*/
[1]228Private
[536]229 Function _run() As Long
[1]230 '------------
231 ' 前処理
232 '------------
233
[480]234 ' 構造体の一時メモリ退避用領域を作成
235 needFreeStructurePointers = _System_malloc( 1 )
236 countOfNeedFreeStructurePointers = 0
237
[1]238 'GCにスレッド開始を通知
[400]239 _System_pobj_AllThreads->BeginThread(This, _System_GetSp() As *LONG_PTR)
[1]240
241
242 '------------
243 '実行
244 '------------
[19]245 _run=Run()
[1]246
247
248 '------------
249 '後処理
250 '------------
251
252 'GCにスレッド終了を通知
[400]253 _System_pobj_AllThreads->EndThread(This)
[1]254
[480]255 ' 構造体の一時メモリ退避用領域を破棄
256 _System_free( needFreeStructurePointers )
257
[1]258 '自身のスレッドハンドルを閉じる
[493]259 CloseHandle(InterlockedExchangePointer(VarPtr(m_hThread),NULL))
[19]260 m_hThread=0
[1]261
262 End Function
263
[597]264 Static Function threadStartEntry(pThreadStart As VoidPtr) As DWord
265 Dim threadStart = ActiveBasic.ReleaseObjectHandle(pThreadStart As LONG_PTR) As ThreadStart
266 threadStart()
267 End Function
268
[495]269 /*------------------------ システム用 --------------------------*/
[1]270Public
[19]271 Function __GetContext(ByRef Context As CONTEXT) As BOOL
272 Return GetThreadContext(m_hThread,Context)
273 End Function
[58]274 Function __SetContext(ByRef Context As CONTEXT) As BOOL
275 Return SetThreadContext(m_hThread,Context)
276 End Function
[19]277
[374]278 Sub __Throw( ex As Object )
279 isThrowing = True
280 throwingParamObject = ex
281 End Sub
282 Sub __Catched()
283 isThrowing = False
284 throwingParamObject = Nothing
285 End Sub
286 Function __IsThrowing() As Boolean
287 Return isThrowing
288 End Function
289 Function __GetThrowintParamObject() As Object
290 Return throwingParamObject
291 End Function
[19]292
[480]293 Sub __AddNeedFreeTempStructure( structurePointer As VoidPtr )
294 needFreeStructurePointers = _System_realloc( needFreeStructurePointers, ( countOfNeedFreeStructurePointers + 1 ) * SizeOf(VoidPtr) )
295 needFreeStructurePointers[countOfNeedFreeStructurePointers] = structurePointer
296 countOfNeedFreeStructurePointers ++
297 End Sub
[374]298
[480]299 Sub __FreeTempStructure()
300 Dim i = 0 As Long
301 While i<countOfNeedFreeStructurePointers
302 free( needFreeStructurePointers[i] )
303 i++
304 Wend
305 countOfNeedFreeStructurePointers = 0
306 End Sub
[19]307End Class
308
309
[400]310Namespace Detail
311
[58]312'--------------------------------------------------------------------
313' すべてのスレッドの管理
314'--------------------------------------------------------------------
315' TODO: このクラスをシングルトンにする
[400]316
[19]317Class _System_CThreadCollection
318Public
[400]319 collection As *ThreadInfo
[19]320 ThreadNum As Long
321
322 CriticalSection As CRITICAL_SECTION
323
324 Sub _System_CThreadCollection()
[400]325 collection = GC_malloc(1)
326 ThreadNum = 0
[19]327 InitializeCriticalSection(CriticalSection)
[1]328 End Sub
[19]329
330 Sub ~_System_CThreadCollection()
[234]331 Dim i As Long
332 For i=0 To ELM(ThreadNum)
[400]333 With collection[i]
[597]334 If Not ActiveBasic.IsNothing( .thread ) Then
[400]335 .thread = Nothing
336 .stackBase = 0
337 .exception = Nothing
[234]338 End If
[400]339 End With
[234]340 Next
[400]341 collection = 0
[19]342 DeleteCriticalSection(CriticalSection)
343 End Sub
344
345 'スレッドを生成
[400]346 Sub BeginThread(thread As Thread, NowSp As *LONG_PTR)
[19]347 EnterCriticalSection(CriticalSection)
[400]348 Dim i = FindFreeIndex
349 With collection[i]
350 .thread = thread
351 .stackBase = NowSp
352 .exception = New ExceptionService '例外処理管理用オブジェクトを生成
353 End With
[19]354 LeaveCriticalSection(CriticalSection)
355 End Sub
[400]356Private
357 'クリティカルセション内で呼ぶこと
358 Function FindFreeIndex() As Long
359 Dim i As Long
360 For i = 0 To ELM(ThreadNum)
361 If ActiveBasic.IsNothing(collection[i].thread) Then
362 FindFreeIndex = i
363 Exit Function
364 End If
365 Next
366 ThreadNum++
367 collection = realloc(collection, ThreadNum * SizeOf(ThreadInfo))
368 FindFreeIndex = i
369 End Function
370Public
[19]371
372 'スレッドを終了
[400]373 Sub EndThread(thread As Thread)
[19]374 EnterCriticalSection(CriticalSection)
375 Dim i As Long
[400]376 For i = 0 To ELM(ThreadNum)
377 With collection[i]
378 If thread.Equals(.thread) Then
379 .thread = Nothing
380 .stackBase = 0
381 .exception = Nothing
382 Exit For
[148]383 End If
[400]384 End With
[19]385 Next
386 LeaveCriticalSection(CriticalSection)
387 End Sub
388
389 ' すべてのスレッドを中断
390 Sub SuspendAllThread()
391 Dim i As Long
[400]392 For i = 0 To ELM(ThreadNum)
393 With collection[i]
394 If Not ActiveBasic.IsNothing(.thread) Then
395 .thread.Suspend()
396 End If
397 End With
[19]398 Next
399 End Sub
400
401 ' すべてのスレッドを再開
402 Sub ResumeAllThread()
403 Dim i As Long
[400]404 For i = 0 To ELM(ThreadNum)
405 With collection[i]
406 If Not ActiveBasic.IsNothing(.thread) Then
407 .thread.Resume()
408 End If
409 End With
[19]410 Next
411 End Sub
[400]412/*
[148]413 ' 自分以外のスレッドを中断
414 Sub SuspendAnotherThread()
[400]415 Dim currentThread = CurrentThread()
[148]416
417 Dim i As Long
418 For i=0 To ELM(ThreadNum)
[400]419 With collection[i]
420 If currentThread.Equals(.thread) Then
421 Continue
422 ElseIf Not ActiveBasic.IsNothing(.thread) Then
423 .thread.Suspend()
424 End If
425 End With
[148]426 Next
427 End Sub
428
429 ' 自分以外のスレッドを再開
430 Sub ResumeAnotherThread()
[400]431 Dim currentThread = CurrentThread()
[148]432
433 Dim i As Long
434 For i=0 To ELM(ThreadNum)
[400]435 With collection[i]
436 If currentThread.Equals(.thread) Then
437 Continue
438 ElseIf Not ActiveBasic.IsNothing(.thread) Then
439 .thread.Resume()
440 End If
441 End With
[148]442 Next
443 End Sub
[400]444*/
[58]445 'カレントスレッドを取得
[249]446 Function CurrentThread() As Thread
[400]447 Dim p = CurrentThreadInfo()
448 If p = 0 Then
449 ' TODO: エラー処理
450 OutputDebugString( Ex"カレントスレッドの取得に失敗\r\n" )
451 debug
452 Exit Function
453 End If
454 CurrentThread = p->thread
455 End Function
[19]456
[400]457 Function CurrentThreadInfo() As *ThreadInfo
458 CurrentThreadInfo = FindThreadInfo(GetCurrentThreadId())
459 End Function
460
461 Function FindThreadInfo(threadID As DWord) As *ThreadInfo
[19]462 Dim i As Long
[400]463 For i = 0 To ELM(ThreadNum)
464 If collection[i].thread.ThreadId = threadID Then
465 FindThreadInfo = VarPtr(collection[i])
466 Exit Function
[19]467 End If
468 Next
469 End Function
[58]470
471Private
472 '------------------------------------------
473 ' スレッド固有の例外処理制御
474 '------------------------------------------
475
476Public
[400]477 Function GetCurrentException() As ExceptionService
478 Dim dwNowThreadId = GetCurrentThreadId()
[58]479
480 Dim i As Long
481 For i=0 To ELM(ThreadNum)
[400]482 With collection[i]
483 If .thread.ThreadId = dwNowThreadId Then
484 Return .exception
485 End If
486 End With
[58]487 Next
488
[400]489 OutputDebugString( Ex"カレントスレッドの取得に失敗\r\n" )
490 Return Nothing
[58]491 End Function
[1]492End Class
[400]493
494Type ThreadInfo
495 thread As Thread
496 stackBase As *LONG_PTR
497 exception As ExceptionService
498End Type
499
500End Namespace 'Detail
[577]501End Namespace 'Threading
502End Namespace 'System
[480]503
[495]504
505/* システムが使う変数 */
506Dim _System_pobj_AllThreads As *System.Threading.Detail._System_CThreadCollection
507
508/* システムが呼び出す関数 */
[480]509Sub _System_AddNeedFreeTempStructure( structurePointer As VoidPtr )
[495]510 System.Threading.Thread.CurrentThread.__AddNeedFreeTempStructure( structurePointer )
[480]511End Sub
512Sub _System_FreeTempStructure()
[495]513 System.Threading.Thread.CurrentThread.__FreeTempStructure()
[480]514End Sub
Note: See TracBrowser for help on using the repository browser.