Page 1 of 2

another tip to avoid crashes with strings and threads

Posted: Tue Aug 03, 2004 10:14 am
by Rings
Code updated For 5.20+

DIGE asks about Critical sections in IRC , and i did a small code to use them to avoid crashes from multilply use of strings in Threads
This snippet only works under windows, remember that in the section of entercriticalsection and Leavecriticalsection no other threads have access to the strings :) (they have to wait)

Code: Select all

Global CSInitialized.l
Global CS.CRITICAL_SECTION
 
Global A.s
 
Procedure testme(P)
If CSInitialized =0
 InitializeCriticalSection_(CS)
 CSInitialized = 1
EndIf
 
While T<20
EntercriticalSection_(Cs)
;do everything now 
A.s=Str(p)
Debug A.s
LeaveCriticalSection_(CS)
Delay(500)
T+1
Wend
EndProcedure
 
For I=1 To 10
 ThreadID = CreateThread(@testme(), I) 
Next I
 
Max=10000
t0=GetTickcount_()
While t<Max
 t=GetTickcount_()-T0
 Delay(100)
 A.s="0"
 Debug A.s
Wend

Posted: Tue Aug 03, 2004 6:58 pm
by newbie
Nice to know, I didn't know this API ;)

Re: another tip to avoid crashes with strings and threads

Posted: Wed Aug 04, 2004 12:26 am
by PB
What exactly is the story with threads and strings? I've used strings in threads
for ages with no problems. What is the problem? And does wrapping a thread
with EnterCriticalSection and LeaveCriticalSection make them safer? If so,
shouldn't Fred automatically use these APIs in the compiled thread code?

Posted: Wed Aug 04, 2004 11:37 am
by dmoc
I've used strings in threads for ages with no problems.
...you have just been lucky. Eventually your code will crash and burn :twisted:

Posted: Sat Aug 07, 2004 1:46 pm
by newbie
I have finally needed it :P

Without this method, strings to display get overlapped like :

"local" + "remote" displays "loremote"

now everything works fine ;)

Posted: Sat Aug 07, 2004 5:55 pm
by newbie
Works better with Mutex :

Mutex creation :

Code: Select all

HLog   = CreateMutex_(#Null, 0, "ZoneLog")

If Hlog = #Null
MessageBox_(0, "Error while creating Mutex.", "MyProg :", #MB_ICONERROR)
End
endif
Mutex usage :

Code: Select all

res = OpenMutex_(#MUTEX_ALL_ACCESS, 0, "ZoneLog")
    While res = #Null : res = OpenMutex_(#MUTEX_ALL_ACCESS, 0, "ZoneLog") : Wend

; your code here

ReleaseMutex_(res)
CloseHandle_(res)   
If I don't do it right, feel free to correct me ;)

Posted: Sun Aug 08, 2004 5:39 am
by PolyVector
EnterCriticalSection_() is fine for simple thread-safety... When your programs use a large number of threads and shared memory, it is very important not to lock every thread each time something needs to be accessed... This will bring your program to a slooooooow crawl... I agree with newbie... Mutex_() is a better practice...

Posted: Sun Aug 08, 2004 8:39 am
by Rings
PolyVector wrote:EnterCriticalSection_() is fine for simple thread-safety... When your programs use a large number of threads and shared memory, it is very important not to lock every thread each time something needs to be accessed... This will bring your program to a slooooooow crawl... I agree with newbie... Mutex_() is a better practice...
of course you should not lock complete Threads(Procedures), only critical sections like String-Operations.

Posted: Sun Aug 08, 2004 10:30 am
by PolyVector
I only meant that complex multi-threaded apps need to be very carefull with mutal-exclusion syncronization... The mutex object provies much more control with commands like WaitForSingleObject_()...
Critical Sections are somewhat limited... In a large project, you might run into problems w/ thread lock...

I'm very tired, maybe I'm not making sense... Just ignore me :|

Posted: Sun Aug 08, 2004 8:45 pm
by newbie
my previous code was wrong, here a right one, and with 3 Mutex :

create the needed Mutex first

Code: Select all

#WAIT_OBJECT_0 = $0

Global HLog
Global HEnter
Global HChat

HLog   = CreateMutex_(#Null, 0, "ZoneLog")
HEnter = CreateMutex_(#Null, 0, "ZoneEnter")
HChat  = CreateMutex_(#Null, 0, "ZoneChat")
let's say they refer to different gadget from a GUI, that many threads access to modify.

If a thread need access and need to ensure that it will have exclusive access,
you can do this :

Code: Select all

Dim hArray.l(2)
hArray(0) = HChat
hArray(1) = HLog
hArray(2) = HEnter

;Wait maximum 5s until the 3 Mutex are free for ownership    
res = WaitForMultipleObjects_(3, @hArray(0), 1, 5000) 
If res = #WAIT_OBJECT_0
 ;your code here
 ;don't forget to release the Mutex for the other Threads !!
    ReleaseMutex_(HLog)
    ReleaseMutex_(HChat)
    ReleaseMutex_(HEnter)
endif
You can use WaitForSingleObject instead for only one Mutex.

Posted: Mon Aug 09, 2004 9:22 pm
by newbie
Hi,

can someone elaborate about this from the help file ?
Note: Threads need to be used carefully because it is possible that you can have multiple access to shared resources (memory, variables, files, etc) and you need to manually ensure that you do run into trouble because of this. For example, it is not safe to modify or write to strings from more than one thread because strings share the same internal memory buffer. If you only ever read from strings while your threads are running then it should be safe.

If you still want to modify strings safely in threads (or any other shared access resource), you need to make sure that only one thread can use strings at a time. To do this you should make use of the synchronisation capabilities of the OS you are running on.
I thought it was just like the Ring example, about a Global string variable, but after reading the help, It makes me wonder if it means that just one thread at a time can write to any local string, because even the local strings are sharing the same global buffer space ??
I mean that two Threads can't do string operation even if the string variables are locals to these Threads ?

Is two threads can simultaneously do memory operation like CopyMemory
if the variables involved are only local to these threads ?

I hope my question makes sense.

Posted: Mon Aug 09, 2004 9:33 pm
by freedimension
PB String Functions do indeed use the same String Buffer for running. For more information have a look in the PB SDK Documentation.

But I don't know if even the simple String Concatenation str1$ + str2$ uses this Buffer!?

Posted: Tue Aug 10, 2004 8:24 am
by Rings
freedimension wrote:PB String Functions do indeed use the same String Buffer for running. For more information have a look in the PB SDK Documentation.

But I don't know if even the simple String Concatenation str1$ + str2$ uses this Buffer!?
it does afaik

Posted: Tue Aug 31, 2004 10:51 am
by Fred
Yes, it uses it. The Enter/LeaveCriticalSection is a good way to enable string safe threads. It uses a mutex under the hood so it's there is no drawback to use it instead mutex for simple synchronisation.

Posted: Tue Aug 31, 2004 12:23 pm
by PB
> it is not safe to modify or write to strings from more than one thread

Does this mean if my app has only one thread (created with CreateThread)
that it's safe to modify strings inside it? Or does the rest of my app (outside
of this thread) also count as a thread? I'm confused.