Можем ли мы использовать C struct API непосредственно из Swift? - PullRequest
2 голосов
/ 27 апреля 2020

Я ушел из WWD C 2016 с пониманием, что мы должны быть осторожны с использованием C API struct на основе непосредственно из Swift. В Параллельное программирование С GCD в Swift 3 , говоря о C блокировках, они были очень специфичны c:

... И в Swift, так как вы Если в вашем распоряжении будет весь модуль Дарвина, вы действительно увидите традиционные C замки на основе struct. Однако Swift предполагает, что все, что является struct, может быть перемещено, и это не работает с мьютексом или с блокировкой. Поэтому мы действительно не рекомендуем вам использовать подобные замки от Swift. ...

... И если вы хотите что-то ... похожее на блокировки, которые есть у вас в C, тогда вам нужно вызвать Objective- C и ввести базовый класс в Цель - C, в которой ваш замок - ивар.

А затем вы откроете методы lock и unlock и tryLock, если он вам также понадобится, что вы сможете позвонить из Swift, когда вы будете подкласс этого класса. ...

@implementation LockableObject {
    os_unfair_lock _lock;
}

- (void)lock   { os_unfair_lock_lock(&_lock); }
- (void)unlock { os_unfair_lock_unlock(&_lock); }
@end

Однако, наблюдая за WWD C 2019 Развитие отличного опыта профилирования , я замечаю, что автор использует os_unfair_lock непосредственно из Swift, без эта оболочка Objective- C, по сути:

private var workItemsLock = os_unfair_lock()

func subWorkItem(...) {
    ...
    os_unfair_lock_lock(&self.workItemsLock)
    ...
    os_unfair_lock_unlock(&self.workItemsLock)
    ...
}

Эмпирически, этот вид прямого использования os_unfair_lock, кажется, работает, но это ничего не значит. Уважая предостережение в видео WWD C 2016 года, я воздерживался от использования os_unfair_lock непосредственно от Swift.

Итак, вопрос в том, не слишком ли они небрежны в использовании этого API в этом образце 2019 года? Или видео 2016 года было неверным в своих заявлениях? Или изменилась обработка C на основе *1043* со времен Swift 3, что теперь делает этот шаблон безопасным?

1 Ответ

1 голос
/ 30 апреля 2020

Пример API с использованием private var workItemsLock = os_unfair_lock() может быть справедливым во время выполнения.

Примитивам потоков из C требуется стабильное расположение в памяти, чтобы использовать их или другую структуру, которая имеет один из этих примитивов непосредственно в качестве членом этого вы должны использовать UnsafePointer. Причина этого в том, что UnsafePointer API, после того как они выделили кусок памяти, эта память стабильна и не может быть перемещена или тривиально скопирована компилятором.

Если вы измените пример таким образом, он теперь действителен

private var workItemsLock: UnsafeMutablePointer<os_unfair_lock> = {
    // Note, somewhere else this will need to be deallocated
    var pointer = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
    pointer.initialize(to: os_unfair_lock())
    return pointer
}()

func subWorkItem(...) {
    ...
    os_unfair_lock_lock(self.workItemsLock)
    ...
    os_unfair_lock_unlock(self.workItemsLock)
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...