Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  tile_pool.rs   Sprache: unbekannt

 
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::sync::Arc;

const NUM_TILE_BUCKETS: usize = 6;

/// A pool of blob tile buffers to mitigate the overhead of
/// allocating and deallocating blob tiles.
///
/// The pool keeps a strong reference to each allocated buffers and
/// reuses the ones with a strong count of 1.
pub struct BlobTilePool {
    largest_size_class: usize,
    buckets: [Vec<Arc<Vec<u8>>>; NUM_TILE_BUCKETS],
}

impl BlobTilePool {
    pub fn new() -> Self {
        // The default max tile size is actually 256, using 512 here
        // so that this still works when experimenting with larger
        // tile sizes. If we ever make larger adjustments, the buckets
        // should be changed accordingly.
        let max_tile_size = 512;
        BlobTilePool {
            largest_size_class: max_tile_size * max_tile_size * 4,
            buckets: [
                Vec::with_capacity(32),
                Vec::with_capacity(32),
                Vec::with_capacity(32),
                Vec::with_capacity(32),
                Vec::with_capacity(32),
                Vec::with_capacity(32),
            ],
        }
    }

    /// Get or allocate a tile buffer of the requested size.
    ///
    /// The returned buffer is zero-inizitalized.
    /// The length of the returned buffer is equal to the requested size,
    /// however the buffer may be allocated with a larger capacity to
    /// conform to the pool's corresponding bucket tile size.
    pub fn get_buffer(&mut self, requested_size: usize) -> MutableTileBuffer {
        if requested_size > self.largest_size_class {
            // If the requested size is larger than the largest size class,
            // simply return a MutableBuffer that isn't tracked/recycled by
            // the pool.
            // In Firefox this should only happen in pathological cases
            // where the blob visible area ends up so large that the tile
            // size is increased to avoid producing too many tiles.
            // See wr_resource_updates_add_blob_image.
            let mut buf = vec![0; requested_size];
            return MutableTileBuffer {
                ptr: buf.as_mut_ptr(),
                strong_ref: Arc::new(buf),
            };
        }

        let (bucket_idx, cap) = self.bucket_and_size(requested_size);
        let bucket = &mut self.buckets[bucket_idx];
        let mut selected_idx = None;
        for (buf_idx, buffer) in bucket.iter().enumerate() {
            if Arc::strong_count(buffer) == 1 {
                selected_idx = Some(buf_idx);
                break;
            }
        }

        let ptr;
        let strong_ref;
        if let Some(idx) = selected_idx {
            {
                // This works because we just ensured the pool has the only strong
                // ref to the buffer.
                let buffer = Arc::get_mut(&mut bucket[idx]).unwrap();
                debug_assert!(buffer.capacity() >= requested_size);
                // Ensure the length is equal to the requested size. It's not
                // strictly necessay for the tile pool but the texture upload
                // code relies on it.
                unsafe { buffer.set_len(requested_size); }

                // zero-initialize
                buffer.fill(0);

                ptr = buffer.as_mut_ptr();
            }
            strong_ref = Arc::clone(&bucket[idx]);
        } else {
            // Allocate a buffer with the adequate capacity for the requested
            // size's bucket.
            let mut buf = vec![0; cap];
            // Force the length to be the requested size.
            unsafe { buf.set_len(requested_size) };

            ptr = buf.as_mut_ptr();
            strong_ref = Arc::new(buf);
            // Track the new buffer.
            bucket.push(Arc::clone(&strong_ref));
        };

        MutableTileBuffer {
            ptr,
            strong_ref,
        }
    }

    fn bucket_and_size(&self, size: usize) -> (usize, usize) {
        let mut next_size_class = self.largest_size_class / 4;
        let mut idx = 0;
        while size < next_size_class && idx < NUM_TILE_BUCKETS - 1 {
            next_size_class /= 4;
            idx += 1;
        }

        (idx, next_size_class * 4)
    }

    /// Go over all allocated tile buffers. For each bucket, deallocate some buffers
    /// until the number of unused buffer is more than half of the buffers for that
    /// bucket.
    ///
    /// In practice, if called regularly, this gradually lets go of blob tiles when
    /// they are not used.
    pub fn cleanup(&mut self) {
        for bucket in &mut self.buckets {
            let threshold = bucket.len() / 2;
            let mut num_available = 0;
            bucket.retain(&mut |buffer: &Arc<Vec<u8>>| {
                if Arc::strong_count(buffer) > 1 {
                    return true;
                }

                num_available += 1;
                num_available < threshold
            });
        }
    }
}


// The role of tile buffer is to encapsulate an Arc to the underlying buffer
// with a reference count of at most 2 and a way to view the buffer's content
// as a mutable slice, even though the reference count may be more than 1.
// The safety of this relies on the other strong reference being held by the
// tile pool which never accesses the buffer's content, so the only reference
// that can access it is the `TileBuffer` itself.
pub struct MutableTileBuffer {
    strong_ref: Arc<Vec<u8>>,
    ptr: *mut u8,
}

impl MutableTileBuffer {
    pub fn as_mut_slice(&mut self) -> &mut[u8] {
        unsafe { std::slice::from_raw_parts_mut(self.ptr, self.strong_ref.len()) }
    }

    pub fn into_arc(self) -> Arc<Vec<u8>> {
        self.strong_ref
    }
}

unsafe impl Send for MutableTileBuffer {}

[ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge