New Cache (Helped with Gimini)

This commit is contained in:
2025-09-14 17:36:20 +02:00
parent c7add6c0de
commit 04492e513d

View File

@@ -104,178 +104,217 @@ DeclareModule Cache
Structure Param
CallBackLoadMedia.CallBackLoadMedia
;LoadList
LoadListSemaphore.i
LoadListMutex.i
List LoadList.i()
;CacheList
NewTaskSemaphore.i
CacheListMutex.i
Map CacheList.Core::FileData()
BackGroundThread.i
;Signal New Image Loaded
Array WorkerThreads.i(1)
SignalMutex.i
Signal.b ;Signal When new image is loaded
;Message
Signal.b
QuitMutex.i
Quit.b
EndStructure
Global Param.Param
Param\LoadListSemaphore=CreateSemaphore(1)
Param\LoadListMutex=CreateMutex()
Param\CacheListMutex=CreateMutex()
param\SignalMutex=CreateMutex()
Param\QuitMutex=CreateMutex()
Declare InitCache()
Declare SetCallBackLoadMedia(CallBackLoadMedia.i)
Declare AddFileToLoadList(FilePath.s)
Declare CacheClean()
Declare AutoLoadStart()
Declare.i GetFileDataFromCache(FilePath.s,Image.i=0)
Declare.b GetSignalAndReset()
Declare Quit()
Declare QuitCache()
EndDeclareModule
Module Cache
EnableExplicit
;- CORRIGÉ : La constante est maintenant privée au module, sans 'Global'.
#WORKER_THREADS = 4
Procedure InitCache()
Param\LoadListMutex = CreateMutex()
Param\CacheListMutex = CreateMutex()
Param\SignalMutex = CreateMutex()
Param\QuitMutex = CreateMutex()
Param\NewTaskSemaphore = CreateSemaphore(0)
Dim Param\WorkerThreads(#WORKER_THREADS - 1)
EndProcedure
Procedure SetCallBackLoadMedia(CallBackLoadMedia.i)
Param\CallBackLoadMedia=CallBackLoadMedia
Param\CallBackLoadMedia = CallBackLoadMedia
EndProcedure
Procedure CacheWorkerThread(ThreadID.i)
Protected Quit.b = #False
Protected *Ptr.Core::FileData
Repeat
WaitSemaphore(Param\NewTaskSemaphore)
LockMutex(Param\QuitMutex)
Quit = Param\Quit
UnlockMutex(Param\QuitMutex)
If Quit = #False
LockMutex(Param\LoadListMutex)
If ListSize(Param\LoadList()) > 0
FirstElement(Param\LoadList())
*Ptr = Param\LoadList()
DeleteElement(Param\LoadList())
Else
*Ptr = 0
EndIf
UnlockMutex(Param\LoadListMutex)
If *Ptr
If *Ptr\Image = 0 And FileSize(*Ptr\FilePath) > 0
Debug "Worker " + ThreadID + " charge: " + GetFilePart(*Ptr\FilePath)
If Param\CallBackLoadMedia <> 0
Param\CallBackLoadMedia(*Ptr)
Else
*Ptr\Image = LoadImage(#PB_Any, *Ptr\FilePath)
EndIf
If IsImage(*Ptr\Image)
Protected result.ImgTools::DefDisplayImage
ImgTools::ImageToContainer(@result, *Ptr\Image, 256, 256, ImgTools::#Image_Style_Fit)
ResizeImage(*Ptr\Image, result\Width, result\Height, #PB_Image_Smooth)
*Ptr\State = 1
LockMutex(Param\SignalMutex)
Param\Signal = #True
UnlockMutex(Param\SignalMutex)
Else
Debug "ERREUR de chargement: " + *Ptr\FilePath
*Ptr\Image = CreateImage(#PB_Any, 256, 256, 24, RGB(255, 0, 0))
*Ptr\State = 1
EndIf
EndIf
EndIf
EndIf
Until Quit = #True
Debug "Cache Worker " + ThreadID + " terminé."
EndProcedure
Procedure StartWorkers()
If IsThread(Param\WorkerThreads(0)) = #False
Debug "Démarrage du pool de " + #WORKER_THREADS + " threads."
Protected i
For i = 0 To #WORKER_THREADS - 1
Param\WorkerThreads(i) = CreateThread(@CacheWorkerThread(), i)
Next
EndIf
EndProcedure
Procedure AddFileToLoadList(FilePath.s)
Protected *Ptr
LockMutex(param\CacheListMutex)
*Ptr=AddMapElement(param\CacheList(),FilePath)
param\CacheList()\FilePath=FilePath
param\CacheList()\State=0
UnlockMutex(param\CacheListMutex)
LockMutex(Param\LoadListMutex)
LastElement(param\LoadList())
AddElement(param\LoadList())
Debug "AddFileToLoadList:"+Str(ListIndex(param\LoadList()))
param\LoadList()=*Ptr
UnlockMutex(Param\LoadListMutex)
EndProcedure
Procedure LoadCacheDataThread(*Ptr.core::FileData)
If *Ptr\Image=0 And FileSize(*Ptr\FilePath)>0
Debug "Cache Load:"+*Ptr\FilePath
;Param\CallBackLoadMedia=0 ;To Force to use Internal Loader
If Param\CallBackLoadMedia<>0 ; <- Use extern procedure to Load Image
LockMutex(Param\CacheListMutex)
Param\CallBackLoadMedia(*Ptr)
UnlockMutex(Param\CacheListMutex)
Else
LockMutex(Param\CacheListMutex) ; <- Or intern with PB Plugin
*Ptr\Image=LoadImage(#PB_Any,*Ptr\FilePath)
If IsImage(*Ptr\Image)
Else
*Ptr\Image=0
EndIf
UnlockMutex(Param\CacheListMutex)
EndIf
LockMutex(Param\CacheListMutex)
If FindMapElement(Param\CacheList(), FilePath) = #False
*Ptr = AddMapElement(Param\CacheList(), FilePath)
Param\CacheList()\FilePath = FilePath
Param\CacheList()\State = 0
UnlockMutex(Param\CacheListMutex)
;Resize Image to Thumnails MaxSize
If IsImage(*Ptr\Image)
Protected result.ImgTools::DefDisplayImage
ImgTools::ImageToContainer(@result,*Ptr\Image,256,256,ImgTools::#Image_Style_Fit)
ResizeImage(*Ptr\Image,result\Width,result\Height,#PB_Image_Smooth)
*Ptr\State=1; Ready to Display Image
;We Have a new Image i Signal it
LockMutex (Param\SignalMutex)
Param\Signal=#True
UnlockMutex (Param\SignalMutex)
;If can't load image
Else
;MessageRequester("Thumbnails Error","ERROR THREAD LOAD IMAGE"+Chr(13)+FilePath+Chr(13)+" in "+#PB_Compiler_Procedure+"()",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
Debug "ERROR THREAD LOAD IMAGE"+Chr(13)+*Ptr\FilePath
*Ptr\Image=CreateImage(#PB_Any,320,200)
StartDrawing(ImageOutput(*Ptr\Image))
Box(0,0,320,200,RGB(0,255,0))
StopDrawing()
*Ptr\State=1
EndIf
LockMutex(Param\LoadListMutex)
AddElement(Param\LoadList())
Param\LoadList() = *Ptr
UnlockMutex(Param\LoadListMutex)
SignalSemaphore(Param\NewTaskSemaphore)
Else
Debug "Cache Load Error:"+*Ptr\FilePath
EndIf
SignalSemaphore(Param\LoadListSemaphore)
UnlockMutex(Param\CacheListMutex)
EndIf
EndProcedure
Procedure BackgroundThread(n.i)
Protected Quit.b
Repeat
Repeat
Procedure.i GetFileDataFromCache(FilePath.s, Image.i = 0)
Protected *Ptr.core::FileData
LockMutex(Param\CacheListMutex)
*Ptr = FindMapElement(Param\CacheList(), FilePath)
UnlockMutex(Param\CacheListMutex)
If *Ptr = 0
StartWorkers()
LockMutex(Param\CacheListMutex)
*Ptr = AddMapElement(Param\CacheList(), FilePath)
*Ptr\FilePath = FilePath
If Image = 0
*Ptr\State = 0
*Ptr\Image = 0
LockMutex(Param\LoadListMutex)
;Select Data from Id
If LastElement(Param\LoadList())<>0
Debug "BackgroundThread:"+Str(ListIndex(param\LoadList()))
Protected *Ptr.core::FileData
*Ptr=Param\LoadList()
WaitSemaphore(Param\LoadListSemaphore)
Debug "LoadList index:"+Str(ListIndex(Param\LoadList()))+"/"+ListSize(Param\LoadList())
If CreateThread(@LoadCacheDataThread(),*Ptr)<>0
DeleteElement(Param\LoadList())
Else
Debug "######################Can't Start Thread"
End
EndIf
EndIf
AddElement(Param\LoadList())
Param\LoadList() = *Ptr
UnlockMutex(Param\LoadListMutex)
;Else
; Debug "Wait Semaphore"
; Delay(200)
; EndIf
; Debug "LOADLIST SIZE:"+Str(ListSize(Param\LoadList()))
LockMutex(Param\QuitMutex)
Quit=Param\Quit
UnlockMutex(Param\QuitMutex)
Until ListSize(Param\LoadList())=0 Or Quit=#True
Delay(1)
Until Quit=#True
Debug "Bye Bye ! Cache::BackgroundThread()"
SignalSemaphore(Param\NewTaskSemaphore)
Else
*Ptr\State = 1
*Ptr\Image = Image
EndIf
UnlockMutex(Param\CacheListMutex)
EndIf
ProcedureReturn *Ptr
EndProcedure
Procedure Quit()
Debug "QUIT CACHE"
If IsThread(Param\BackGroundThread)
Procedure QuitCache()
Debug "Arrêt du cache..."
If IsThread(Param\WorkerThreads(0))
LockMutex(Param\QuitMutex)
Param\Quit=#True
Param\Quit = #True
UnlockMutex(Param\QuitMutex)
Debug "Cache::Quit Wait Param\BackGroundThread"
WaitThread(Param\BackGroundThread)
Debug "Cache::Quit Finish"
EndIf
Protected i
For i = 0 To #WORKER_THREADS - 1
SignalSemaphore(Param\NewTaskSemaphore)
Next
For i = 0 To #WORKER_THREADS - 1
If IsThread(Param\WorkerThreads(i))
WaitThread(Param\WorkerThreads(i))
EndIf
Next
Debug "Tous les workers sont arrêtés."
EndIf
FreeMutex(Param\LoadListMutex)
FreeMutex(Param\CacheListMutex)
FreeMutex(Param\SignalMutex)
FreeMutex(Param\QuitMutex)
FreeSemaphore(Param\NewTaskSemaphore)
EndProcedure
Procedure AutoLoadStart()
If IsThread(Param\BackGroundThread)=#False
Param\BackGroundThread=CreateThread(@BackgroundThread(),0)
EndIf
Procedure.b GetSignalAndReset()
Protected Signal.b
LockMutex(Param\SignalMutex)
Signal = Param\Signal
Param\Signal = #False
UnlockMutex(Param\SignalMutex)
ProcedureReturn Signal
EndProcedure
Procedure Free(*Ptr.core::FileData)
If IsImage(*Ptr\Image):FreeImage(*Ptr\Image):EndIf
If IsImage(*Ptr\Image): FreeImage(*Ptr\Image): EndIf
FreeMap(*Ptr\MetaData())
EndProcedure
;TODO remake it
Procedure CacheClean()
Protected *Ptr.core::FileData
LockMutex(Param\CacheListMutex)
ForEach Param\CacheList()
If MapSize(Param\CacheList())<500
Break;
If MapSize(Param\CacheList()) < 500
Break
Else
*Ptr=Param\CacheList()
If *Ptr\State=1 And *Ptr\Selected=#False
Debug "Free Cache :"+GetFilePart(*Ptr\FilePath)+" State:"+Str(*Ptr\State)
*Ptr = Param\CacheList()
If *Ptr\State = 1 And *Ptr\Selected = #False
Debug "Nettoyage cache : " + GetFilePart(*Ptr\FilePath)
Free(*Ptr)
DeleteMapElement(Param\CacheList())
EndIf
@@ -283,48 +322,9 @@ Module Cache
Next
UnlockMutex(Param\CacheListMutex)
EndProcedure
Procedure.i GetFileDataFromCache(FilePath.s,Image.i=0)
LockMutex(Param\CacheListMutex)
Protected *Ptr.core::FileData
*Ptr=FindMapElement(Param\CacheList(),FilePath)
UnlockMutex(Param\CacheListMutex)
If *Ptr=0
;AddToLoadList
LockMutex(Param\CacheListMutex)
*Ptr=AddMapElement(Param\CacheList(),FilePath)
*Ptr\FilePath=FilePath
If Image=0
*Ptr\State=0
*Ptr\Image=0
Else ;If We have Image (Ex when use Blob in DB)
*Ptr\State=1
*Ptr\Image=Image
EndIf
UnlockMutex(Param\CacheListMutex)
LockMutex(Param\LoadListMutex)
Debug "ListSize:"+Str(ListSize(param\LoadList()))
FirstElement(param\LoadList())
AddElement(param\LoadList())
Param\LoadList()=*Ptr
UnlockMutex(Param\LoadListMutex)
AutoLoadStart()
EndIf
ProcedureReturn *Ptr
EndProcedure
Procedure.b GetSignalAndReset()
Protected Signal.b
LockMutex (Param\SignalMutex)
Signal=Param\Signal
Param\Signal=#False
UnlockMutex (Param\SignalMutex)
ProcedureReturn Signal
EndProcedure
EndModule
;-Thumbs
DeclareModule Thumbs
Declare SetCallBackLoadFromIndex(GadgetId.i,CallBackLoadFromIndex.i)
@@ -495,7 +495,7 @@ Module Thumbs
Delay(10)
Debug "No Set CallBackLoadFromIndex"
EndIf
Cache::AutoLoadStart()
Else
Delay(50)
EndIf
@@ -959,6 +959,7 @@ CompilerIf #PB_Compiler_IsMainFile
If OpenWindow(#Win_main, 0, 0, 1024, 600, "Thumbnails", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
ButtonGadget(#Gdt_Folder,0,0,100,25,"Choose Folder")
Cache::InitCache()
Thumbs::ThumbsGadget(#Gdt_ThumbA,0,50,WindowWidth(#Win_main),WindowHeight(#Win_main)-50,128,@CallBackLoadFromIndexB())
Repeat
Event = WaitWindowEvent()
@@ -997,11 +998,12 @@ CompilerIf #PB_Compiler_IsMainFile
Until Event = #PB_Event_CloseWindow
Thumbs::FreeThumbsGadget(#Gdt_ThumbA)
Cache::QuitCache()
EndIf
CompilerEndIf
; IDE Options = PureBasic 6.21 (Windows - x64)
; CursorPosition = 205
; FirstLine = 205
; CursorPosition = 1000
; FirstLine = 954
; Folding = ------
; EnableThread
; EnableXP