General problem:
- When Threadcall involves to pass parameters to the thread, there is no guarentee that the corresponding data are still maintained after the end of the Threadcall statement and this until the thread is launched.
- In particular, object copies (as strings) must not be destructed before the thread is launched (for these, the fault may be more obvious than data that still may remain in memory even released).
- That may cause bad behavior.
A faults example for several passing types:
Dim Shared As Any Ptr m m = Mutexcreate() Dim As Any Ptr p(19) Dim As Integer K Sub threadByVal (Byval I As Integer) Mutexlock(m) Print @I, Str(I) Mutexunlock(m) End Sub Sub threadByRef (Byref I As Integer) Mutexlock(m) Print @I, Str(I) Mutexunlock(m) End Sub Print "Adress", "Data value" Print For I As Integer = 0 To 9 p(I) = Threadcall threadByVal(I) Next I For I As Integer = 0 To 9 Threadwait(p(I)) Next I Print For K = 10 To 19 p(K) = Threadcall threadByRef(K) Next K For I As Integer = 10 To 19 Threadwait(p(I)) Next I Mutexdestroy(m) Sleep
Output:
Adress Data value 10485420 1 11533996 3 13631148 4 15728300 7 16776876 1 18874028 1 12582572 1 14679724 2 10485420 2 17825452 2 1244800 13 1244800 18 1244800 20 1244800 20 11 Appuyez sur une touche pour continuer...
First part of example with parameter passed by value:
- The data should be correctly incremented from 0 to 9 because a copy of each iterator data is passed by value.
Second part of example with parameter passed by reference:
- The fault is not the rapid incrementation of the displayed data of the iterator because it is passed by reference (there is no temporary variables involved by ThreadCall) and each value is not frozen until the thread is launched.
- But the address of the reference should be maintained until the thread is launched, instead of, a wrong address value is passed to the thread ('11' instead of '1244800' in the above example), then the program crashes when it tries to access it.
Referring at forum, from the post:
http://www.freebasic.net/forum/viewtopic.php?p=205239#p205239
Rewording of the analysis above:
First part of example with parameter passed by value:
- The data should be
correctly incremented from 0 to 9equi-distributed (not necessarily in the order) between 0 and 9 because a copy of each iterator data is passed by value.Another malfunction with respect to the below extract of the ThreadCall documentation:
In fact, ThreadCall also refuses the subroutines with arguments like described above:
- unions
- user types containing unions, arrays, strings, or bitfields
but even if they are passed Byref !
error 287: Unsupported function in 'Dim As Any Ptr p = Threadcall thread(u)'
For now, a workaround is to pass pointers Byval.