void TopographyThread::Trigger(const WindowProjection &_projection) { assert(_projection.IsValid()); const GeoBounds new_bounds = _projection.GetScreenBounds(); if (last_bounds.IsValid() && last_bounds.IsInside(new_bounds)) { /* still inside cache bounds - now check if we crossed a scale threshold for at least one file, which would mean we have to update a file which was not updated for the current cache bounds */ if (scale_threshold < 0 || _projection.GetMapScale() >= scale_threshold) /* the cache is still fresh */ return; } last_bounds = new_bounds.Scale(1.1); scale_threshold = store.GetNextScaleThreshold(_projection.GetMapScale()); { const ScopeLock protect(mutex); next_projection = _projection; StandbyThread::Trigger(); } }
bool TopographyFile::Update(const WindowProjection &map_projection) { if (IsEmpty()) return false; if (map_projection.GetMapScale() > scale_threshold) /* not visible, don't update cache now */ return false; const GeoBounds screenRect = map_projection.GetScreenBounds(); if (cache_bounds.IsValid() && cache_bounds.IsInside(screenRect)) /* the cache is still fresh */ return false; cache_bounds = screenRect.Scale(2); rectObj deg_bounds = ConvertRect(cache_bounds); // Test which shapes are inside the given bounds and save the // status to file.status switch (msShapefileWhichShapes(&file, dir, deg_bounds, 0)) { case MS_FAILURE: ClearCache(); return false; case MS_DONE: /* screen is outside of map bounds */ return false; case MS_SUCCESS: break; } assert(file.status != nullptr); // Iterate through the shapefile entries const ShapeList **current = &first; auto it = shapes.begin(); for (int i = 0; i < file.numshapes; ++i, ++it) { if (!msGetBit(file.status, i)) { // If the shape is outside the bounds // delete the shape from the cache if (it->shape != nullptr) { assert(*current == it); /* remove from linked list (protected) */ { const ScopeLock lock(mutex); *current = it->next; ++serial; } /* now it's unreachable, and we can delete the XShape without holding a lock */ delete it->shape; it->shape = nullptr; } } else { // is inside the bounds if (it->shape == nullptr) { assert(*current != it); // shape isn't cached yet -> cache the shape it->shape = LoadShape(&file, center, i, label_field); it->next = *current; /* insert into linked list (protected) */ { const ScopeLock lock(mutex); *current = it; ++serial; } } current = &it->next; } } // end of list marker assert(*current == nullptr); return true; }