What constitutes threadsafe?

Windows specific forum
blackborg
User
User
Posts: 38
Joined: Thu Nov 02, 2006 8:20 pm

What constitutes threadsafe?

Post by blackborg »

Hello,

I am writing an application that fills a listicon gadget with thousands of records..

I have a thread reading the database and updating the listicon in the main window.. that part works great.. the intention of doing this is so that if the user clicks anything on the window, the display/window doesn't freeze..

The problem is this.. I am also trying to add a progress bar that lets the user know how much farther there is to process..

so far.. I have a second thread that creates it's own child window that holds only the progressbar gadget. Does anyone have an example of how to do this..
Baldrick
Addict
Addict
Posts: 860
Joined: Fri Jul 02, 2004 6:49 pm
Location: Australia

Post by Baldrick »

Hi Blackorg,
I am probably not the person to answer this for you, but here is a snippet I have made up for you which I think may do the job.
This snippet simply opens & reads a text file which is then placed into a linked list with numbered lines & then added to a listicon gadget in the main window.
It was my 2nd effort, with the 1st failing to work when the compiler threadsafe switch option was enabled. ( Which is also the reason why I have used a control from the main loop to open & close the 2ndry window instead of directly from the thread. )
Maybe 1 of the guru's would like to check my code & fix as needed... :)

Code: Select all

; PureBasic Visual Designer v3.95 build 1485 (PB4Code)

Enumeration
  #Window_0
  #Window_1
  #ListIcon_0
  #Button_0
  #Text_0
  #ProgressBar_0
  #File_0
EndEnumeration

Structure MyInfo
 Line.l
 String.s
EndStructure 
Global NewList MyData.MyInfo() ;may as well give the thread something to do!!

Procedure Open_Window_0()
  If OpenWindow(#Window_0, 258, 4, 600, 300, "New window ( 0 )",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
    If CreateGadgetList(WindowID(#Window_0))
      ListIconGadget(#ListIcon_0, 20, 15, 555, 215, "Line", 50, #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect)
      AddGadgetColumn(#ListIcon_0,1,"String",450)
      ButtonGadget(#Button_0, 20, 250, 50, 20, "Select")
    EndIf
  EndIf
EndProcedure

Procedure Open_Window_1()
  If OpenWindow(#Window_1, 236, 20, 326, 89, "New window ( 1 )", #PB_Window_TitleBar,WindowID(#Window_0) )
    If CreateGadgetList(WindowID(#Window_1))
      TextGadget(#Text_0, 15, 10, 295, 20, "", #PB_Text_Center | #PB_Text_Border)
      ProgressBarGadget(#ProgressBar_0, 15, 50, 295, 20, 0, 100,#PB_ProgressBar_Smooth)
    EndIf
  EndIf
EndProcedure

Procedure Update(F$)
 Shared Destroywindow.l
  If ReadFile(#File_0,F$)
   DisableGadget(#ListIcon_0,1)
   DisableGadget(#Button_0,1)
   SetGadgetText(#Text_0,"Deleting existing lists, please wait....")
   Flen.f=Lof(#File_0)
   ClearGadgetItemList(#ListIcon_0)
   ClearList(MyData())
   AddElement(MyData())
   count=0
   SetGadgetText(#Text_0,"Updating, please wait....")
    Repeat
     count+1 
     MyData()\Line=count 
     MyData()\String=ReadString(#File_0)
     AddGadgetItem(#ListIcon_0,-1,"")
     SetGadgetItemText(#ListIcon_0,count-1,Str(MyData()\Line),0)
     SetGadgetItemText(#ListIcon_0,count-1,MyData()\String,1)
     pos.f=Loc(#File_0)
     mypos.l= pos/Flen*100
     SetGadgetState(#ProgressBar_0,mypos)
     AddElement(MyData())
    Until Eof(#File_0)
   CloseFile(#File_0)
   DisableGadget(#ListIcon_0,0) 
   DisableGadget(#Button_0,0) 
   Destroywindow=1
  EndIf
EndProcedure 

  Open_Window_0()
  Repeat 
    Ev=WaitWindowEvent(10)
    
     If Destroywindow
       If IsWindow(#Window_1)
        CloseWindow(#Window_1)
       EndIf 
      Destroywindow=IsThread(MyThread)
     EndIf 
     
    If Ev=#PB_Event_Gadget
     Select EventGadget()
      Case #Button_0
       File$=OpenFileRequester("Select File","","Text (*.txt)|*.txt",0)
        If File$
         Open_Window_1()
         Mythread=CreateThread(@Update(),File$)
        EndIf        
      EndSelect 
    EndIf 
    
     If Ev=#PB_Event_CloseWindow
      Select EventWindow()
       Case #Window_0
        Quit.b=#True
      EndSelect 
     EndIf 
     
  Until Quit
End 
I have tried this code using Win Xp to load a text file containing 160,000 lines of text without fault.
( Just took a while to read all those lines )
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

hi blackborg,

you need to know the total number of records before starting the load.
if that is not a fix value, you could calculate it by the total length
of the file devided by the length of one record.
from this you have the maximum for the ProgressBarGadget.
the minimum in this case should be zero.

communication between seperate threads could be handled over global variables.

in the load-thread you count a global counter up each loaded record.

in the ProgressBarGadget-thread you set the GadgetState according to this global counter.

note that the thread needs an own eventloop to display the update of the gadget properly.
also the opening of the window and the creating of the ProgressBarGadget
should be within this thread.
the eventloop may look like this:

Code: Select all

Repeat
  Event = WaitWindowEvent(100)
  If Event = 0
    SetGadgetState(#ProgressBar, GlobalCounter)
  EndIf
Until EndCondition
the EndCondition also can be a Global Variable, that will be set to #True
by the Load-Thread when loading is finished.

the 100 lets the thread wait for 1/10sec between the updates of the progressbar.
in the first pass, Event is 0 because the 100ms ran out without an event.
so the progressbar is updated, and an event is created.
instandly in the second pass the update-event can be handled without
creating a new event, the updated progressbar is displayed.
next, the code will wait another 100ms.

hope it helped a bit....
oh... and have a nice day.
blackborg
User
User
Posts: 38
Joined: Thu Nov 02, 2006 8:20 pm

code snippet

Post by blackborg »

looks good.. crashes for me though with invalid memory access
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

booyah...

well, that can be caused anywhere...

some IMA can only be located in full code.... have fun...
since I don't know how you access your file, how you shift this data..
i have no idea where the IMA could be caused...
oh... and have a nice day.
blackborg
User
User
Posts: 38
Joined: Thu Nov 02, 2006 8:20 pm

just needed an update for PB.. that resolved it..

Post by blackborg »

but I really would like to know what functions need to be mutexed.. like, does assigning a string value to a variable in a thread need to be mutexed.. or is it just if I use the PB "String" functions like replacestring()and mid().

Could I use string pointers instead of mutexing?.. I just want to know if anyone has the beginnings of a list of which functions cause issues with strings in PB specifically.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

wich PB-Version are you using?

note that the "threadsafe"-feature came with 4.0
oh... and have a nice day.
blackborg
User
User
Posts: 38
Joined: Thu Nov 02, 2006 8:20 pm

I'm using PB 4.00 and I know about that option

Post by blackborg »

but if there's something that's not threadsafe.. it just gives a genetic error.. not a specific line number.. I don't know how to write threadsafe code.. hence the question..
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

an IMA could be caused by any stack-manipulation...

and it will always return no correct line-number in the error-message...

i'm sorry, i haven't dealt with string-shoving between threads so far....

i've read topics about list-gadget-filling in a thread, but i have no experience with it...
(never used a list-gadget... i'm a game-progger, i'm a algorithm-theoretical... but i'm not a windows-surface-freak...)
i only know basic thread-handling...

what exactly is the problem?
oh... and have a nice day.
Post Reply