Using 'ThreadCall':
The using of a pointer (as passed parameter) is more robust but not 100% safe.
Indeed, the allocated memory may be freed before the thread launch:
- if the passed parameter is an object with destructor (like a string for example), the effect is immediate because object being destroyed before the memory deallocation, then the argument value to be passed is broken.
- if the passed parameter is not an object (like a numeric value for example), the allocated memory is not cleared before deallocation, then the argument value to be passed is broken only if the freed memory is reallocated and reassigned in the meantime for other thing.
Using 'ThreadCreate':
Now that you have modified your code to pass a pointer as only argument, there is not much work left to replace 'ThreadCall' by 'ThreadCreate' which is 100% safe:
Code: Select all
#Include Once "windows.bi"
#Inclib "bcrypt"
#Include Once "win/wincrypt.bi"
#Inclib "crypt32"
Type Params
As LPCWSTR HashAlg
As PUCHAR ulData
As Ulong ulDatalen
As Long Final
As String sHash
End Type
Sub Hash( Byval p As Any Ptr )
Dim ptrParams As Params Ptr = p
Static As Byte Ptr phalg, phhash
Dim sBinary As String
Dim sHex As String
Dim nLength As Long
' Initialize section
If phhash = 0 Then ' will be the Case On, And perhaps only, first pass
BcryptOpenAlgorithmprovider @phalg, ptrParams->HashAlg, 0, 0 ' we want phalg
BcryptCreatehash phalg, @phhash, null, 0, 0, 0, 0 ' we want phhash
End If
' update section
BcryptHashData( phhash, Cast( PUCHAR, ptrParams->ulData ), ptrParams->ulDataLen, 0 )
' Finalization section
If ptrParams->Final = true Then ' finalize hash
Dim As Ulong lHashLength
Dim As Ulong lResult
Dim sBinHash As String
BcryptGetProperty phalg, BCRYPT_HASH_LENGTH, Cast( Puchar, @lHashLength ), 4, @lResult, 0
sBinHash = String( lHashLength, 0 )
BcryptFinishHash phhash, Strptr( sBinHash ), lHashLength, 0
BcryptDestroyHash phhash
BcryptCloseAlgorithmprovider phalg, 0
phhash = 0
nLength = Len(sBinHash)*2 + 1 ' + 1 To accomodate a null terminator
sHex = Space( nLength )
CryptBinaryToStringa Strptr(sBinHash), Len(sBinHash), CRYPT_STRING_HEXRAW + CRYPT_STRING_NOCRLF, _
Strptr(sHex), @nLength ' at msdn nlength 'Out' Is Len(sBinHash) * 2, so
ptrParams->sHash = Ucase( Left( sHex, nLength ) )
End If
End Sub
Dim As String s = "FreeBASIC"
Dim As Params ArgList
ArgList.hashalg = @Wstr("SHA256")
ArgList.ulData = Strptr(s)
ArgList.ulDataLen = Len(s)
ArgList.final = True
Dim stoe As Any Ptr = ThreadCreate( @Hash, @ArgList )
ThreadWait stoe
Print ArgList.sHash
Sleep
Code: Select all
Type Params
As String id
As Any Ptr tlock
As Integer count
End Type
Sub thread( Byval p As Any Ptr )
Dim ptrParams As Params Ptr = p
For i As Integer = 1 To ptrParams->count
Mutexlock ptrParams->tlock
Print "thread " & ptrParams->id;
Locate , 20
Print i & "/" & ptrParams->count
Mutexunlock ptrParams->tlock
Next
End Sub
Dim tlock As Any Ptr = Mutexcreate()
Dim As Params ArgList1
ArgList1.id = "A"
ArgList1.tlock = tlock
ArgList1.count = 6
Dim a As Any Ptr = Threadcreate( @thread, @ArgList1 )
Dim As Params ArgList2
ArgList2.id = "B"
ArgList2.tlock = tlock
ArgList2.count = 4
Dim b As Any Ptr = Threadcreate( @thread, @ArgList2 )
Threadwait a
Threadwait b
Mutexdestroy tlock
Print "All done (And without Dim Shared!)"
Sleep