Added download slots and automatic download cancellation after a delay

This commit is contained in:
djes
2017-06-09 15:16:08 +02:00
parent 1de62dfb16
commit 530273a934

View File

@@ -125,6 +125,7 @@ Module PBMap
CacheFile.s CacheFile.s
GetImageThread.i GetImageThread.i
Download.i Download.i
Time.i
EndStructure EndStructure
Structure BoundingBox Structure BoundingBox
@@ -198,6 +199,7 @@ Module PBMap
TimerInterval.i TimerInterval.i
MaxMemCache.i ; in MiB MaxMemCache.i ; in MiB
MaxThreads.i ; Maximum simultaneous web loading threads MaxThreads.i ; Maximum simultaneous web loading threads
MaxDownloadSlots.i ; Maximum simultaneous download slots
TileLifetime.i TileLifetime.i
Verbose.i ; Maximum debug informations Verbose.i ; Maximum debug informations
Warning.i ; Warning requesters Warning.i ; Warning requesters
@@ -288,7 +290,10 @@ Module PBMap
Redraw.i Redraw.i
Dragging.i Dragging.i
Dirty.i ; To signal that drawing need a refresh Dirty.i ; To signal that drawing need a refresh
MemoryCacheManagement.i ; To pause web loading threads MemoryCacheManagement.i ; To pause web loading threads
DownloadSlots.i ; Actual nb of used download slots
DownloadSlotsMutex.i ; To be sure that only one thread at a time can access to the DownloadSlots var
List TracksList.Tracks() ; To display a GPX track List TracksList.Tracks() ; To display a GPX track
List Markers.Marker() ; To diplay marker List Markers.Marker() ; To diplay marker
@@ -687,6 +692,8 @@ Module PBMap
PBMap\Options\MaxMemCache = Val(Value) PBMap\Options\MaxMemCache = Val(Value)
Case "maxthreads" Case "maxthreads"
PBMap\Options\MaxThreads = Val(Value) PBMap\Options\MaxThreads = Val(Value)
Case "maxdownloadslots"
PBMap\Options\MaxDownloadSlots = Val(Value)
Case "tilelifetime" Case "tilelifetime"
PBMap\Options\TileLifetime = Val(Value) PBMap\Options\TileLifetime = Val(Value)
Case "verbose" Case "verbose"
@@ -756,6 +763,8 @@ Module PBMap
ProcedureReturn StrU(\MaxMemCache) ProcedureReturn StrU(\MaxMemCache)
Case "maxthreads" Case "maxthreads"
ProcedureReturn StrU(\MaxThreads) ProcedureReturn StrU(\MaxThreads)
Case "maxdownloadslots"
ProcedureReturn StrU(\MaxDownloadSlots)
Case "tilelifetime" Case "tilelifetime"
ProcedureReturn StrU(\TileLifetime) ProcedureReturn StrU(\TileLifetime)
Case "verbose" Case "verbose"
@@ -818,6 +827,7 @@ Module PBMap
WritePreferenceInteger("WheelMouseRelative", \WheelMouseRelative) WritePreferenceInteger("WheelMouseRelative", \WheelMouseRelative)
WritePreferenceInteger("MaxMemCache", \MaxMemCache) WritePreferenceInteger("MaxMemCache", \MaxMemCache)
WritePreferenceInteger("MaxThreads", \MaxThreads) WritePreferenceInteger("MaxThreads", \MaxThreads)
WritePreferenceInteger("MaxDownloadSlots", \MaxDownloadSlots)
WritePreferenceInteger("TileLifetime", \TileLifetime) WritePreferenceInteger("TileLifetime", \TileLifetime)
WritePreferenceInteger("Verbose", \Verbose) WritePreferenceInteger("Verbose", \Verbose)
WritePreferenceInteger("Warning", \Warning) WritePreferenceInteger("Warning", \Warning)
@@ -882,7 +892,8 @@ Module PBMap
PreferenceGroup("OPTIONS") PreferenceGroup("OPTIONS")
\WheelMouseRelative = ReadPreferenceInteger("WheelMouseRelative", #True) \WheelMouseRelative = ReadPreferenceInteger("WheelMouseRelative", #True)
\MaxMemCache = ReadPreferenceInteger("MaxMemCache", 20480) ; 20 MiB, about 80 tiles in memory \MaxMemCache = ReadPreferenceInteger("MaxMemCache", 20480) ; 20 MiB, about 80 tiles in memory
\MaxThreads = ReadPreferenceInteger("MaxThreads", 10) \MaxThreads = ReadPreferenceInteger("MaxThreads", 40)
\MaxDownloadSlots = ReadPreferenceInteger("MaxDownloadSlots", 2)
\TileLifetime = ReadPreferenceInteger("TileLifetime", 1209600) ; about 2 weeks ;-1 = unlimited \TileLifetime = ReadPreferenceInteger("TileLifetime", 1209600) ; about 2 weeks ;-1 = unlimited
\Verbose = ReadPreferenceInteger("Verbose", #False) \Verbose = ReadPreferenceInteger("Verbose", #False)
\Warning = ReadPreferenceInteger("Warning", #False) \Warning = ReadPreferenceInteger("Warning", #False)
@@ -1031,6 +1042,8 @@ Module PBMap
ProcedureReturn PBMap\Layers(Name)\Alpha ProcedureReturn PBMap\Layers(Name)\Alpha
EndProcedure EndProcedure
;-***
Procedure MemoryCacheManagement() Procedure MemoryCacheManagement()
; 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) * 5 ; 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)
@@ -1133,6 +1146,20 @@ Module PBMap
Procedure GetImageThread(*Tile.Tile) Procedure GetImageThread(*Tile.Tile)
MyDebug("Thread starting for image " + *Tile\CacheFile + "(" + *Tile\key + ")", 5) MyDebug("Thread starting for image " + *Tile\CacheFile + "(" + *Tile\key + ")", 5)
; Waits for a free download slot
LockMutex(PBMap\DownloadSlotsMutex)
While PBMap\DownloadSlots >= PBMap\Options\MaxDownloadSlots
UnlockMutex(PBMap\DownloadSlotsMutex)
If ElapsedMilliseconds() - *Tile\Time > 10000
MyDebug(" Thread for image " + *Tile\CacheFile + " canceled after 10 seconds waiting for a slot.", 5)
PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread
ProcedureReturn #False
EndIf
Delay(500)
LockMutex(PBMap\DownloadSlotsMutex)
Wend
PBMap\DownloadSlots + 1
UnlockMutex(PBMap\DownloadSlotsMutex)
*Tile\Download = ReceiveHTTPFile(*Tile\URL, *Tile\CacheFile, #PB_HTTP_Asynchronous) *Tile\Download = ReceiveHTTPFile(*Tile\URL, *Tile\CacheFile, #PB_HTTP_Asynchronous)
If *Tile\Download If *Tile\Download
Repeat Repeat
@@ -1143,22 +1170,23 @@ Module PBMap
Size = FinishHTTP(*Tile\Download) Size = FinishHTTP(*Tile\Download)
MyDebug(" Thread for image " + *Tile\CacheFile + " finished. Size : " + Str(Size), 5) MyDebug(" Thread for image " + *Tile\CacheFile + " finished. Size : " + Str(Size), 5)
PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread
*Tile\Download = 0
ProcedureReturn #True ProcedureReturn #True
Case #PB_Http_Failed Case #PB_Http_Failed
FinishHTTP(*Tile\Download) FinishHTTP(*Tile\Download)
MyDebug(" Thread for image " + *Tile\CacheFile + " failed.", 5) MyDebug(" Thread for image " + *Tile\CacheFile + " failed.", 5)
PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread
*Tile\Download = 0
ProcedureReturn #False ProcedureReturn #False
Case #PB_Http_Aborted Case #PB_Http_Aborted
FinishHTTP(*Tile\Download) FinishHTTP(*Tile\Download)
MyDebug(" Thread for image " + *Tile\CacheFile + " aborted.", 5) MyDebug(" Thread for image " + *Tile\CacheFile + " aborted.", 5)
PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread
*Tile\Download = 0
ProcedureReturn #False ProcedureReturn #False
Default Default
MyDebug(" Thread for image " + *Tile\CacheFile + " downloading " + Str(Progress) + " bytes", 5) MyDebug(" Thread for image " + *Tile\CacheFile + " downloading " + Str(Progress) + " bytes", 5)
If ElapsedMilliseconds() - *Tile\Time > 60000
MyDebug(" Thread for image " + *Tile\CacheFile + " canceled after 60 seconds.", 5)
AbortHTTP(*Tile\Download)
EndIf
EndSelect EndSelect
EndIf EndIf
Delay(500) ; Frees CPU Delay(500) ; Frees CPU
@@ -1227,6 +1255,7 @@ Module PBMap
\URL = URL \URL = URL
\CacheFile = CacheFile \CacheFile = CacheFile
\nImage = 0 \nImage = 0
\Time = ElapsedMilliseconds()
\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)
@@ -2281,7 +2310,7 @@ Module PBMap
Case #PB_EventType_LeftButtonDown Case #PB_EventType_LeftButtonDown
; LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) ; LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom)
PBMap\Dragging = #True PBMap\Dragging = #True
;Mem cursor Coord ; Memorize cursor Coord
PBMap\MoveStartingPoint\x = CanvasMouseX PBMap\MoveStartingPoint\x = CanvasMouseX
PBMap\MoveStartingPoint\y = CanvasMouseY PBMap\MoveStartingPoint\y = CanvasMouseY
; Clip MouseX to the map range (in X, the map is infinite) ; Clip MouseX to the map range (in X, the map is infinite)
@@ -2408,7 +2437,11 @@ Module PBMap
*Tile = EventData() *Tile = EventData()
key = *Tile\key key = *Tile\key
; After a Web tile loading thread, clean the tile structure memory and set the image nb in the cache ; After a Web tile loading thread, clean the tile structure memory and set the image nb in the cache
; avoid to have threads accessing vars (and avoid mutex), see GetImageThread() ; avoid to have threads accessing vars (and avoid some mutex), see GetImageThread()
*Tile\Download = 0
LockMutex(PBMap\DownloadSlotsMutex)
PBMap\DownloadSlots - 1
UnlockMutex(PBMap\DownloadSlotsMutex)
Protected timg = PBMap\MemCache\Images(key)\Tile\nImage ; Get this new tile image nb Protected timg = PBMap\MemCache\Images(key)\Tile\nImage ; Get this new tile image nb
PBMap\MemCache\Images(key)\nImage = timg ; Stores it in the cache using the key PBMap\MemCache\Images(key)\nImage = timg ; Stores it in the cache using the key
FreeMemory(PBMap\MemCache\Images(key)\Tile) ; Frees the data needed for the thread FreeMemory(PBMap\MemCache\Images(key)\Tile) ; Frees the data needed for the thread
@@ -2421,7 +2454,7 @@ Module PBMap
; Redraws at regular intervals ; Redraws at regular intervals
Procedure TimerEvents() Procedure TimerEvents()
If EventTimer() = PBMap\Timer And (PBMap\Redraw Or PBMap\Dirty) If EventTimer() = PBMap\Timer And (PBMap\Redraw Or PBMap\Dirty)
MemoryCacheManagement() ; MemoryCacheManagement()
Drawing() Drawing()
EndIf EndIf
EndProcedure EndProcedure
@@ -2484,6 +2517,11 @@ Module PBMap
PBMap\Window = Window PBMap\Window = Window
PBMap\Timer = 1 PBMap\Timer = 1
PBMap\Mode = #MODE_DEFAULT PBMap\Mode = #MODE_DEFAULT
PBMap\DownloadSlotsMutex = CreateMutex()
If PBMap\DownloadSlotsMutex = #False
MyDebug("Cannot create a mutex", 0)
End
EndIf
LoadOptions() LoadOptions()
TechnicalImagesCreation() TechnicalImagesCreation()
SetLocation(0, 0) SetLocation(0, 0)
@@ -2799,8 +2837,8 @@ CompilerIf #PB_Compiler_IsMainFile
CompilerEndIf CompilerEndIf
; IDE Options = PureBasic 5.60 (Windows - x64) ; IDE Options = PureBasic 5.60 (Windows - x64)
; CursorPosition = 893 ; CursorPosition = 1162
; FirstLine = 894 ; FirstLine = 1143
; Folding = ------------------- ; Folding = -------------------
; EnableThread ; EnableThread
; EnableXP ; EnableXP