OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
thread_priority.hpp
1#pragma once
2
3#include <ossia/detail/sleep.hpp>
4#if defined(_WIN32)
5#include <mmsystem.h>
6#include <avrt.h>
7#endif
8
9namespace ossia
10{
11
12struct priority_boost_handle
13{
14public:
15 explicit priority_boost_handle(double frequencyHz)
16 {
17#if defined(_WIN32)
18 // Timer resolution already increased in main()
19
20 // MMCSS priority boost
21 DWORD taskIndex = 0;
22 m_mmcss = AvSetMmThreadCharacteristicsW(L"Pro Audio", &taskIndex);
23 if (m_mmcss)
24 {
25 AvSetMmThreadPriority(m_mmcss, AVRT_PRIORITY_CRITICAL);
26 }
27#elif defined(__APPLE__)
28 // Set real-time thread policy with time constraint
29 // This tells the scheduler we need periodic execution
30 mach_port_t threadPort = pthread_mach_thread_np(pthread_self());
31
32 // Convert frequency to period in mach absolute time units
33 double periodNs = 1'000'000'000.0 / frequencyHz;
34 uint32_t periodMach = static_cast<uint32_t>(periodNs * detail::g_timebase_info.denom / detail::g_timebase_info.numer);
35
36 thread_time_constraint_policy_data_t policy;
37 policy.period = periodMach; // Nominal period
38 policy.computation = periodMach / 10; // Max computation time (~10% of period)
39 policy.constraint = periodMach / 2; // Must complete within half period
40 policy.preemptible = 1; // Can be preempted
41
42 kern_return_t kr = thread_policy_set(
43 threadPort,
44 THREAD_TIME_CONSTRAINT_POLICY,
45 reinterpret_cast<thread_policy_t>(&policy),
46 THREAD_TIME_CONSTRAINT_POLICY_COUNT
47 );
48
49 m_policy_set = (kr == KERN_SUCCESS);
50
51 if (!m_policy_set)
52 {
53 // Fallback: at least set high QoS
54 pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0);
55 }
56#else
57 // Save original scheduling policy
58 pthread_getschedparam(pthread_self(), &m_original_policy, &m_original_param);
59
60 // Try to set SCHED_FIFO
61 struct sched_param param;
62 param.sched_priority = sched_get_priority_max(SCHED_FIFO);
63
64 if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &param) == 0)
65 {
66 m_elevated = true;
67 }
68 else
69 {
70 // Fallback: set highest nice value we can
71 setpriority(PRIO_PROCESS, 0, -20);
72 }
73#endif
74 }
75
76 ~priority_boost_handle()
77 {
78#if defined(_WIN32)
79 if (m_mmcss)
80 {
81 AvRevertMmThreadCharacteristics(m_mmcss);
82 m_mmcss = nullptr;
83 }
84#elif defined(__APPLE__)
85 if (m_policy_set)
86 {
87 // Revert to default policy
88 mach_port_t threadPort = pthread_mach_thread_np(pthread_self());
89 thread_standard_policy_data_t policy;
90 thread_policy_set(
91 threadPort,
92 THREAD_STANDARD_POLICY,
93 reinterpret_cast<thread_policy_t>(&policy),
94 THREAD_STANDARD_POLICY_COUNT
95 );
96 m_policy_set = false;
97 }
98#else
99 if (m_elevated)
100 {
101 pthread_setschedparam(pthread_self(), m_original_policy, &m_original_param);
102 m_elevated = false;
103 }
104#endif
105 }
106
107private:
108#if defined(_WIN32)
109 HANDLE m_mmcss = nullptr;
110 UINT m_timer_resolution = 1;
111#elif defined(__APPLE__)
112 bool m_policy_set = false;
113#else
114 int m_original_policy = SCHED_OTHER;
115 struct sched_param m_original_param = {};
116 bool m_elevated = false;
117#endif
118};
119
120}
Definition git_info.h:7