multithreading - Delphi: Should a thread ever be created "not suspended"? -


i've been trying track down memory leak in jedi vcl's jvhidcontrollerclass.pas, came across change in source history:

older revision:

constructor tjvhiddevicereadthread.ctlcreate(const dev: tjvhiddevice); begin   inherited create(true);   device := dev;   numbytesread := 0;   setlength(report, dev.caps.inputreportbytelength); end; 

current revision:

constructor tjvhiddevicereadthread.ctlcreate(const dev: tjvhiddevice); begin   inherited create(false);   device := dev;   numbytesread := 0;   setlength(report, dev.caps.inputreportbytelength); end; 

from experience, i've discovered if create thread not suspended:

inherited create(false); 

then thread starts running. in case attempt access object has not been initialized yet:

procedure tjvhiddevicereadthread.execute; begin    while not terminated    begin      fillchar(report[0], device.caps.inputreportbytelength, #0);      if device.readfileex(report[0], device.caps.inputreportbytelength, @dummyreadcompletion) 

right away trying fill report, , access object device. problem haven't been initialized yet; next lines after thread has started:

  device := dev;   numbytesread := 0;   setlength(report, dev.caps.inputreportbytelength); 

i realize race condition; , chances of user experiencing crash in production pretty low, it's harmless leave race-crash.

but way off? missing something? calling:

beginthread(nil, 0, @threadproc, pointer(self), flags, fthreadid); 

not start thread off , running right away? race condition regression (intentionally) added jvcl? there secret

createsuspended(false); 

that makes correct code over:

createsuspended(true); ... fdatathread.resume; 

?

after having been burned mistakenly calling

tmythread.create(false) 

i've filed in brain never correct. there valid use letting thread start right away (when have initialize values)?

this basic design flaw delphi 5 implementation of tthread. underlying windows thread started in constructor of tthread. leads race describe.

in delphi 6 version of rtl, thread start mechanism changed. delphi 6 onwards, thread started in tthread.afterconstruction. , runs after constructor completes. render code race free.

in delphi 6 , later, underlying windows thread created in tthread constructor, created suspended using create_suspended flag. in afterconstruction, long tthread.fcreatesuspended false, thread resumed.

one way work around issue in delphi 5 call inherited constructor last. this:

constructor tjvhiddevicereadthread.ctlcreate(const dev: tjvhiddevice); begin   device := dev;   numbytesread := 0;   setlength(report, dev.caps.inputreportbytelength);   inherited create(false); end; 

rather ugly know.

so, approach of creating thread suspended , resuming once constructor has completed better. approach mirrors how rtl solves problem in delphi 6 , up.


Comments