Mach_task_self_ не является безопасным для параллелизма, поскольку он включает в себя общее изменяемое состояние

У меня есть функция, которая возвращает использование памяти устройства. Он использует mach_task_self_, который предупреждает, что он небезопасен для параллелизма.

task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count)

Согласно этому ответу вы можете импортировать и пометить как @preconcurrency, однако когда я попробовал это, это не сработало.

@preconcurrency import Darwin.Mach.mach_init

Там написано '@preconcurrency' attribute on module 'Darwin' has no effect

Когда я перехожу к определению mach_task_self_, я вижу, что оно находится в Darwin > Mach > mach_init.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
174
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже, что @preconcurrency import не будет работать, если вещь, к которой вы пытаетесь получить доступ, также импортирована с помощью другого импорта без предварительного параллелизма. Вероятно, вы также импортируете такие вещи, как Foundation.

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

@preconcurrency import Darwin

var machTaskSelf: mach_port_t {
    mach_task_self_
}

нет никакого предупреждения.

И теперь вы можете использовать это вычисленное свойство в другом месте.

task_info(machTaskSelf, task_flavor_t(TASK_VM_INFO), intPtr, &count)

Несмотря на то, что это удаляет предупреждение об импорте @preconcurrency, оно все равно выдает предупреждение о том, что mach_task_self_ небезопасен для параллелизма.

Darren 12.06.2024 13:15

Странный. Он делает это как в моей основной структуре, так и в небольшом тестовом приложении, которое я создал специально для этого здесь file.io/LyHve5khA1bt Я также пробовал новый Xcode и Swift 6, но он тот же.

Darren 12.06.2024 13:39

Да! Я действовал на автопилоте и даже не заметил этого. Спасибо.

Darren 12.06.2024 14:04

Собственно, хотя в новом тестовом проекте это работает. Он по-прежнему выдает мне ошибки в моем основном проекте Framework. В новом файле есть только импорт preconcurrency и переменная machTaskSelf, но я получаю сообщение об ошибке, связанное с отсутствием эффекта предварительного параллелизма. Может ли это быть связано с порядком компиляции файлов?

Darren 12.06.2024 15:04

@Даррен Хорошо, мне удалось воспроизвести это в проекте SPM (в отличие от проекта Xcode). Согласно это, «импорт из других языков осуществляется неявно @preconcurrency», поэтому вы можете просто удалить @preconcurrency. Поэтому я предполагаю, что, по-видимому, Darwin считается «из другого языка» в проекте SPM, но не в проекте Xcode.

Sweeper 12.06.2024 15:25

Интересный. Однако удаление pre concurrency по-прежнему приводит к фактическому mach_task_self_ сообщению, что он небезопасен для параллелизма.

Darren 12.06.2024 15:39

Интересно, что если полностью удалить import Darwin и оставить в файле только machTaskSelf var, проект компилируется нормально. Значит, он, должно быть, импортирует его откуда-то еще.

Darren 12.06.2024 15:41

@Даррен, почему ты не принял? Насколько я вижу из вашего последнего комментария, ваша проблема решена. Если вы тоже хотите, чтобы я объяснил, откуда импортирован mach_task_self_? Это другой вопрос, и вам нужно будет показать минимально воспроизводимый пример.

Sweeper 13.06.2024 01:59

Извините, я не знал, что могу не принять. Моя проблема не решена. Сам проект находится здесь github.com/ddaddy/DJLogging-Swift и использование вашего решения приводит к ошибке компилятора при использовании Swift 6, чего я пытаюсь избежать.

Darren 13.06.2024 23:49

Я вижу замешательство. Мой комментарий по поводу компиляции проекта просто указывал на то, что мне вообще не нужен импорт. Он по-прежнему быстро предупреждает, что mach_task_self_ небезопасен для параллелизма.

Darren 14.06.2024 15:35

@Даррен, я понимаю. Я думаю, что понять, почему вам не нужен импорт для Дарвина, — это хороший первый шаг. После того, как вы это выясните, попробуйте сделать так, чтобы вам действительно требовался импорт. Тогда импорт @preconcurrency, вероятно, сработает. Это все, что я хочу сказать.

Sweeper 14.06.2024 15:49

Понятно :) Поскольку Framework поддерживает objc, у него есть публичный заголовок, который импортирует Foundation. Удаление удалило предупреждение. Спасибо.

Darren 14.06.2024 17:09

Мне отлично помогло и с другими mach проблемами: @preconcurrency import Darwin var vm_kernel_page_size: vm_size_t { Darwin.vm_kernel_page_size }

adamz 15.07.2024 21:02

Ранее сегодня я столкнулся с той же проблемой и в итоге нашел обходной путь, чтобы избавиться от предупреждений.

Мне пришлось немного побаловаться с Objective-C, но это позволило мне написать оболочку для mach_task_self_, которая заимствует изоляцию актеров Swift, чтобы мы могли безопасно получать доступ к данным.

Я создал класс со статическим свойством, которое инициализируется сразу после загрузки фреймворка, и все последующие обращения к атрибуту синхронизируются внутри. В моем случае это прекрасно сработало, надеюсь, вам это тоже поможет!

MyMachTaskWrapper.h:

@import Foundation;
@import Darwin;

__attribute__((swift_attr("@MainActor")))
@interface MyMachTaskWrapper: NSObject

@property(class) mach_port_t isolatedMachTaskSelf;

@end

MyMachTaskWrapper.m:

#import "MyMachTaskWrapper.h"

@implementation MyMachTaskWrapper

static mach_port_t isolated_mach_task_self_;

// Invoked when this class is added to the Objective-C runtime
+ (void)load {
  [self setIsolatedMachTaskSelf:mach_task_self_];
}

// Just to be sure I decided to synchronize reads with a mutex lock,
// but I'm not completely sure if this is needed
+ (mach_port_t)isolatedMachTaskSelf {
  @synchronized(self) {
    return isolated_mach_task_self_;
  }
}

// This should only ever run on `load`
+ (void)setIsolatedMachTaskSelf:(mach_port_t)task {
    isolated_mach_task_self_ = task;
}

@end

Конечно, вам нужно будет предоставить этот класс Swift. После этого использование будет таким же простым, как:

Task { @MainActor in
  MyMachTaskWrapper.isolatedMachTaskSelf // no warnings here!
}

Обратите внимание, что Swift воспринимает MyMachTaskWrapper как @MainActor, поэтому мы должны убедиться, что работаем в правильном контексте.

Идея написать эту обертку пришла мне от SE-0412, в которой говорится:

Остаются инструменты для обеспечения безопасности импортированных глобальных переменных из других языков, такие как изоляция глобального актера с использованием, например, атрибута((swift_attr("@MainActor"))) в C или Obj-C или перенос доступа в более безопасный API. который объявляет правильную изоляцию или блокирует соответствующим образом.

Я до сих пор не уверен, что это лучший подход, но у меня он работает :)

Спасибо. Я только что попробовал это, но получаю сообщение об ошибке «Использование заголовков моста с целями платформы не поддерживается», поэтому я думаю, что смешивание objc и Swift может быть здесь не лучшей идеей.

Darren 14.06.2024 15:34

@Даррен, взгляни на эту ссылку?. Вам придется предпринять дополнительные шаги, чтобы заставить его работать для целей платформы, но это наверняка возможно! Я знаю, потому что делал это раньше :) Вам просто нужно придумать заголовок зонтика, и все готово.

vcoutasso 14.06.2024 15:45

Другие вопросы по теме