New cache mechanism and thread overload fixed

This commit is contained in:
djes
2017-06-08 15:02:34 +02:00
parent c862f9099e
commit bbf5be2efd

145
PBMap.pb
View File

@@ -303,7 +303,7 @@ Module PBMap
;-*** Global variables ;-*** Global variables
;-Show debug infos ;-Show debug infos
Global MyDebugLevel = 0 Global MyDebugLevel = 5
Global PBMap.PBMap, Null.i, NullPtrMem.i, *NullPtr = @NullPtrMem Global PBMap.PBMap, Null.i, NullPtrMem.i, *NullPtr = @NullPtrMem
Global slash.s Global slash.s
@@ -1063,17 +1063,17 @@ Module PBMap
ProcedureReturn 0 ProcedureReturn 0
EndProcedure EndProcedure
Procedure.i GetTileFromWeb(TileURL.s, CacheFile.s) ; Procedure.i GetTileFromWeb(TileURL.s, CacheFile.s)
;Debug TileURL ; ;Debug TileURL
If ReceiveHTTPFile(TileURL, CacheFile) ; If ReceiveHTTPFile(TileURL, CacheFile, #PB_HTTP_Asynchronous)
MyDebug(" Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) ; MyDebug(" Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3)
; Debug TileURL + " OK" ; ; Debug TileURL + " OK"
ProcedureReturn GetTileFromHDD(CacheFile) ; ProcedureReturn GetTileFromHDD(CacheFile)
Else ; Else
MyDebug(" Problem receving from web " + TileURL + " as CacheFile " + CacheFile, 3) ; MyDebug(" Problem receving from web " + TileURL + " as CacheFile " + CacheFile, 3)
; Debug TileURL + " NOT OK" ; ; Debug TileURL + " NOT OK"
ProcedureReturn -1 ; ProcedureReturn -1
EndIf ; EndIf
; **** (OLD) IMPORTANT NOTICE (please not remove) ; **** (OLD) IMPORTANT NOTICE (please not remove)
; I'm (djes) now using Curl (actually, just normal pb) only, as this original catchimage/saveimage method is a double operation (uncompress/recompress PNG) ; I'm (djes) now using Curl (actually, just normal pb) only, as this original catchimage/saveimage method is a double operation (uncompress/recompress PNG)
; and is modifying the original PNG image which could lead to PNG error (Idle has spent hours debunking the 1 bit PNG bug) ; and is modifying the original PNG image which could lead to PNG error (Idle has spent hours debunking the 1 bit PNG bug)
@@ -1099,22 +1099,47 @@ Module PBMap
; MyDebug(" Problem loading from web " + TileURL, 3) ; MyDebug(" Problem loading from web " + TileURL, 3)
; EndIf ; EndIf
; **** ; ****
EndProcedure ; EndProcedure
Procedure GetImageThread(*Tile.Tile) Procedure GetImageThread(*Tile.Tile)
MyDebug("Thread for image key " + *Tile\key, 3) Protected Download, Progress, Size
Repeat MyDebug("Thread starting for image " + *Tile\CacheFile + "(" + *Tile\key + ")", 3)
*Tile\nImage = GetTileFromWeb(*Tile\URL, *Tile\CacheFile) Download = ReceiveHTTPFile(*Tile\URL, *Tile\CacheFile, #PB_HTTP_Asynchronous)
If *Tile\nImage <> -1 If Download
*Tile\RetryNb = 0 Repeat
Else Progress = HTTPProgress(Download)
Delay(2000) Select Progress
*Tile\RetryNb - 1 Case #PB_Http_Success
EndIf Size = FinishHTTP(Download)
Until *Tile\RetryNb <= 0 MyDebug(" Thread for image " + *Tile\CacheFile + " finished. Size : " + Str(Size), 3)
MyDebug(" Thread for image key " + *Tile\key + " finished", 3) PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread
*Tile\RetryNb = -2 ;End of the thread ProcedureReturn
PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread Case #PB_Http_Failed
MyDebug(" Thread for image " + *Tile\CacheFile + " failed.", 3)
PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread
ProcedureReturn
Case #PB_Http_Aborted
MyDebug(" Thread for image " + *Tile\CacheFile + " aborted.", 3)
PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread
ProcedureReturn
Default
MyDebug(" Thread for image " + *Tile\CacheFile + " downloading " + Str(Progress) + " bytes", 3)
EndSelect
Delay(500) ; Frees CPU
ForEver
EndIf
; Repeat
; *Tile\nImage = GetTileFromWeb(*Tile\URL, *Tile\CacheFile)
; If *Tile\nImage <> -1
; *Tile\RetryNb = 0
; Else
; Delay(2000)
; *Tile\RetryNb - 1
; EndIf
; Until *Tile\RetryNb <= 0
; MyDebug(" Thread for image key " + *Tile\key + " finished", 3)
; *Tile\RetryNb = -2 ;End of the thread
; PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread
EndProcedure EndProcedure
;-*** ;-***
@@ -1136,35 +1161,37 @@ Module PBMap
EndIf EndIf
Else Else
;*** Cache management ;*** Cache management
; if cache size exceeds limit, try to delete the oldest tiles used (first in the time stack) ; If cache size exceeds limit, try to delete the oldest tiles used (first in the time stack)
Protected CacheSize = MapSize(PBMap\MemCache\Images()) * Pow(PBMap\TileSize, 2) * 4 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA) Protected CacheSize = MapSize(PBMap\MemCache\Images()) * Pow(PBMap\TileSize, 2) * 5 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA)
Protected CacheLimit = PBMap\Options\MaxMemCache * 1024 Protected CacheLimit = PBMap\Options\MaxMemCache * 1024
MyDebug("Cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 3) MyDebug("Cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 5)
If CacheSize > CacheLimit If CacheSize > CacheLimit
MyDebug(" Cache full. Trying cache cleaning", 3) MyDebug(" Cache full. Trying cache cleaning", 5)
ResetList(PBMap\MemCache\ImagesTimeStack()) ResetList(PBMap\MemCache\ImagesTimeStack())
; Try to free half the cache memory (one pass) ; Try to free half the cache memory (one pass)
While NextElement(PBMap\MemCache\ImagesTimeStack()) And CacheSize > (CacheLimit / 2) ; /2 = half While NextElement(PBMap\MemCache\ImagesTimeStack()) And CacheSize > (CacheLimit / 2) ; /2 = half
Protected CacheMapKey.s = PBMap\MemCache\ImagesTimeStack()\MapKey Protected CacheMapKey.s = PBMap\MemCache\ImagesTimeStack()\MapKey
Protected Image = PBMap\MemCache\Images(CacheMapKey)\nImage Protected Image = PBMap\MemCache\Images(CacheMapKey)\nImage
If IsImage(Image) ; Check if the image is valid (is a loading thread running ?) If PBMap\MemCache\Images(CacheMapKey)\Tile = 0 ; Check if a loading thread is not already running
FreeImage(Image) If IsImage(Image) ; Check if the image is valid
DeleteMapElement(PBMap\MemCache\Images(), CacheMapKey) FreeImage(Image)
DeleteElement(PBMap\MemCache\ImagesTimeStack()) EndIf
MyDebug(" Delete " + CacheMapKey + " as image nb " + Str(Image), 3) DeleteMapElement(PBMap\MemCache\Images(), CacheMapKey)
EndIf DeleteElement(PBMap\MemCache\ImagesTimeStack())
CacheSize = MapSize(PBMap\MemCache\Images()) * Pow(PBMap\TileSize, 2) * 4 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA) MyDebug(" Delete " + CacheMapKey + " as image nb " + Str(Image), 5)
Wend EndIf
MyDebug(" New cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 3) CacheSize = MapSize(PBMap\MemCache\Images()) * Pow(PBMap\TileSize, 2) * 4 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA)
If CacheSize > CacheLimit Wend
MyDebug(" Cache cleaning unsuccessfull, can't add new tiles.", 3) MyDebug(" New cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 5)
ProcedureReturn 0 If CacheSize > CacheLimit
EndIf MyDebug(" Cache cleaning unsuccessfull, can't add new tiles.", 5)
ProcedureReturn 0
EndIf
EndIf EndIf
; Creates a new cache element ; Creates a new cache element
*timg = AddMapElement(PBMap\MemCache\Images(), key) *timg = AddMapElement(PBMap\MemCache\Images(), key)
If *timg = 0 If *timg = 0
MyDebug(" Can't add a new cache element.", 3) MyDebug(" Can't add a new cache element.", 5)
ProcedureReturn 0 ProcedureReturn 0
EndIf EndIf
; add a new time stack element at the End ; add a new time stack element at the End
@@ -1172,16 +1199,16 @@ Module PBMap
; Stores the time stack ptr ; Stores the time stack ptr
*timg\TimeStackPtr = AddElement(PBMap\MemCache\ImagesTimeStack()) *timg\TimeStackPtr = AddElement(PBMap\MemCache\ImagesTimeStack())
If *timg\TimeStackPtr = 0 If *timg\TimeStackPtr = 0
MyDebug(" Can't add a new time stack element.", 3) MyDebug(" Can't add a new time stack element.", 5)
DeleteMapElement(PBMap\MemCache\Images()) DeleteMapElement(PBMap\MemCache\Images())
ProcedureReturn 0 ProcedureReturn 0
EndIf EndIf
; Associates the time stack element to the cache element ; Associates the time stack element to the cache element
PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(PBMap\MemCache\Images()) PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(PBMap\MemCache\Images())
MyDebug("Key : " + key + " added in memory cache", 3) MyDebug("Key : " + key + " added in memory cache", 5)
;*** ;***
EndIf EndIf
If *timg\Tile = 0 ; Check if a loading thread is not already running If *timg\Tile = 0 ; Checks if a loading thread is not already running
; Is the file image on HDD ? ; Is the file image on HDD ?
*timg\nImage = GetTileFromHDD(CacheFile.s) *timg\nImage = GetTileFromHDD(CacheFile.s)
If *timg\nImage If *timg\nImage
@@ -1202,7 +1229,7 @@ Module PBMap
\URL = URL \URL = URL
\CacheFile = CacheFile \CacheFile = CacheFile
\RetryNb = 5 \RetryNb = 5
\nImage = -1 \nImage = 0
\GetImageThread = CreateThread(@GetImageThread(), *NewTile) \GetImageThread = CreateThread(@GetImageThread(), *NewTile)
If \GetImageThread If \GetImageThread
MyDebug(" Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile, 3) MyDebug(" Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile, 3)
@@ -2630,8 +2657,8 @@ CompilerIf #PB_Compiler_IsMainFile
;Our main gadget ;Our main gadget
PBMap::InitPBMap(#Window_0) PBMap::InitPBMap(#Window_0)
PBMap::SetOption("ShowDegrees", "1") : Degrees = 0 PBMap::SetOption("ShowDegrees", "1") : Degrees = 0
PBMap::SetOption("ShowDebugInfos", "1") PBMap::SetOption("ShowDebugInfos", "0")
PBMap::SetOption("Verbose", "1") PBMap::SetOption("Verbose", "0")
PBMap::SetOption("ShowScale", "1") PBMap::SetOption("ShowScale", "1")
PBMap::SetOption("Warning", "1") PBMap::SetOption("Warning", "1")
PBMap::SetOption("ShowMarkersLegend", "1") PBMap::SetOption("ShowMarkersLegend", "1")
@@ -2774,8 +2801,8 @@ CompilerIf #PB_Compiler_IsMainFile
CompilerEndIf CompilerEndIf
; IDE Options = PureBasic 5.60 (Windows - x64) ; IDE Options = PureBasic 5.60 (Windows - x64)
; CursorPosition = 1067 ; CursorPosition = 871
; FirstLine = 1055 ; FirstLine = 858
; Folding = ------------------- ; Folding = -------------------
; EnableThread ; EnableThread
; EnableXP ; EnableXP