Сохранение размера среза [дубликат]

В этот момент существует способ сделать это непосредственно на объекте запроса:

request.setTimeout(timeout, function() {
    request.abort();
});

Это метод ярлыков, который привязывается к событию сокета, а затем создает тайм-аут.

Ссылка: Node.js v0.8.8 Manual & amp; Документация

4
задан Shepmaster 24 March 2015 в 19:16
поделиться

2 ответа

Я написал реализацию, и я рассмотрю основные моменты.

  • Полный код доступен в crates.io/arrayvec ( API doc )
  • Используйте атрибут (называемый Array) для абстракции по разным размерам массива.
/// Trait for fixed size arrays.
pub unsafe trait Array {
    /// The array's element type
    type Item;
    unsafe fn new() -> Self;
    fn as_ptr(&self) -> *const Self::Item;
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    fn capacity() -> usize;
}
  • В современном стиле ржавчины мы можем реализовать этот признак только для определенных размеров массива. Я покрываю некоторые небольшие размеры макросом:
macro_rules! fix_array_impl {
    ($len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            /// Note: Returning an uninitialized value here only works
            /// if we can be sure the data is never used. The nullable pointer
            /// inside enum optimization conflicts with this this for example,
            /// so we need to be extra careful. See `Flag` enum.
            unsafe fn new() -> [T; $len] { mem::uninitialized() }
            fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
            fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
            fn capacity() -> usize { $len }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    () => ();
    ($len:expr, $($more:expr,)*) => (
        fix_array_impl!($len);
        fix_array_impl_recursive!($($more,)*);
    );
}

fix_array_impl_recursive!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                          16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
                          32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,);
  • Нам нужно подавить падение по умолчанию встроенного массива. Вы можете сделать это теоретически используя Option<Array> и используя ptr::write, чтобы перезаписать его с помощью None в последний момент в Drop.
  • Мы должны , однако использовать наш собственный enum, по аналогии с Option по одной причине: нам нужно избегать оптимизации с нулевым указателем, которая применяется к перечислениям, которые имеют то же представление, что и Option. Затем в Drop мы делаем решающее торможение деструктора по умолчанию для внутреннего массива: мы принудительно перезаписываем наше перечисление. Конечно, только после уничтожения всех элементов.
/// Make sure the non-nullable pointer optimization does not occur!
#[repr(u8)]
enum Flag<T> {
    Dropped,
    Alive(T),
}

/// A vector with a fixed capacity.
pub struct ArrayVec<A: Array> {
    len: u8,
    xs: Flag<A>,
}

impl<A: Array> Drop for ArrayVec<A> {
    fn drop(&mut self) {
        // clear all elements, then inhibit drop of inner array
        while let Some(_) = self.pop() { }
        unsafe {
            ptr::write(&mut self.xs, Flag::Dropped);
        }
    }
}
  • Мы реализуем Deref<Target=[T]> и DerefMut и получаем тонны методов среза бесплатно. Это отличная особенность Rust!
impl<A: Array> Deref for ArrayVec<A> {
    type Target = [A::Item];
    fn deref(&self) -> &[A::Item] {
        unsafe {
            slice::from_raw_parts(self.inner_ref().as_ptr(), self.len())
        }
    }
}
  • Тип ArrayVec имеет инвариант, что Flag<A> всегда Flag::Alive(A), когда значение живое. Мы должны иметь возможность оптимизировать это с учетом этого. (Там отмечен FIXME.)
fn inner_mut(&mut self) -> &mut A {
    // FIXME: Optimize this, we know it's always present.
    match self.xs {
        Flag::Alive(ref mut xs) => xs,
        _ => unreachable!(),
    }
}

Спасибо, kmky за вопрос! Изучение этого ответа привело к созданию arrayvec, приведенному выше, и выявило некоторые моменты, которые были очень важны для обеспечения надежной структуры данных ржавчины.

5
ответ дан bluss 17 August 2018 в 08:55
поделиться

Мое предположение заключается в том, что компилятор не знает, какие элементы массива являются «свободными» и для чего нужен деструктор для запуска при отбрасывании массива.

Попробуйте сохранить Option<T>, который имеет a .take(), который позволит вам перемещать элемент из массива.

1
ответ дан Kornel 17 August 2018 в 08:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: