amarao: (Default)
amarao ([personal profile] amarao) wrote2021-03-14 11:53 pm
Entry tags:

Как безопасно сделать небезопасно?

Я пока не до конца уверен, что я в правильном направлени иду, но вот какая у меня идея:

Мне нужно в новый тред отдавать ссылки только со 'static, а я хочу туда отдать (из метода структуры) ссылку на кусок "себя". Что, очевидно, нарушает 'static, потому что если "себя" сделают drop() по выходу из блока/функции, будет danging pointer, а весь раст строился вокруг того, чтобы такого не было. И нужно именно так сделать.

Задача: сохранить инвариант. Т.е. сделать так, чтобы при drop() себя, отданная ранее в соседний тред ссылка была бы жива. Это традиционная задача AI tetris (https://www.youtube.com/embed/xOCurBYI_gY?start=910&feature=oembed&enablejsapi=1), и она прекрасно решается с помощью bottom type.

impl Drop for Screen{
    fn drop(&mut self){
        if let Some(..) = self.thread {
            println!("Attempt to drop Screen. Looping forever.");
            loop{}
        }
    }
}

Такой подход гарантирует: а) что ссылка жива до конца программы. б) что структуру можно создавать с не 'static lifetime, потому что есть drop().

В самой программе нужно, конечно, выходить не через return:

        match event {
            Event::Quit { .. }
            | Event::KeyDown {
                keycode: Some(Keycode::Escape),
                ..
            } => std::process::exit(0),
            _ => {}
        }

Это была простая часть. А теперь сложная - как бы мне сделать mut slice и slice на один и тот же набор данных, чтобы мне за это не особо много влетело?

stay tuned.

ufm: (Default)

[personal profile] ufm 2021-03-14 10:32 pm (UTC)(link)
А в расте разве нет ничего похожего на "ссылка со счётчиком"? Или я совсем не туда и этим способом твоя задача не решается?

[personal profile] permeakra 2021-03-15 08:42 am (UTC)(link)
Почему нельзя посмотреть, как реализован std::RwLock ?
ufm: (Default)

[personal profile] ufm 2021-03-15 09:01 am (UTC)(link)
Я посмотрел. Уперся в
    pub unsafe fn read(&self) {
        self.0.read()
    }

и понял что это уже выше моего понимания.
ufm: (Default)

[personal profile] ufm 2021-03-15 08:23 pm (UTC)(link)
Почему там usafe - мне понятно. Я не понимаю что такое self.0 - я-же подробно язык не изучал.
ufm: (Default)

[personal profile] ufm 2021-03-15 08:54 pm (UTC)(link)
У меня, как ты понимаешь, сразу куча вопросов:
1. а x.i сделать можно?
2. а x[0]? А почему?
3. а к элементу массива/слайса так обратиться можно?
ufm: (Default)

[personal profile] ufm 2021-03-15 09:11 pm (UTC)(link)
В go есть такой тип - interface{}
Он позволяет объявить безтиповую переменную.
В rust нет ничего похожего?
ufm: (Default)

[personal profile] ufm 2021-03-16 01:09 pm (UTC)(link)
func main() {
    var a interface{}
    a = 5
    fmt.Println(a)
    a = "string"
    fmt.Println(a)
}
ufm: (Default)

[personal profile] ufm 2021-03-16 04:15 pm (UTC)(link)
Ок, давай по другому.
Как в rust сделать так:

func main() {
    m := make(map[int]interface{})
    m[1] = 1
    m[2] = "two"
    m[3] = 3.14

    for i, val := range m {
        fmt.Printf("m[%d] == %v\n", i, val)
    }
}
ufm: (Default)

[personal profile] ufm 2021-03-15 08:51 am (UTC)(link)
Ээээ. Мне казалось что без unsafe такое в расте принципиально сделать нельзя, так как это противоречит идеологии?
ufm: (Default)

[personal profile] ufm 2021-03-15 08:38 pm (UTC)(link)
Мне не очень нравится такой подход. (Мне вобще не очень нравится раст как язык, но это вкусовщина, мы сейчас именно о концепциях).

Это тебе "джаст фо фан" интересно сделать всё правильно. А я уверен, что найдётся уйма программистов, которые по какой либо из причин (сроки поджимают, лень разбираться, "я достаточно умный и понимаю что делаю") в этом месте обернут код в unsafe и не будут париться.

Понимаешь, если в обычном Си/СиПиПи все знают и уже привыкли - "это язык для стреляния себе в ногу, поэтому нужно быть внимательным и не расслабляться", то в расте на слуху "это специальный язык, тут нельзя выстрелить себе в ногу". Но когда начинаешь разбираться - выясняется что выстрелить можно. Более того - иногда прям хочется обернуть всё в один большой unsafe и перестать испытывать анальную боль, потому что компилятор постоянно бъёт по рукам (руки и анальная боль в одной фразе - это не случайно).

Да, я понимаю что по другому сделать нельзя, скорее всего, если мы делаем язык на котором можно лазить к железу, например. Но блин.