Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

<style>
body                { margin: 0; }
pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }

.lifetime           { color: #DFAF8F; font-style: italic; }
.label              { color: #DFAF8F; font-style: italic; }
.comment            { color: #7F9F7F; }
.documentation      { color: #629755; }
.intra_doc_link     { font-style: italic; }
.injected           { opacity: 0.65 ; }
.struct, .enum      { color: #7CB8BB; }
.enum_variant       { color: #BDE0F3; }
.string_literal     { color: #CC9393; }
.field              { color: #94BFF3; }
.function           { color: #93E0E3; }
.function.unsafe    { color: #BC8383; }
.trait.unsafe       { color: #BC8383; }
.operator.unsafe    { color: #BC8383; }
.mutable.unsafe     { color: #BC8383; text-decoration: underline; }
.keyword.unsafe     { color: #BC8383; font-weight: bold; }
.macro.unsafe       { color: #BC8383; }
.parameter          { color: #94BFF3; }
.text               { color: #DCDCCC; }
.type               { color: #7CB8BB; }
.builtin_type       { color: #8CD0D3; }
.type_param         { color: #DFAF8F; }
.attribute          { color: #94BFF3; }
.numeric_literal    { color: #BFEBBF; }
.bool_literal       { color: #BFE6EB; }
.macro              { color: #94BFF3; }
.proc_macro         { color: #94BFF3; text-decoration: underline; }
.derive             { color: #94BFF3; font-style: italic; }
.module             { color: #AFD8AF; }
.value_param        { color: #DCDCCC; }
.variable           { color: #DCDCCC; }
.format_specifier   { color: #CC696B; }
.mutable            { text-decoration: underline; }
.escape_sequence    { color: #94BFF3; }
.keyword            { color: #F0DFAF; font-weight: bold; }
.control            { font-style: italic; }
.reference          { font-style: italic; font-weight: bold; }
.const              { font-weight: bolder; }

.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
</style>
<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>

<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
    <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span><span class="none injected">
</span><span class="keyword injected">trait</span><span class="none injected"> </span><span class="trait declaration injected">Foo</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
    </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function associated declaration injected static trait">foo</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
        </span><span class="unresolved_reference injected">println</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="string_literal injected macro">"2 + 2 = {}"</span><span class="comma injected macro">,</span><span class="none injected"> </span><span class="numeric_literal injected macro">4</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span><span class="none injected">
    </span><span class="brace injected">}</span><span class="none injected">
</span><span class="brace injected">}</span><span class="string_literal">"#</span>
    <span class="parenthesis">)</span><span class="semicolon">;</span>
    <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r"</span><span class="none injected">
</span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function declaration injected">foo</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
    </span><span class="function injected">foo</span><span class="parenthesis injected">(</span><span class="keyword injected">$0</span><span class="brace injected">{</span><span class="none injected">
        </span><span class="numeric_literal injected">92</span><span class="none injected">
    </span><span class="brace injected">}</span><span class="keyword injected">$0</span><span class="parenthesis injected">)</span><span class="none injected">
</span><span class="brace injected">}</span><span class="string_literal">"</span>
    <span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span></code></pre>
s(self); set_current_thread_qos_class(class); } pub(super) fn assert_is_used_on_current_thread(self) { if IS_QOS_AVAILABLE { let class = thread_intent_to_qos_class(self); assert_eq!(get_current_thread_qos_class(), Some(class)); } } } use imp::QoSClass; const IS_QOS_AVAILABLE: bool = imp::IS_QOS_AVAILABLE; #[expect(clippy::semicolon_if_nothing_returned, reason = "thin wrapper")] fn set_current_thread_qos_class(class: QoSClass) { imp::set_current_thread_qos_class(class) } fn get_current_thread_qos_class() -> Option<QoSClass> { imp::get_current_thread_qos_class() } fn thread_intent_to_qos_class(intent: ThreadIntent) -> QoSClass { imp::thread_intent_to_qos_class(intent) } // All Apple platforms use XNU as their kernel // and thus have the concept of QoS. #[cfg(target_vendor = "apple")] mod imp { use super::ThreadIntent; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] // Please maintain order from least to most priority for the derived `Ord` impl. pub(super) enum QoSClass { // Documentation adapted from https://github.com/apple-oss-distributions/libpthread/blob/67e155c94093be9a204b69637d198eceff2c7c46/include/sys/qos.h#L55 // /// TLDR: invisible maintenance tasks /// /// Contract: /// /// * **You do not care about how long it takes for work to finish.** /// * **You do not care about work being deferred temporarily.** /// (e.g. if the device's battery is in a critical state) /// /// Examples: /// /// * in a video editor: /// creating periodic backups of project files /// * in a browser: /// cleaning up cached sites which have not been accessed in a long time /// * in a collaborative word processor: /// creating a searchable index of all documents /// /// Use this QoS class for background tasks /// which the user did not initiate themselves /// and which are invisible to the user. /// It is expected that this work will take significant time to complete: /// minutes or even hours. /// /// This QoS class provides the most energy and thermally-efficient execution possible. /// All other work is prioritized over background tasks. Background, /// TLDR: tasks that don't block using your app /// /// Contract: /// /// * **Your app remains useful even as the task is executing.** /// /// Examples: /// /// * in a video editor: /// exporting a video to disk – /// the user can still work on the timeline /// * in a browser: /// automatically extracting a downloaded zip file – /// the user can still switch tabs /// * in a collaborative word processor: /// downloading images embedded in a document – /// the user can still make edits /// /// Use this QoS class for tasks which /// may or may not be initiated by the user, /// but whose result is visible. /// It is expected that this work will take a few seconds to a few minutes. /// Typically your app will include a progress bar /// for tasks using this class. /// /// This QoS class provides a balance between /// performance, responsiveness, and efficiency. Utility, /// TLDR: tasks that block using your app /// /// Contract: /// /// * **You need this work to complete /// before the user can keep interacting with your app.** /// * **Your work will not take more than a few seconds to complete.** /// /// Examples: /// /// * in a video editor: /// opening a saved project /// * in a browser: /// loading a list of the user's bookmarks and top sites /// when a new tab is created /// * in a collaborative word processor: /// running a search on the document's content /// /// Use this QoS class for tasks which were initiated by the user /// and block the usage of your app while they are in progress. /// It is expected that this work will take a few seconds or less to complete; /// not long enough to cause the user to switch to something else. /// Your app will likely indicate progress on these tasks /// through the display of placeholder content or modals. /// /// This QoS class is not energy-efficient. /// Rather, it provides responsiveness /// by prioritizing work above other tasks on the system /// except for critical user-interactive work. UserInitiated, /// TLDR: render loops and nothing else /// /// Contract: /// /// * **You absolutely need this work to complete immediately /// or your app will appear to freeze.** /// * **Your work will always complete virtually instantaneously.** /// /// Examples: /// /// * the main thread in a GUI application /// * the update & render loop in a game /// * a secondary thread which progresses an animation /// /// Use this QoS class for any work which, if delayed, /// will make your user interface unresponsive. /// It is expected that this work will be virtually instantaneous. /// /// This QoS class is not energy-efficient. /// Specifying this class is a request to run with /// nearly all available system CPU and I/O bandwidth even under contention. UserInteractive, } pub(super) const IS_QOS_AVAILABLE: bool = true; pub(super) fn set_current_thread_qos_class(class: QoSClass) { let c = match class { QoSClass::UserInteractive => libc::qos_class_t::QOS_CLASS_USER_INTERACTIVE, QoSClass::UserInitiated => libc::qos_class_t::QOS_CLASS_USER_INITIATED, QoSClass::Utility => libc::qos_class_t::QOS_CLASS_UTILITY, QoSClass::Background => libc::qos_class_t::QOS_CLASS_BACKGROUND, }; let code = unsafe { libc::pthread_set_qos_class_self_np(c, 0) }; if code == 0 { return; } let errno = unsafe { *libc::__error() }; match errno { libc::EPERM => { // This thread has been excluded from the QoS system // due to a previous call to a function such as `pthread_setschedparam` // which is incompatible with QoS. // // Panic instead of returning an error // to maintain the invariant that we only use QoS APIs. panic!("tried to set QoS of thread which has opted out of QoS (os error {errno})") } libc::EINVAL => { // This is returned if we pass something other than a qos_class_t // to `pthread_set_qos_class_self_np`. // // This is impossible, so again panic. unreachable!( "invalid qos_class_t value was passed to pthread_set_qos_class_self_np" ) } _ => { // `pthread_set_qos_class_self_np`'s documentation // does not mention any other errors. unreachable!("`pthread_set_qos_class_self_np` returned unexpected error {errno}") } } } pub(super) fn get_current_thread_qos_class() -> Option<QoSClass> { let current_thread = unsafe { libc::pthread_self() }; let mut qos_class_raw = libc::qos_class_t::QOS_CLASS_UNSPECIFIED; let code = unsafe { libc::pthread_get_qos_class_np(current_thread, &mut qos_class_raw, std::ptr::null_mut()) }; if code != 0 { // `pthread_get_qos_class_np`'s documentation states that // an error value is placed into errno if the return code is not zero. // However, it never states what errors are possible. // Inspecting the source[0] shows that, as of this writing, it always returns zero. // // Whatever errors the function could report in future are likely to be // ones which we cannot handle anyway // // 0: https://github.com/apple-oss-distributions/libpthread/blob/67e155c94093be9a204b69637d198eceff2c7c46/src/qos.c#L171-L177 let errno = unsafe { *libc::__error() }; unreachable!("`pthread_get_qos_class_np` failed unexpectedly (os error {errno})"); } match qos_class_raw { libc::qos_class_t::QOS_CLASS_USER_INTERACTIVE => Some(QoSClass::UserInteractive), libc::qos_class_t::QOS_CLASS_USER_INITIATED => Some(QoSClass::UserInitiated), libc::qos_class_t::QOS_CLASS_DEFAULT => None, // QoS has never been set libc::qos_class_t::QOS_CLASS_UTILITY => Some(QoSClass::Utility), libc::qos_class_t::QOS_CLASS_BACKGROUND => Some(QoSClass::Background), libc::qos_class_t::QOS_CLASS_UNSPECIFIED => { // Using manual scheduling APIs causes threads to “opt out” of QoS. // At this point they become incompatible with QoS, // and as such have the “unspecified” QoS class. // // Panic instead of returning an error // to maintain the invariant that we only use QoS APIs. panic!("tried to get QoS of thread which has opted out of QoS") } } } pub(super) fn thread_intent_to_qos_class(intent: ThreadIntent) -> QoSClass { match intent { ThreadIntent::Worker => QoSClass::Utility, ThreadIntent::LatencySensitive => QoSClass::UserInitiated, } } } // FIXME: Windows has QoS APIs, we should use them! #[cfg(not(target_vendor = "apple"))] mod imp { use super::ThreadIntent; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub(super) enum QoSClass { Default, } pub(super) const IS_QOS_AVAILABLE: bool = false; pub(super) fn set_current_thread_qos_class(_: QoSClass) {} pub(super) fn get_current_thread_qos_class() -> Option<QoSClass> { None } pub(super) fn thread_intent_to_qos_class(_: ThreadIntent) -> QoSClass { QoSClass::Default } }