From 04492e513dbe2d25e156264dfe6b19c6b4f8f78a Mon Sep 17 00:00:00 2001 From: Thyphoon Date: Sun, 14 Sep 2025 17:36:20 +0200 Subject: [PATCH] New Cache (Helped with Gimini) --- Thumbnails.pb | 344 +++++++++++++++++++++++++------------------------- 1 file changed, 173 insertions(+), 171 deletions(-) diff --git a/Thumbnails.pb b/Thumbnails.pb index 706dbec..328c802 100644 --- a/Thumbnails.pb +++ b/Thumbnails.pb @@ -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