I have a function that returns the memory use of a device. It uses mach_task_self_
which gives a warning that it is not concurrency-safe.
task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count)
According to this answer you can import and mark as @preconcurrency
however when I try this it doesn’t work.
@preconcurrency import Darwin.Mach.mach_init
It says '@preconcurrency' attribute on module 'Darwin' has no effect
When I jump to the definition of mach_task_self_
it shows me it is in Darwin > Mach > mach_init
2
Answers
It seems like a
@preconcurrency import
won’t work if the thing you are trying to access is also imported by another non-preconcurrency import. Presumably, you are also importing things likeFoundation
.If you put the import in a separate file,
there is no warning.
And now you can use this computed property elsewhere.
I ran into the same issue earlier today and ended up coming up with a workaround to get rid of the warnings.
I had to dabble a bit with Objective-C, but that allowed me to write a wrapper to
mach_task_self_
that borrows Swift’s actor isolation such that we can safely access the data.I created a class with a static property that is initialized as soon as the framework is loaded and all subsequent accesses to the attribute are synchronized internally. It worked beautifully for my use case, I hope it helps you too!
MyMachTaskWrapper.h
:MyMachTaskWrapper.m
:Of course, you will need to expose this class to Swift. After that, the usage is as simple as:
Note that Swift sees
MyMachTaskWrapper
as a@MainActor
, so we must ensure we’re working on the right context.I got the idea of writing this wrapper from SE-0412, which states:
I’m still not sure if this is the best approach, but it works for me 🙂