Я не могу просто взять и изменить поле memory_backend: &'a mut dyn MemoryBackend на
// crate::sync::cache;
pub struct Cache<'a, T> {
memory_backend: &'a mut dyn MemoryBackend + Send + Sync,
phantom_data: core::marker::PhantomData<T>,
}
// crate::cache;
pub struct Cache<'a, T> {
memory_backend: &'a mut dyn MemoryBackend,
phantom_data: core::marker::PhantomData<T>,
}
&mut [MaybeUninit<*mut State>]
, инициализируете элементы и после std::mem::transmute
в &mut [*mut State]
TARGET
.HOST
. pub fn run<T, F>(self, event_handler: F) -> Result<(), EventLoopError>
where
F: for<'a> FnMut(Event<T>, &'a EventLoopWindowTarget<T>),
{
self.event_loop.run(event_handler)
}
Я знаю, что следует избегать всяких "продвинутых" штук из ряда связных списков, самореферентных структур и т.п.Односвязные списки никаких проблем не доставляют (ну кроме того, что они плохо ложатся на процессорный кэш). Для двусвязных списков и самореферентных структур придётся использовать сырые указатели и unsafe.
Ещё я обнаружил, что создание больших структур, с методами, с кучей полей, обычно приводит к проблемам с borrow checker.Borrow checker абсолютно плевать на размер структур. Это никак не связано.
А если в структуре будет ссылка или иное заимствование, то это гарантированные проблемы.Нет ни каких проблем.
Насколько я понимаю, самым рабочим выглядит чисто функциональный подход, а не структур с методами.Одно другому никак не противоречит.
И правильно ли я понимаю, что следует избегать структур хранящих ссылки и имеющими лайфтайм?Не правильно.
Так, наличие в умеренных размерах программе, которая по сути была одной функцией, лишь одной структуры хранящей ссылку, поставило крест на попытке структуризации программы в более человеческий вид.Что-то делаете не так. Без конкретных примеров кода сказать сложно.
И очень часто в Rust программах, мне приходится идти на более уродливую архитектуру, дабы избежать проблем с (почти ненужным в однопоточном коде) borrow checker.Что-то делаете не так. Скорее всего просто не понимаете borrow checker и пытаетесь писать на новом языке так, как привыкли в каком-то другом.
И в вопросе о borrow checker, разве не является тот факт, что большинство библиотек избегает &mut self в изменяющих что-то методах, звоночком к наличию большим проблем в языке?О каком большинстве речь? Библиотеки используют мутабельные ссылки там где это нужно. Если метод действительно что-то меняет, то будет мутабельная ссылка ну и иногда будет использоваться interior mutability там где это необходимо. В языке нет проблем с мутабельными ссылками.
В общем, посоветуйте что-то что-бы помогало меньше бороться с borrow checker, потому что сейчас я очень много времени трачу именно на это.Для начала понять его. Понять какую проблему он решает. Почитайте, что такое undefined behavior. Почитайте, что такое алиасинг.
extern C
обёртку над библиотекой и биндится уже с ней. Ну и надо понимать, что никакие абстракции плюсов вроде темплейтов, классов и т.д. в раст не протащить.Почему drop принимает ссылку, а не значение?
Причём если вызывать drop() рукамиФункция core::mem::drop никакого отношения к трейту Drop не имеет. Если Вы глянете на её реализацию, то это просто пустая функция, которая принимает аргумент по значению, а он уже дропается на общих основаниях, так как выходит из области видимости в ней.
Почему сначала вызывается drop для A, а потом для B? По логике drop должен сначала вызываться для полей.У Вас неверная логика. В метод трейта Drop приходит ссылка, а значит должна быть гарантия того что данные по ней полностью валидные. Всегда дропается сначала внешняя структура,а затем её поля. Более того компилятор не даст Вам даже мувнуть части структуры имплиментирующей Drop.
Вплоть до 29 пакета всё кажется идёт хорошо, но в 29 пакете браузер пытается отправить ACK, как я понял в ответ на FIN ACK, но похоже тут что-то не так.
У меня подозрение, что в после того как сервер в 28 пакете отправил FIN ACK он не дожидается ACK от клиента, верно ли это?
но браузер тут-же создаёт новое подключение
не присылает никаких запросов в этом подключении
поскольку я хочу просто отправить ответ и закрыть соединение
в этом варианте клиенту с сервером чуть-чуть не хватило что-бы полностью обработать последовательность:
Правильно ли я понимаю, что сервер посылая FIN ACK не дожидается ACK и в целом неверно производит завершение TCP подключения, завершая соединение раньше времени?
Именно поэтому браузер инициирует повторное подключение, но не присылает никаких данных.
Я попробовал отправлять запрос с помощью сторонней утилиты, в этом случае соединение завершается корректно
(я пробовал разные браузеры)
Cell<T>
has the same memory layout and caveats asUnsafeCell<T>
. In particular, this means thatCell<T>
has the same in-memory representation as its inner type T.
pub struct HashMap<K, V> {
table: Table<(K, V)>,
}
struct Table<T> {
// битовая маска занятых ячеек в items
mask: u64,
items: Box<[std::mem::MaybeUninit<Item<T>>; 64]>,
len: usize,
}
struct Item<T> {
data: T,
next: Option<std::ptr::NonNull<Item<T>>>,
}
pub enum Entry<'a, K, V> {
Vacant(VacantEntry<'a, K, V>),
Occupied(OccupiedEntry<'a, K, V>),
}
pub struct VacantEntry<'a, K, V> {
hash: u64,
key: K,
table: &'a mut Table<(K, V)>,
}
pub struct OccupiedEntry<'a, K, V> {
elem: Bucket<(K, V)>,
table: &'a mut Table<(K, V)>,
}
// указатель на Item.data
struct Bucket<T> {
ptr: std::ptr::NonNull<T>,
}
impl<K, V> HashMap<K, V> {
pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V>
where
K: Eq + std::hash::Hash,
{
use std::hash::Hasher as _;
let mut hasher = self.get_hasher();
key.hash(&mut hasher);
let hash = hasher.finish();
if let Some(elem) = self.table.find(hash, |(k, _)| key == *k) {
Entry::Occupied(OccupiedEntry {
elem,
table: &mut self.table,
})
} else {
Entry::Vacant(VacantEntry {
hash,
key,
table: &mut self.table,
})
}
}
fn get_hasher(&self) -> impl std::hash::Hasher {
todo!()
}
}
impl<T> Table<T> {
fn find(&self, hash: u64, is_match: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
todo!()
}
}