Page 1 of 1

[Solved] Directory loop without global?

Posted: Sun Jun 09, 2024 1:52 am
by BarryG
Anyone know how I can convert this code to NOT use a global variable to hold the directory size? Because my app needs to call this routine multiple times now from different threads, and the var is getting incorrectly updated even though my app is thread-safe. :(

Source -> https://www.purebasic.fr/english/viewto ... 82#p171382

Code: Select all

Global foldersize.q ; Don't want to rely on this being global.

Procedure.q FolderSizeRoutine(dir$)
  dir=ExamineDirectory(#PB_Any,dir$,"")
  If dir
    While NextDirectoryEntry(dir)
      If DirectoryEntryType(dir)=#PB_DirectoryEntry_File
        foldersize+DirectoryEntrySize(dir)
        Continue
      ElseIf Not DirectoryEntryName(dir)="." And Not DirectoryEntryName(dir)=".."
        FolderSizeRoutine(dir$+DirectoryEntryName(dir)+"\")
        Continue
      EndIf
    Wend
    FinishDirectory(dir)
  EndIf
  ProcedureReturn foldersize
EndProcedure

Procedure.q FolderSize(dir$)
  If Right(dir$,1)<>"\"
    dir$+"\"
  EndIf
  foldersize=0
  FolderSizeRoutine(dir$)
  ProcedureReturn foldersize
EndProcedure

Debug FolderSize("C:\Windows\System32\") ; Example of current non-thread use.

Re: Directory loop without global?

Posted: Sun Jun 09, 2024 4:55 am
by jassing
Or keep it simple... (now with thread demo) (assuming you don't need the size in one location, just from individual threads)

Code: Select all

EnableExplicit

Procedure.q FolderSize(dir$)
  Protected size.q, dir
  dir=ExamineDirectory(#PB_Any,dir$,"")
  
  If dir
    While NextDirectoryEntry(dir)
      If DirectoryEntryType(dir)=#PB_DirectoryEntry_File
        size+DirectoryEntrySize(dir)
      ElseIf Not DirectoryEntryName(dir)="." And Not DirectoryEntryName(dir)=".."
        size+FolderSize(dir$+"\"+DirectoryEntryName(dir)+"\")
      EndIf
    Wend
    FinishDirectory(dir)
  Else
    size=-1
  EndIf
  ProcedureReturn size
EndProcedure

Procedure threadTest( *folder )
  Debug FormatNumber(FolderSize(PeekS(*folder)),0) + " bytes in "+PeekS(*folder)
EndProcedure  

Define h1=CreateThread(@threadTest(),@"c:\windows\system32"),
       h2=CreateThread(@threadTest(),@"C:\temp"),
       h3=CreateThread(@threadTest(),@"c:\non-existant\folder")

Debug FormatNumber(FolderSize(#PB_Compiler_Home),0) +" bytes in "+#PB_Compiler_Home
WaitThread(h1) : WaitThread(h2) : WaitThread(h3)

Re: Directory loop without global?

Posted: Sun Jun 09, 2024 5:15 am
by idle
that's better :D

Re: Directory loop without global?

Posted: Sun Jun 09, 2024 7:53 am
by BarryG
Thanks, but the size for "System32" isn't correct (it's 21 bytes off). The code in my first post gets the correct size.

Image

Image

[Edit] Doing only ONE thread makes it work:

Code: Select all

EnableExplicit

Procedure.q FolderSize(dir$)
  Protected size.q, dir
  dir=ExamineDirectory(#PB_Any,dir$,"")
  If dir
    While NextDirectoryEntry(dir)
      If DirectoryEntryType(dir)=#PB_DirectoryEntry_File
        size+DirectoryEntrySize(dir)
      ElseIf Not DirectoryEntryName(dir)="." And Not DirectoryEntryName(dir)=".."
        size+FolderSize(dir$+"\"+DirectoryEntryName(dir)+"\")
      EndIf
    Wend
    FinishDirectory(dir)
  EndIf
  ProcedureReturn size
EndProcedure

Procedure threadTest( *folder )
  Debug FormatNumber(FolderSize(PeekS(*folder)),0) + " bytes in "+PeekS(*folder)
EndProcedure  

Define h1=CreateThread(@threadTest(),@"c:\windows\system32")
WaitThread(h1)

Re: Directory loop without global?

Posted: Sun Jun 09, 2024 8:21 am
by DarkDragon
Probably because If dir fails (permissions?) and size = -1 leads to a subtraction of one.

Re: [Solved] Directory loop without global?

Posted: Sun Jun 09, 2024 8:34 am
by BarryG
Edited my post above because it's working if I create one thread. Don't know why.

Re: [Solved] Directory loop without global?

Posted: Sun Jun 09, 2024 6:03 pm
by AZJIO
The hard drive will still be a bottleneck