В этот момент существует способ сделать это непосредственно на объекте запроса:
request.setTimeout(timeout, function() {
request.abort();
});
Это метод ярлыков, который привязывается к событию сокета, а затем создает тайм-аут.
Я написал реализацию, и я рассмотрю основные моменты.
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
. 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())
}
}
}
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
, приведенному выше, и выявило некоторые моменты, которые были очень важны для обеспечения надежной структуры данных ржавчины.
Мое предположение заключается в том, что компилятор не знает, какие элементы массива являются «свободными» и для чего нужен деструктор для запуска при отбрасывании массива.
Попробуйте сохранить Option<T>
, который имеет a .take()
, который позволит вам перемещать элемент из массива.