Skip to content

Commit 9b0309e

Browse files
committed
Add multithreading on subtile retrieval
1 parent 765ad96 commit 9b0309e

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

lib/tileset.c

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,11 +795,42 @@ int mapcache_tileset_tile_get_readonly(mapcache_context *ctx, mapcache_tile *til
795795

796796
typedef struct {
797797
mapcache_tile *tile;
798-
int cache_status;
798+
int isFetched;
799799
} mapcache_subtile;
800800

801801
static void mapcache_tileset_tile_get_without_subdimensions(mapcache_context *ctx, mapcache_tile *tile, int read_only);
802802

803+
#if APR_HAS_THREADS
804+
/* use a thread pool if using 1.3.12 or higher apu */
805+
#include "apu_version.h"
806+
#if (APU_MAJOR_VERSION <= 1 && APU_MINOR_VERSION <= 3)
807+
#define USE_THREADPOOL 0
808+
#include <apr_thread_proc.h>
809+
#else
810+
#define USE_THREADPOOL 1
811+
#include <apr_thread_pool.h>
812+
#endif
813+
814+
typedef struct {
815+
mapcache_subtile *subtile;
816+
mapcache_tile *tile;
817+
mapcache_context *ctx;
818+
} _thread_subtile;
819+
static void* APR_THREAD_FUNC _thread_get_subtile(apr_thread_t *thread, void *data)
820+
{
821+
_thread_subtile * t = (_thread_subtile *)data;
822+
/* creates the tile from the source, takes care of metatiling */
823+
mapcache_tileset_tile_get_without_subdimensions(t->ctx, t->subtile->tile,
824+
(t->tile->tileset->subdimension_read_only||!t->tile->tileset->source)?1:0);
825+
t->subtile->isFetched = MAPCACHE_TRUE;
826+
#if !USE_THREADPOOL
827+
apr_thread_exit(thread, APR_SUCCESS);
828+
#endif
829+
return NULL;
830+
}
831+
#endif // APR_HAS_THREADS
832+
833+
803834
void mapcache_tileset_tile_set_get_with_subdimensions(mapcache_context *ctx, mapcache_tile *tile) {
804835
apr_array_header_t *subtiles;
805836
mapcache_extent extent;
@@ -813,6 +844,7 @@ void mapcache_tileset_tile_set_get_with_subdimensions(mapcache_context *ctx, map
813844
*/
814845
subtiles = apr_array_make(ctx->pool,1,sizeof(mapcache_subtile));
815846
st.tile = tile;
847+
st.isFetched = MAPCACHE_FALSE;
816848
APR_ARRAY_PUSH(subtiles,mapcache_subtile) = st;
817849
mapcache_grid_get_tile_extent(ctx,tile->grid_link->grid,tile->x,tile->y,tile->z,&extent);
818850
if(GC_HAS_ERROR(ctx)) goto cleanup;
@@ -856,6 +888,7 @@ void mapcache_tileset_tile_set_get_with_subdimensions(mapcache_context *ctx, map
856888
/* clone the existing subtiles if we have more than one sub-dimension to assemble for the the current dimension */
857889
for(k=1;k<single_subdimension->nelts;k++) {
858890
st.tile = mapcache_tileset_tile_clone(ctx->pool,APR_ARRAY_IDX(subtiles,j,mapcache_subtile).tile);
891+
st.isFetched = MAPCACHE_FALSE;
859892
APR_ARRAY_PUSH(subtiles,mapcache_subtile)=st;
860893
}
861894
}
@@ -872,10 +905,50 @@ void mapcache_tileset_tile_set_get_with_subdimensions(mapcache_context *ctx, map
872905

873906
/* our subtiles array now contains a list of tiles with subdimensions split up, we now need to fetch them from the cache */
874907
/* note that subtiles[0].tile == tile */
908+
#if APR_HAS_THREADS
909+
{
910+
apr_thread_t **threads;
911+
apr_threadattr_t *thread_attrs;
912+
int nthreads;
913+
_thread_subtile * thread_subtiles;
914+
915+
nthreads = 0;
916+
apr_threadattr_create(&thread_attrs, ctx->pool);
917+
thread_subtiles = (_thread_subtile*)apr_pcalloc(ctx->pool,subtiles->nelts*sizeof(_thread_subtile));
918+
threads = (apr_thread_t**)apr_pcalloc(ctx->pool,subtiles->nelts*sizeof(apr_thread_t*));
919+
for(i=subtiles->nelts-1; i>=0; i--) {
920+
int rv;
921+
thread_subtiles[i].subtile = &(APR_ARRAY_IDX(subtiles,i,mapcache_subtile));
922+
thread_subtiles[i].tile = tile;
923+
thread_subtiles[i].ctx = ctx->clone(ctx);
924+
rv = apr_thread_create(&threads[i], thread_attrs, _thread_get_subtile,
925+
(void*)&(thread_subtiles[i]), thread_subtiles[i].ctx->pool);
926+
if (rv != APR_SUCCESS) {
927+
// In case of failure creating a thread, the subtile will be fetched in the main loop below
928+
break;
929+
}
930+
nthreads++;
931+
}
932+
for(i=0 ; i<nthreads ; i++) {
933+
int rv;
934+
apr_thread_join(&rv, threads[i]);
935+
if(rv != APR_SUCCESS) {
936+
ctx->set_error(ctx,500, "thread %d of %d failed on exit\n",i,nthreads);
937+
}
938+
if(GC_HAS_ERROR(thread_subtiles[i].ctx)) {
939+
/* transfer error message from child thread to main context */
940+
ctx->set_error(ctx,thread_subtiles[i].ctx->get_error(thread_subtiles[i].ctx),
941+
thread_subtiles[i].ctx->get_error_message(thread_subtiles[i].ctx));
942+
}
943+
}
944+
}
945+
#endif // APR_HAS_THREADS
875946

876947
for(i=subtiles->nelts-1; i>=0; i--) {
877948
mapcache_tile *subtile = APR_ARRAY_IDX(subtiles,i,mapcache_subtile).tile;
878-
mapcache_tileset_tile_get_without_subdimensions(ctx, subtile, (tile->tileset->subdimension_read_only||!tile->tileset->source)?1:0); /* creates the tile from the source, takes care of metatiling */
949+
if (!APR_ARRAY_IDX(subtiles,i,mapcache_subtile).isFetched) {
950+
mapcache_tileset_tile_get_without_subdimensions(ctx, subtile, (tile->tileset->subdimension_read_only||!tile->tileset->source)?1:0); /* creates the tile from the source, takes care of metatiling */
951+
}
879952
if(GC_HAS_ERROR(ctx))
880953
goto cleanup;
881954
if(!subtile->nodata) {

0 commit comments

Comments
 (0)