Changeset 144 for MicroThreading
- Timestamp:
- Jan 25, 2011, 2:16:25 PM (14 years ago)
- Location:
- MicroThreading
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
MicroThreading/Demo/Demo.lpi
r143 r144 42 42 </Item3> 43 43 </RequiredPackages> 44 <Units Count=" 39">44 <Units Count="44"> 45 45 <Unit0> 46 46 <Filename Value="Demo.lpr"/> … … 50 50 <TopLine Value="1"/> 51 51 <CursorPos X="1" Y="15"/> 52 <UsageCount Value="4 0"/>52 <UsageCount Value="46"/> 53 53 </Unit0> 54 54 <Unit1> … … 60 60 <EditorIndex Value="0"/> 61 61 <WindowIndex Value="0"/> 62 <TopLine Value="1 47"/>63 <CursorPos X="2 9" Y="148"/>64 <UsageCount Value="4 0"/>62 <TopLine Value="182"/> 63 <CursorPos X="28" Y="184"/> 64 <UsageCount Value="46"/> 65 65 <Loaded Value="True"/> 66 66 <LoadedDesigner Value="True"/> … … 70 70 <UnitName Value="UMicroThreading"/> 71 71 <IsVisibleTab Value="True"/> 72 <EditorIndex Value=" 3"/>73 <WindowIndex Value="0"/> 74 <TopLine Value=" 128"/>75 <CursorPos X=" 36" Y="144"/>76 <UsageCount Value="2 1"/>72 <EditorIndex Value="6"/> 73 <WindowIndex Value="0"/> 74 <TopLine Value="337"/> 75 <CursorPos X="17" Y="350"/> 76 <UsageCount Value="25"/> 77 77 <Loaded Value="True"/> 78 78 </Unit2> … … 83 83 <TopLine Value="1310"/> 84 84 <CursorPos X="15" Y="1327"/> 85 <UsageCount Value=" 9"/>85 <UsageCount Value="8"/> 86 86 </Unit3> 87 87 <Unit4> … … 90 90 <TopLine Value="346"/> 91 91 <CursorPos X="24" Y="351"/> 92 <UsageCount Value=" 9"/>92 <UsageCount Value="8"/> 93 93 </Unit4> 94 94 <Unit5> … … 97 97 <TopLine Value="1"/> 98 98 <CursorPos X="1" Y="1"/> 99 <UsageCount Value=" 9"/>99 <UsageCount Value="8"/> 100 100 <DefaultSyntaxHighlighter Value="XML"/> 101 101 </Unit5> … … 106 106 <TopLine Value="286"/> 107 107 <CursorPos X="1" Y="1"/> 108 <UsageCount Value=" 9"/>108 <UsageCount Value="8"/> 109 109 </Unit6> 110 110 <Unit7> … … 114 114 <TopLine Value="8"/> 115 115 <CursorPos X="1" Y="1"/> 116 <UsageCount Value=" 9"/>116 <UsageCount Value="8"/> 117 117 <DefaultSyntaxHighlighter Value="Delphi"/> 118 118 </Unit7> … … 123 123 <TopLine Value="56"/> 124 124 <CursorPos X="24" Y="77"/> 125 <UsageCount Value=" 20"/>125 <UsageCount Value="19"/> 126 126 <DefaultSyntaxHighlighter Value="Delphi"/> 127 127 </Unit8> … … 132 132 <TopLine Value="264"/> 133 133 <CursorPos X="37" Y="141"/> 134 <UsageCount Value=" 20"/>134 <UsageCount Value="19"/> 135 135 <DefaultSyntaxHighlighter Value="Delphi"/> 136 136 </Unit9> … … 141 141 <TopLine Value="302"/> 142 142 <CursorPos X="5" Y="33"/> 143 <UsageCount Value=" 9"/>143 <UsageCount Value="8"/> 144 144 </Unit10> 145 145 <Unit11> … … 148 148 <TopLine Value="886"/> 149 149 <CursorPos X="20" Y="900"/> 150 <UsageCount Value=" 9"/>150 <UsageCount Value="8"/> 151 151 </Unit11> 152 152 <Unit12> … … 155 155 <TopLine Value="1046"/> 156 156 <CursorPos X="34" Y="1053"/> 157 <UsageCount Value="1 8"/>157 <UsageCount Value="17"/> 158 158 </Unit12> 159 159 <Unit13> … … 162 162 <TopLine Value="156"/> 163 163 <CursorPos X="21" Y="175"/> 164 <UsageCount Value=" 9"/>164 <UsageCount Value="8"/> 165 165 </Unit13> 166 166 <Unit14> … … 169 169 <TopLine Value="45"/> 170 170 <CursorPos X="17" Y="62"/> 171 <UsageCount Value=" 9"/>171 <UsageCount Value="8"/> 172 172 </Unit14> 173 173 <Unit15> … … 176 176 <TopLine Value="2271"/> 177 177 <CursorPos X="4" Y="2274"/> 178 <UsageCount Value="1 2"/>178 <UsageCount Value="11"/> 179 179 </Unit15> 180 180 <Unit16> … … 184 184 <TopLine Value="290"/> 185 185 <CursorPos X="36" Y="306"/> 186 <UsageCount Value="2 1"/>186 <UsageCount Value="20"/> 187 187 </Unit16> 188 188 <Unit17> … … 191 191 <TopLine Value="67"/> 192 192 <CursorPos X="10" Y="91"/> 193 <UsageCount Value=" 9"/>193 <UsageCount Value="8"/> 194 194 </Unit17> 195 195 <Unit18> … … 198 198 <TopLine Value="1368"/> 199 199 <CursorPos X="3" Y="1385"/> 200 <UsageCount Value="1 1"/>200 <UsageCount Value="10"/> 201 201 </Unit18> 202 202 <Unit19> … … 205 205 <TopLine Value="861"/> 206 206 <CursorPos X="1" Y="878"/> 207 <UsageCount Value=" 10"/>207 <UsageCount Value="9"/> 208 208 </Unit19> 209 209 <Unit20> … … 212 212 <TopLine Value="32"/> 213 213 <CursorPos X="48" Y="50"/> 214 <UsageCount Value=" 10"/>214 <UsageCount Value="9"/> 215 215 </Unit20> 216 216 <Unit21> … … 219 219 <TopLine Value="8"/> 220 220 <CursorPos X="11" Y="25"/> 221 <UsageCount Value="1 2"/>221 <UsageCount Value="11"/> 222 222 </Unit21> 223 223 <Unit22> … … 227 227 <TopLine Value="1"/> 228 228 <CursorPos X="25" Y="9"/> 229 <UsageCount Value="1 3"/>229 <UsageCount Value="12"/> 230 230 </Unit22> 231 231 <Unit23> 232 232 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/objpas/dateutil.inc"/> 233 <EditorIndex Value="1"/>234 233 <WindowIndex Value="0"/> 235 234 <TopLine Value="38"/> 236 235 <CursorPos X="29" Y="50"/> 237 <UsageCount Value="13"/> 238 <Loaded Value="True"/> 236 <UsageCount Value="16"/> 239 237 </Unit23> 240 238 <Unit24> 241 239 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/objpas/sysutils/datih.inc"/> 242 <EditorIndex Value="2"/>243 240 <WindowIndex Value="0"/> 244 241 <TopLine Value="161"/> 245 242 <CursorPos X="11" Y="184"/> 246 <UsageCount Value="13"/> 247 <Loaded Value="True"/> 243 <UsageCount Value="16"/> 248 244 </Unit24> 249 245 <Unit25> … … 252 248 <TopLine Value="254"/> 253 249 <CursorPos X="12" Y="258"/> 254 <UsageCount Value="1 3"/>250 <UsageCount Value="12"/> 255 251 </Unit25> 256 252 <Unit26> … … 260 256 <TopLine Value="581"/> 261 257 <CursorPos X="11" Y="585"/> 262 <UsageCount Value="1 3"/>258 <UsageCount Value="12"/> 263 259 </Unit26> 264 260 <Unit27> … … 267 263 <TopLine Value="525"/> 268 264 <CursorPos X="11" Y="538"/> 269 <UsageCount Value="1 3"/>265 <UsageCount Value="12"/> 270 266 </Unit27> 271 267 <Unit28> 272 268 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/packages/fcl-base/src/syncobjs.pp"/> 273 269 <UnitName Value="syncobjs"/> 274 <EditorIndex Value="11"/>275 270 <WindowIndex Value="0"/> 276 271 <TopLine Value="57"/> 277 272 <CursorPos X="16" Y="70"/> 278 <UsageCount Value="10"/> 279 <Loaded Value="True"/> 273 <UsageCount Value="13"/> 280 274 </Unit28> 281 275 <Unit29> 282 276 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/inc/threadh.inc"/> 283 <EditorIndex Value="12"/>284 277 <WindowIndex Value="0"/> 285 278 <TopLine Value="18"/> 286 279 <CursorPos X="50" Y="31"/> 287 <UsageCount Value="10"/> 288 <Loaded Value="True"/> 280 <UsageCount Value="13"/> 289 281 </Unit29> 290 282 <Unit30> 291 283 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/inc/thread.inc"/> 292 <EditorIndex Value="14"/>293 284 <WindowIndex Value="0"/> 294 285 <TopLine Value="109"/> 295 286 <CursorPos X="3" Y="112"/> 296 <UsageCount Value="10"/> 297 <Loaded Value="True"/> 287 <UsageCount Value="13"/> 298 288 </Unit30> 299 289 <Unit31> 300 290 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/win/sysosh.inc"/> 301 <EditorIndex Value=" 13"/>291 <EditorIndex Value="3"/> 302 292 <WindowIndex Value="0"/> 303 293 <TopLine Value="12"/> 304 294 <CursorPos X="3" Y="25"/> 305 <UsageCount Value="1 0"/>295 <UsageCount Value="13"/> 306 296 <Loaded Value="True"/> 307 297 </Unit31> 308 298 <Unit32> 309 299 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/objpas/classes/classesh.inc"/> 310 <EditorIndex Value="6"/>311 300 <WindowIndex Value="0"/> 312 301 <TopLine Value="1507"/> 313 302 <CursorPos X="3" Y="1469"/> 314 <UsageCount Value="10"/> 315 <Loaded Value="True"/> 303 <UsageCount Value="13"/> 316 304 </Unit32> 317 305 <Unit33> 318 306 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/win/tthread.inc"/> 319 <EditorIndex Value="8"/>320 307 <WindowIndex Value="0"/> 321 308 <TopLine Value="96"/> 322 309 <CursorPos X="15" Y="98"/> 323 <UsageCount Value="10"/> 324 <Loaded Value="True"/> 310 <UsageCount Value="13"/> 325 311 </Unit33> 326 312 <Unit34> 327 313 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/win/wininc/func.inc"/> 328 <EditorIndex Value="10"/>329 314 <WindowIndex Value="0"/> 330 315 <TopLine Value="130"/> 331 316 <CursorPos X="10" Y="143"/> 332 <UsageCount Value="10"/> 333 <Loaded Value="True"/> 317 <UsageCount Value="13"/> 334 318 </Unit34> 335 319 <Unit35> 336 320 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/win/wininc/defines.inc"/> 337 <EditorIndex Value="9"/>338 321 <WindowIndex Value="0"/> 339 322 <TopLine Value="1923"/> 340 323 <CursorPos X="6" Y="1936"/> 341 <UsageCount Value="10"/> 342 <Loaded Value="True"/> 324 <UsageCount Value="13"/> 343 325 </Unit35> 344 326 <Unit36> 345 327 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/objpas/classes/classes.inc"/> 346 <EditorIndex Value="7"/>347 328 <WindowIndex Value="0"/> 348 329 <TopLine Value="109"/> 349 330 <CursorPos X="6" Y="115"/> 350 <UsageCount Value="10"/> 351 <Loaded Value="True"/> 331 <UsageCount Value="13"/> 352 332 </Unit36> 353 333 <Unit37> 354 334 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/inc/objpash.inc"/> 355 <EditorIndex Value="5"/>356 335 <WindowIndex Value="0"/> 357 336 <TopLine Value="181"/> 358 337 <CursorPos X="21" Y="194"/> 359 <UsageCount Value="10"/> 360 <Loaded Value="True"/> 338 <UsageCount Value="13"/> 361 339 </Unit37> 362 340 <Unit38> 363 341 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/objpas/sysutils/osutilsh.inc"/> 364 <EditorIndex Value="4"/>365 342 <WindowIndex Value="0"/> 366 343 <TopLine Value="14"/> 367 344 <CursorPos X="11" Y="27"/> 345 <UsageCount Value="13"/> 346 </Unit38> 347 <Unit39> 348 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/lcl/include/control.inc"/> 349 <WindowIndex Value="0"/> 350 <TopLine Value="2275"/> 351 <CursorPos X="39" Y="2285"/> 352 <UsageCount Value="12"/> 353 </Unit39> 354 <Unit40> 355 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/inc/systemh.inc"/> 356 <EditorIndex Value="1"/> 357 <WindowIndex Value="0"/> 358 <TopLine Value="492"/> 359 <CursorPos X="3" Y="504"/> 368 360 <UsageCount Value="10"/> 369 361 <Loaded Value="True"/> 370 </Unit38> 362 </Unit40> 363 <Unit41> 364 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/win/syswin.inc"/> 365 <EditorIndex Value="5"/> 366 <WindowIndex Value="0"/> 367 <TopLine Value="197"/> 368 <CursorPos X="30" Y="208"/> 369 <UsageCount Value="10"/> 370 <Loaded Value="True"/> 371 </Unit41> 372 <Unit42> 373 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/inc/system.inc"/> 374 <EditorIndex Value="4"/> 375 <WindowIndex Value="0"/> 376 <TopLine Value="737"/> 377 <CursorPos X="21" Y="747"/> 378 <UsageCount Value="10"/> 379 <Loaded Value="True"/> 380 </Unit42> 381 <Unit43> 382 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/inc/innr.inc"/> 383 <EditorIndex Value="2"/> 384 <WindowIndex Value="0"/> 385 <TopLine Value="96"/> 386 <CursorPos X="1" Y="1"/> 387 <UsageCount Value="10"/> 388 <Loaded Value="True"/> 389 </Unit43> 371 390 </Units> 372 <JumpHistory Count="30" HistoryIndex="2 8">391 <JumpHistory Count="30" HistoryIndex="29"> 373 392 <Position1> 374 393 <Filename Value="../UMicroThreading.pas"/> 375 <Caret Line=" 189" Column="1" TopLine="180"/>394 <Caret Line="322" Column="1" TopLine="315"/> 376 395 </Position1> 377 396 <Position2> 378 397 <Filename Value="../UMicroThreading.pas"/> 379 <Caret Line=" 190" Column="1" TopLine="180"/>398 <Caret Line="328" Column="1" TopLine="315"/> 380 399 </Position2> 381 400 <Position3> 382 401 <Filename Value="../UMicroThreading.pas"/> 383 <Caret Line=" 185" Column="1" TopLine="180"/>402 <Caret Line="363" Column="3" TopLine="350"/> 384 403 </Position3> 385 404 <Position4> 386 405 <Filename Value="../UMicroThreading.pas"/> 387 <Caret Line=" 186" Column="1" TopLine="180"/>406 <Caret Line="322" Column="1" TopLine="309"/> 388 407 </Position4> 389 408 <Position5> 390 409 <Filename Value="../UMicroThreading.pas"/> 391 <Caret Line=" 191" Column="1" TopLine="180"/>410 <Caret Line="326" Column="20" TopLine="309"/> 392 411 </Position5> 393 412 <Position6> 394 413 <Filename Value="../UMicroThreading.pas"/> 395 <Caret Line="1 49" Column="1" TopLine="136"/>414 <Caret Line="169" Column="1" TopLine="156"/> 396 415 </Position6> 397 416 <Position7> 398 417 <Filename Value="../UMicroThreading.pas"/> 399 <Caret Line=" 189" Column="1" TopLine="176"/>418 <Caret Line="363" Column="1" TopLine="350"/> 400 419 </Position7> 401 420 <Position8> 402 421 <Filename Value="../UMicroThreading.pas"/> 403 <Caret Line=" 190" Column="1" TopLine="176"/>422 <Caret Line="322" Column="1" TopLine="309"/> 404 423 </Position8> 405 424 <Position9> 406 425 <Filename Value="../UMicroThreading.pas"/> 407 <Caret Line=" 185" Column="1" TopLine="176"/>426 <Caret Line="330" Column="1" TopLine="309"/> 408 427 </Position9> 409 428 <Position10> 410 429 <Filename Value="../UMicroThreading.pas"/> 411 <Caret Line=" 186" Column="1" TopLine="176"/>430 <Caret Line="316" Column="1" TopLine="309"/> 412 431 </Position10> 413 432 <Position11> 414 433 <Filename Value="../UMicroThreading.pas"/> 415 <Caret Line="1 91" Column="1" TopLine="176"/>434 <Caret Line="169" Column="1" TopLine="156"/> 416 435 </Position11> 417 436 <Position12> 418 437 <Filename Value="../UMicroThreading.pas"/> 419 <Caret Line=" 149" Column="1" TopLine="136"/>438 <Caret Line="316" Column="1" TopLine="303"/> 420 439 </Position12> 421 440 <Position13> 422 441 <Filename Value="../UMicroThreading.pas"/> 423 <Caret Line=" 156" Column="1" TopLine="136"/>442 <Caret Line="330" Column="16" TopLine="317"/> 424 443 </Position13> 425 444 <Position14> 426 445 <Filename Value="../UMicroThreading.pas"/> 427 <Caret Line=" 157" Column="1" TopLine="136"/>446 <Caret Line="363" Column="1" TopLine="350"/> 428 447 </Position14> 429 448 <Position15> 430 <Filename Value=" ../UMicroThreading.pas"/>431 <Caret Line=" 158" Column="1" TopLine="136"/>449 <Filename Value="UMainForm.pas"/> 450 <Caret Line="228" Column="1" TopLine="208"/> 432 451 </Position15> 433 452 <Position16> 434 <Filename Value=" ../UMicroThreading.pas"/>435 <Caret Line=" 189" Column="1" TopLine="176"/>453 <Filename Value="UMainForm.pas"/> 454 <Caret Line="235" Column="1" TopLine="215"/> 436 455 </Position16> 437 456 <Position17> 438 <Filename Value=" ../UMicroThreading.pas"/>439 <Caret Line="1 90" Column="1" TopLine="176"/>457 <Filename Value="UMainForm.pas"/> 458 <Caret Line="184" Column="28" TopLine="182"/> 440 459 </Position17> 441 460 <Position18> 442 <Filename Value="../ UMicroThreading.pas"/>443 <Caret Line=" 409" Column="21" TopLine="387"/>461 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/inc/system.inc"/> 462 <Caret Line="660" Column="22" TopLine="656"/> 444 463 </Position18> 445 464 <Position19> 446 465 <Filename Value="../UMicroThreading.pas"/> 447 <Caret Line=" 206" Column="18" TopLine="201"/>466 <Caret Line="527" Column="78" TopLine="504"/> 448 467 </Position19> 449 468 <Position20> 450 469 <Filename Value="../UMicroThreading.pas"/> 451 <Caret Line=" 21" Column="15" TopLine="7"/>470 <Caret Line="531" Column="51" TopLine="513"/> 452 471 </Position20> 453 472 <Position21> 454 <Filename Value="../ UMicroThreading.pas"/>455 <Caret Line=" 123" Column="50" TopLine="110"/>473 <Filename Value="../../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/win/syswin.inc"/> 474 <Caret Line="208" Column="27" TopLine="194"/> 456 475 </Position21> 457 476 <Position22> 458 477 <Filename Value="../UMicroThreading.pas"/> 459 <Caret Line=" 165" Column="29" TopLine="145"/>478 <Caret Line="531" Column="46" TopLine="522"/> 460 479 </Position22> 461 480 <Position23> 462 481 <Filename Value="../UMicroThreading.pas"/> 463 <Caret Line="1 48" Column="31" TopLine="135"/>482 <Caret Line="161" Column="27" TopLine="158"/> 464 483 </Position23> 465 484 <Position24> 466 485 <Filename Value="../UMicroThreading.pas"/> 467 <Caret Line="1 65" Column="26" TopLine="152"/>486 <Caret Line="195" Column="43" TopLine="180"/> 468 487 </Position24> 469 488 <Position25> 470 489 <Filename Value="../UMicroThreading.pas"/> 471 <Caret Line=" 148" Column="31" TopLine="148"/>490 <Caret Line="211" Column="43" TopLine="198"/> 472 491 </Position25> 473 492 <Position26> 474 493 <Filename Value="../UMicroThreading.pas"/> 475 <Caret Line=" 150" Column="31" TopLine="135"/>494 <Caret Line="241" Column="45" TopLine="226"/> 476 495 </Position26> 477 496 <Position27> 478 497 <Filename Value="../UMicroThreading.pas"/> 479 <Caret Line=" 80" Column="33" TopLine="68"/>498 <Caret Line="542" Column="1" TopLine="524"/> 480 499 </Position27> 481 500 <Position28> 482 501 <Filename Value="../UMicroThreading.pas"/> 483 <Caret Line=" 143" Column="12" TopLine="136"/>502 <Caret Line="538" Column="39" TopLine="525"/> 484 503 </Position28> 485 504 <Position29> 486 505 <Filename Value="../UMicroThreading.pas"/> 487 <Caret Line="1 44" Column="36" TopLine="128"/>506 <Caret Line="181" Column="1" TopLine="155"/> 488 507 </Position29> 489 508 <Position30> 490 <Filename Value="../ ../../../Programy/Lazarus/0.9.31_2.4.3/fpc/2.4.3/source/rtl/objpas/sysutils/osutilsh.inc"/>491 <Caret Line=" 27" Column="11" TopLine="14"/>509 <Filename Value="../UMicroThreading.pas"/> 510 <Caret Line="350" Column="22" TopLine="337"/> 492 511 </Position30> 493 512 </JumpHistory> … … 525 544 <Item3> 526 545 <Source Value="umainform.pas"/> 527 <Line Value=" 58"/>546 <Line Value="62"/> 528 547 </Item3> 529 548 <Item4> -
MicroThreading/Demo/UMainForm.lfm
r142 r144 1 1 object Form1: TForm1 2 Left = 2982 Left = 300 3 3 Height = 510 4 Top = 1 444 Top = 137 5 5 Width = 703 6 6 Caption = 'MicroThreading demo' … … 98 98 end 99 99 object Button4: TButton 100 Left = 1 36100 Left = 120 101 101 Height = 25 102 102 Top = 12 103 Width = 75103 Width = 88 104 104 Caption = 'Start workers' 105 105 OnClick = Button4Click … … 116 116 Value = 20 117 117 end 118 object Button5: TButton 119 Left = 168 120 Height = 25 121 Top = 48 122 Width = 131 123 Caption = 'Get max TThread count' 124 OnClick = Button5Click 125 TabOrder = 7 126 end 127 object Button6: TButton 128 Left = 88 129 Height = 25 130 Top = 48 131 Width = 75 132 Caption = 'Button6' 133 OnClick = Button6Click 134 TabOrder = 8 135 end 118 136 object Timer1: TTimer 119 137 Interval = 100 -
MicroThreading/Demo/UMainForm.pas
r142 r144 24 24 Button3: TButton; 25 25 Button4: TButton; 26 Button5: TButton; 27 Button6: TButton; 26 28 Label1: TLabel; 27 29 Label2: TLabel; … … 34 36 procedure Button3Click(Sender: TObject); 35 37 procedure Button4Click(Sender: TObject); 38 procedure Button5Click(Sender: TObject); 39 procedure Button6Click(Sender: TObject); 36 40 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); 37 41 procedure FormCreate(Sender: TObject); … … 157 161 for I := 0 to SpinEdit1.Value do 158 162 Scheduler.AddMethod(Worker); 163 end; 164 165 procedure TForm1.Button5Click(Sender: TObject); 166 var 167 NewThread: TThread; 168 I: Integer; 169 begin 170 try 171 I := 0; 172 while True do begin 173 NewThread := TThread.Create(True); 174 NewThread.FreeOnTerminate:= False; 175 Inc(I); 176 end; 177 except 178 ShowMessage('Application can create ' + IntToStr(I) +' TThread instances'); 179 end; 180 end; 181 182 procedure TForm1.Button6Click(Sender: TObject); 183 begin 184 ShowMessage(IntToStr(GetThreadID)); 159 185 end; 160 186 -
MicroThreading/UMicroThreading.pas
r143 r144 17 17 TMicroThread = class; 18 18 TMicroThreadScheduler = class; 19 TMicroThreadManager = class; 19 20 20 21 TMicroThreadState = (tsWaiting, tsRunning, tsBlocked, tsSuspended, 21 22 tsSleeping); 22 23 23 24 24 { TMicroThread } … … 27 27 private 28 28 FFreeOnTerminate: Boolean; 29 FStack: Pointer;30 FStackSize: Integer;31 29 FExecutionStartTime: TDateTime; 32 30 FExecutionEndTime: TDateTime; 33 31 FExecutionTime: TDateTime; 32 FStack: Pointer; 34 33 FStackPointer: Pointer; 34 FStackSize: Integer; 35 35 FBasePointer: Pointer; 36 36 FWakeupTime: TDateTime; … … 43 43 Priority: Integer; 44 44 State: TMicroThreadState; 45 Manager: TMicroThreadManager; 45 46 Scheduler: TMicroThreadScheduler; 46 47 procedure Execute; virtual; … … 79 80 TMicroThreadSchedulerPoolThread = class(TThread) 80 81 Scheduler: TMicroThreadScheduler; 82 Manager: TMicroThreadManager; 81 83 procedure Execute; override; 82 84 end; … … 84 86 TThreadPool = class(TObjectList) 85 87 88 end; 89 90 { TMicroThreadManager } 91 92 TMicroThreadManager = class 93 private 94 FStack: Pointer; 95 FStackSize: Pointer; 96 FStackPointer: Pointer; 97 FBasePointer: Pointer; 98 FSelected: TMicroThread; 99 FExecuteCount: Integer; 100 FExecutedCount: Integer; 101 FTerminated: Boolean; 102 FTempPointer: Pointer; 103 function Execute(Count: Integer): Integer; 104 public 105 Scheduler: TMicroThreadScheduler; 106 CurrentMicroThread: TMicroThread; 107 procedure Yield(MicroThread: TMicroThread); 108 constructor Create; 109 destructor Destroy; override; 86 110 end; 87 111 … … 93 117 RoundRobinIndex: Integer; 94 118 LastId: Integer; 95 FMainStackPointer: Pointer;96 FMainBasePointer: Pointer;97 FSelected: TMicroThread;98 FTempPointer: Pointer;99 119 FFrequency: Int64; 100 FExecuteCount: Integer; 101 FExecutedCount: Integer; 120 FThreadPoolSize: Integer; 102 121 FTerminated: Boolean; 103 FThreadPoolSize: Integer;104 122 function GetMicroThreadCount: Integer; 105 123 function GetThreadPoolSize: Integer; 106 124 procedure SetThreadPoolSize(const AValue: Integer); 107 procedure Yield(MicroThread: TMicroThread);125 function GetNextMicroThread: TMicroThread; 108 126 public 127 MainThreadManager: TMicroThreadManager; 109 128 MicroThreads: TObjectList; // TList<TMicroThread> 110 129 Lock: TCriticalSection; 111 CurrentMicroThread: TMicroThread;112 130 function GetNow: TDateTime; 113 131 function Add(MicroThread: TMicroThread): Integer; … … 115 133 constructor Create; 116 134 destructor Destroy; override; 117 function Execute(Count: Integer): Integer;118 135 procedure Start; 119 136 procedure Stop; … … 132 149 implementation 133 150 134 { TMicroThreadSchedulerPoolThread } 135 136 procedure TMicroThreadSchedulerPoolThread.Execute; 137 var 138 ExecutedCount: Integer; 139 begin 140 inherited Execute; 141 try 142 repeat 143 ExecutedCount := Scheduler.Execute(10); 144 if ExecutedCount = 0 then Sleep(1); 145 until Terminated; 146 except 147 on E: Exception do 148 //ExceptionHandler(E); 149 end; 150 end; 151 152 { TMicroThreadMethod } 153 154 procedure TMicroThreadMethod.Execute; 155 begin 156 inherited Execute; 157 Method(Self); 158 end; 159 160 161 { TMicroThread } 162 163 procedure TMicroThread.Execute; 164 begin 165 166 end; 167 168 procedure TMicroThread.Yield; 169 begin 170 Scheduler.Yield(Self); 171 end; 172 173 procedure TMicroThread.WaitFor; 174 begin 175 while not FFinished do begin 176 Sleep(1); 177 end; 178 end; 179 180 procedure TMicroThread.Sleep(Duration: TDateTime); 181 begin 182 FWakeUpTime := Scheduler.GetNow + Duration; 183 State := tsSleeping; 184 Yield; 185 end; 186 187 function TMicroThread.WaitForSignal(Signal: TEvent): TWaitResult; 188 begin 189 repeat 190 Result := Signal.WaitFor(1); 191 Sleep(1); 192 until Result <> wrTimeout; 193 end; 194 195 constructor TMicroThread.Create(CreateSuspended: Boolean; 196 const StackSize: SizeUInt = DefaultStackSize); 197 begin 198 FStackSize := StackSize; 199 FStack := GetMem(FStackSize); 200 FBasePointer := FStack + FStackSize; 201 FStackPointer := FBasePointer - 20; 202 FExecutionTime := 0; 203 FTerminated := False; 204 if CreateSuspended then 205 State := tsSuspended; 206 FFreeOnTerminate := True; 207 end; 208 209 procedure TMicroThread.Terminate; 210 begin 211 FTerminated := True; 212 end; 213 214 destructor TMicroThread.Destroy; 215 begin 216 Terminate; 217 WaitFor; 218 // Microthread is finished, remove it from queue 219 try 220 Scheduler.Lock.Acquire; 221 Scheduler.MicroThreads.Delete(Scheduler.MicroThreads.IndexOf(Self)); 222 finally 223 Scheduler.Lock.Release; 224 end; 225 FreeMem(FStack); 226 inherited Destroy; 227 end; 228 229 procedure TMicroThread.Start; 230 begin 231 State := tsWaiting; 232 end; 233 234 procedure TMicroThread.Stop; 235 begin 236 State := tsSuspended; 237 end; 238 239 240 { TMicroThreadScheduler } 241 242 function TMicroThreadScheduler.GetNow: TDateTime; 243 var 244 {$IFDEF Linux}T: TimeVal;{$ENDIF} 245 {$IFDEF Windows}TimerValue: Int64;{$ENDIF} 246 begin 247 {$IFDEF Windows} 248 QueryPerformanceCounter(TimerValue); 249 //Result := Int64(TimeStampToMSecs(DateTimeToTimeStamp(Now)) * 1000) // an alternative Win32 timebase 250 Result := TimerValue / FFrequency; 251 {$ENDIF} 252 {$IFDEF Linux} 253 fpgettimeofday(@t, nil); 254 // Build a 64 bit microsecond tick from the seconds and microsecond longints 255 Result := (Int64(t.tv_sec) * 1000000) + t.tv_usec; 256 {$ENDIF} 257 258 Result := (Trunc(Now / OneSecond) + Frac(Result)) * OneSecond; 259 end; 260 261 function TMicroThreadScheduler.Add(MicroThread: TMicroThread): Integer; 262 begin 263 Inc(LastId); 264 MicroThread.Scheduler := Self; 265 MicroThread.Id := LastId; 266 Result := MicroThreads.Add(MicroThread); 267 end; 268 269 function TMicroThreadScheduler.AddMethod(Method: TMicroThreadEvent): Integer; 270 var 271 NewMicroThread: TMicroThreadMethod; 272 begin 273 NewMicroThread := TMicroThreadMethod.Create(False); 274 NewMicroThread.Method := Method; 275 NewMicroThread.Scheduler := Self; 276 Result := Add(NewMicroThread); 277 end; 278 279 constructor TMicroThreadScheduler.Create; 280 begin 281 Lock := TCriticalSection.Create; 282 MicroThreads := TObjectList.Create; 283 ThreadPool := TThreadPool.Create; 284 {$IFDEF Windows} 285 QueryPerformanceFrequency(FFrequency); 286 {$ENDIF} 287 RoundRobinIndex := -1; 288 end; 289 290 destructor TMicroThreadScheduler.Destroy; 291 begin 292 FTerminated := True; 293 ThreadPool.Free; 294 MicroThreads.Free; 295 Lock.Free; 296 inherited Destroy; 297 end; 298 299 function TMicroThreadScheduler.Execute(Count: Integer): Integer; 300 begin 151 var 152 StaticManagers: TObjectList; // TList<TMicroThreadManager>; 153 StaticManager: TMicroThreadManager; 154 StaticMicroThread: TMicroThread; 155 156 function GetMicroThreadId: Integer; 157 var 158 I: Integer; 159 CurrentStack: Pointer; 160 begin 161 asm 162 mov CurrentStack, sp 163 end; 164 with MainScheduler do begin 165 try 166 Lock.Acquire; 167 I := 0; 168 while (I < MicroThreads.Count) and 169 not ((CurrentStack >= TMicroThread(MicroThreads[I]).FStack) and 170 (CurrentStack <= (TMicroThread(MicroThreads[I]).FStack + 171 TMicroThread(MicroThreads[I]).FStackSize))) do Inc(I); 172 if I < MicroThreads.Count then begin 173 Result := TMicroThread(MicroThreads[I]).Id; 174 end else Result := -1; 175 finally 176 Lock.Release; 177 end; 178 end; 179 end; 180 181 { TMicroThreadManager } 182 183 function TMicroThreadManager.Execute(Count: Integer): Integer; 184 begin 185 FStack := StackBottom; 186 FStackSize := StackBottom + StackLength; 301 187 FExecuteCount := Count; 302 188 FExecutedCount := 0; … … 305 191 end; 306 192 307 procedure TMicroThreadScheduler.Start; 308 var 309 Executed: Integer; 310 begin 311 FTerminated := False; 312 repeat 313 Executed := Execute(10); 314 Application.ProcessMessages; 315 if Executed = 0 then Sleep(1); 316 until FTerminated; 317 end; 318 319 procedure TMicroThreadScheduler.Stop; 320 begin 321 FTerminated := True; 322 end; 323 324 var 325 StaticMicroThread: TMicroThread; 326 StaticScheduler: TMicroThreadScheduler; 327 328 procedure TMicroThreadScheduler.Yield(MicroThread: TMicroThread); 193 procedure TMicroThreadManager.Yield(MicroThread: TMicroThread); 329 194 var 330 195 I: Integer; 331 196 Time: TDateTime; 332 197 begin 333 Time := GetNow;198 Time := Scheduler.GetNow; 334 199 if Assigned(MicroThread) then begin 200 MicroThread.Manager := nil; 335 201 MicroThread.FExecutionEndTime := Time; 336 202 MicroThread.FExecutionTime := MicroThread.FExecutionTime + … … 346 212 mov [eax].TMicroThread.FBasePointer, edx 347 213 end; 348 Static Scheduler := MicroThread.Scheduler;214 StaticManager := MicroThread.Manager; 349 215 asm 350 216 // Restore scheduler stack 351 mov eax, Static Scheduler // Self is invalid before BP restore352 mov edx, [eax].TMicroThread Scheduler.FMainStackPointer217 mov eax, StaticManager // Self is invalid before BP restore 218 mov edx, [eax].TMicroThreadManager.FStackPointer 353 219 mov esp, edx 354 mov edx, [eax].TMicroThread Scheduler.FMainBasePointer220 mov edx, [eax].TMicroThreadManager.FBasePointer 355 221 mov ebp, edx 356 222 end; … … 358 224 end; 359 225 360 // Try to find new microthread for execution 361 FSelected := nil; 226 FSelected := Scheduler.GetNextMicroThread; 227 228 if Assigned(FSelected) and (FExecutedCount < FExecuteCount) then begin 229 FSelected.Manager := Self; 230 Inc(FExecutedCount); 231 CurrentMicroThread := FSelected; 232 asm 233 // Store scheduler stack 234 mov eax, Self 235 mov edx, esp 236 mov [eax].TMicroThreadManager.FStackPointer, edx 237 mov edx, ebp 238 mov [eax].TMicroThreadManager.FBasePointer, edx 239 end; 240 if not FSelected.FExecuted then begin 241 FSelected.FExecuted := True; 242 FSelected.State := tsRunning; 243 FSelected.FExecutionStartTime := Time; 244 FTempPointer := FSelected.FStackPointer; 245 asm 246 // Restore microthread stack 247 mov eax, Self 248 mov edx, [eax].TMicroThreadManager.FTempPointer 249 mov esp, edx 250 end; 251 StaticMicroThread := FSelected; // BP will be change and Self pointer will be invalid 252 FTempPointer := FSelected.FBasePointer; 253 asm 254 mov eax, Self 255 mov edx, [eax].TMicroThreadManager.FTempPointer 256 mov ebp, edx 257 end; 258 StaticMicroThread.Execute; 259 //FSelected.Method(FSelected); 260 StaticManager := StaticMicroThread.Manager; 261 asm 262 // Restore scheduler stack 263 mov eax, StaticManager // Self is invalid before BP restore 264 mov edx, [eax].TMicroThreadManager.FStackPointer 265 mov esp, edx 266 mov edx, [eax].TMicroThreadManager.FBasePointer 267 mov ebp, edx 268 end; 269 FSelected.Manager := nil; 270 FSelected.FExecutionEndTime := Time; 271 FSelected.FExecutionTime := FSelected.FExecutionTime + 272 (FSelected.FExecutionEndTime - FSelected.FExecutionStartTime); 273 FSelected.FFinished := True; 274 if FSelected.FFreeOnTerminate then begin 275 FSelected.Free; 276 end;; 277 end else 278 if FSelected.State = tsWaiting then begin 279 // Execute selected thread 280 FSelected.State := tsRunning; 281 FSelected.FExecutionStartTime := Time; 282 FTempPointer := FSelected.FStackPointer; 283 asm 284 // Restore microthread stack 285 mov eax, Self 286 mov edx, [eax].TMicroThreadManager.FTempPointer 287 mov esp, edx 288 end; 289 FTempPointer := FSelected.FBasePointer; 290 asm 291 mov eax, Self 292 mov edx, [eax].TMicroThreadManager.FTempPointer 293 mov ebp, edx 294 end; 295 end; 296 end; 297 end; 298 299 constructor TMicroThreadManager.Create; 300 begin 301 302 end; 303 304 destructor TMicroThreadManager.Destroy; 305 begin 306 inherited Destroy; 307 end; 308 309 { TMicroThreadSchedulerPoolThread } 310 311 procedure TMicroThreadSchedulerPoolThread.Execute; 312 var 313 ExecutedCount: Integer; 314 begin 315 inherited Execute; 316 try 317 repeat 318 ExecutedCount := Manager.Execute(10); 319 if ExecutedCount = 0 then Sleep(1); 320 until Terminated; 321 except 322 on E: Exception do 323 //ExceptionHandler(E); 324 end; 325 end; 326 327 { TMicroThreadMethod } 328 329 procedure TMicroThreadMethod.Execute; 330 begin 331 inherited Execute; 332 Method(Self); 333 end; 334 335 336 { TMicroThread } 337 338 procedure TMicroThread.Execute; 339 begin 340 341 end; 342 343 procedure TMicroThread.Yield; 344 begin 345 Manager.Yield(Self); 346 end; 347 348 procedure TMicroThread.WaitFor; 349 begin 350 if GetMicroThreadId <> -1 then 351 while not FFinished do begin 352 Sleep(1); 353 end; 354 end; 355 356 procedure TMicroThread.Sleep(Duration: TDateTime); 357 begin 358 FWakeUpTime := Scheduler.GetNow + Duration; 359 State := tsSleeping; 360 Yield; 361 end; 362 363 function TMicroThread.WaitForSignal(Signal: TEvent): TWaitResult; 364 begin 365 repeat 366 Result := Signal.WaitFor(1); 367 Sleep(1); 368 until Result <> wrTimeout; 369 end; 370 371 constructor TMicroThread.Create(CreateSuspended: Boolean; 372 const StackSize: SizeUInt = DefaultStackSize); 373 begin 374 FStackSize := StackSize; 375 FStack := GetMem(FStackSize); 376 FBasePointer := FStack + FStackSize; 377 FStackPointer := FBasePointer - 20; 378 FExecutionTime := 0; 379 FTerminated := False; 380 if CreateSuspended then 381 State := tsSuspended; 382 FFreeOnTerminate := True; 383 end; 384 385 procedure TMicroThread.Terminate; 386 begin 387 FTerminated := True; 388 end; 389 390 destructor TMicroThread.Destroy; 391 begin 392 Terminate; 393 WaitFor; 394 // Microthread is finished, remove it from queue 395 try 396 Manager.Scheduler.Lock.Acquire; 397 Manager.Scheduler.MicroThreads.Delete(Manager.Scheduler.MicroThreads.IndexOf(Self)); 398 finally 399 Manager.Scheduler.Lock.Release; 400 end; 401 FreeMem(FStack); 402 inherited Destroy; 403 end; 404 405 procedure TMicroThread.Start; 406 begin 407 State := tsWaiting; 408 end; 409 410 procedure TMicroThread.Stop; 411 begin 412 State := tsSuspended; 413 end; 414 415 416 { TMicroThreadScheduler } 417 418 function TMicroThreadScheduler.GetNow: TDateTime; 419 var 420 {$IFDEF Linux}T: TimeVal;{$ENDIF} 421 {$IFDEF Windows}TimerValue: Int64;{$ENDIF} 422 begin 423 {$IFDEF Windows} 424 QueryPerformanceCounter(TimerValue); 425 //Result := Int64(TimeStampToMSecs(DateTimeToTimeStamp(Now)) * 1000) // an alternative Win32 timebase 426 Result := TimerValue / FFrequency; 427 {$ENDIF} 428 429 {$IFDEF Linux} 430 fpgettimeofday(@t, nil); 431 // Build a 64 bit microsecond tick from the seconds and microsecond longints 432 Result := (Int64(t.tv_sec) * 1000000) + t.tv_usec; 433 {$ENDIF} 434 435 Result := (Trunc(Now / OneSecond) + Frac(Result)) * OneSecond; 436 end; 437 438 function TMicroThreadScheduler.Add(MicroThread: TMicroThread): Integer; 439 begin 440 Inc(LastId); 441 MicroThread.Scheduler := Self; 442 MicroThread.Id := LastId; 443 Result := MicroThreads.Add(MicroThread); 444 end; 445 446 function TMicroThreadScheduler.AddMethod(Method: TMicroThreadEvent): Integer; 447 var 448 NewMicroThread: TMicroThreadMethod; 449 begin 450 NewMicroThread := TMicroThreadMethod.Create(False); 451 NewMicroThread.Method := Method; 452 NewMicroThread.Scheduler := Self; 453 Result := Add(NewMicroThread); 454 end; 455 456 constructor TMicroThreadScheduler.Create; 457 begin 458 Lock := TCriticalSection.Create; 459 MicroThreads := TObjectList.Create; 460 ThreadPool := TThreadPool.Create; 461 {$IFDEF Windows} 462 QueryPerformanceFrequency(FFrequency); 463 {$ENDIF} 464 RoundRobinIndex := -1; 465 MainThreadManager := TMicroThreadManager.Create; 466 MainThreadManager.Scheduler := Self; 467 end; 468 469 destructor TMicroThreadScheduler.Destroy; 470 begin 471 MainThreadManager.Free; 472 FTerminated := True; 473 ThreadPool.Free; 474 MicroThreads.Free; 475 Lock.Free; 476 inherited Destroy; 477 end; 478 479 procedure TMicroThreadScheduler.Start; 480 var 481 Executed: Integer; 482 begin 483 FTerminated := False; 484 repeat 485 Executed := MainThreadManager.Execute(10); 486 Application.ProcessMessages; 487 if Executed = 0 then Sleep(1); 488 until FTerminated; 489 end; 490 491 procedure TMicroThreadScheduler.Stop; 492 begin 493 FTerminated := True; 494 end; 495 496 function TMicroThreadScheduler.GetNextMicroThread: TMicroThread; 497 var 498 I: Integer; 499 begin 500 Result := nil; 362 501 try 363 502 Lock.Acquire; … … 381 520 end; 382 521 if I < MicroThreads.Count then begin 383 FSelected:= TMicroThread(MicroThreads[RoundRobinIndex]);522 Result := TMicroThread(MicroThreads[RoundRobinIndex]); 384 523 end; 385 524 finally 386 525 Lock.Release; 387 end;388 389 if Assigned(FSelected) and (FExecutedCount < FExecuteCount) then begin390 Inc(FExecutedCount);391 CurrentMicroThread := FSelected;392 asm393 // Store scheduler stack394 mov eax, Self395 mov edx, esp396 mov [eax].TMicroThreadScheduler.FMainStackPointer, edx397 mov edx, ebp398 mov [eax].TMicroThreadScheduler.FMainBasePointer, edx399 end;400 if not FSelected.FExecuted then begin401 FSelected.FExecuted := True;402 FSelected.State := tsRunning;403 FSelected.FExecutionStartTime := Time;404 FTempPointer := FSelected.FStackPointer;405 asm406 // Restore microthread stack407 mov eax, Self408 mov edx, [eax].TMicroThreadScheduler.FTempPointer409 mov esp, edx410 end;411 StaticMicroThread := FSelected; // BP will be change and Self pointer will be invalid412 FTempPointer := FSelected.FBasePointer;413 asm414 mov eax, Self415 mov edx, [eax].TMicroThreadScheduler.FTempPointer416 mov ebp, edx417 end;418 StaticMicroThread.Execute;419 //FSelected.Method(FSelected);420 StaticScheduler := StaticMicroThread.Scheduler;421 asm422 // Restore scheduler stack423 mov eax, StaticScheduler // Self is invalid before BP restore424 mov edx, [eax].TMicroThreadScheduler.FMainStackPointer425 mov esp, edx426 mov edx, [eax].TMicroThreadScheduler.FMainBasePointer427 mov ebp, edx428 end;429 FSelected.FExecutionEndTime := Time;430 FSelected.FExecutionTime := FSelected.FExecutionTime +431 (FSelected.FExecutionEndTime - FSelected.FExecutionStartTime);432 FSelected.FFinished := True;433 if FSelected.FFreeOnTerminate then begin434 FSelected.Free;435 end;;436 end else437 if FSelected.State = tsWaiting then begin438 // Execute selected thread439 FSelected.State := tsRunning;440 FSelected.FExecutionStartTime := Time;441 FTempPointer := FSelected.FStackPointer;442 asm443 // Restore microthread stack444 mov eax, Self445 mov edx, [eax].TMicroThreadScheduler.FTempPointer446 mov esp, edx447 end;448 FTempPointer := FSelected.FBasePointer;449 asm450 mov eax, Self451 mov edx, [eax].TMicroThreadScheduler.FTempPointer452 mov ebp, edx453 end;454 end;455 526 end; 456 527 end; … … 478 549 initialization 479 550 551 StaticManagers := TObjectList.Create; 480 552 MainScheduler := TMicroThreadScheduler.Create; 481 553 … … 483 555 484 556 MainScheduler.Free; 557 StaticManagers.Free; 485 558 486 559 end.
Note:
See TracChangeset
for help on using the changeset viewer.