tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_Threads.cpp
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11#pragma once
12
13#ifdef _WIN32
14 #include <windows.h>
15#endif
16
17namespace tracktion { inline namespace graph
18{
19
20#ifdef _WIN32
21 bool setThreadPriority (void* handle, int priority)
22 {
23 assert (handle != nullptr);
24 int pri = THREAD_PRIORITY_TIME_CRITICAL;
25
26 if (priority < 1) pri = THREAD_PRIORITY_IDLE;
27 else if (priority < 2) pri = THREAD_PRIORITY_LOWEST;
28 else if (priority < 5) pri = THREAD_PRIORITY_BELOW_NORMAL;
29 else if (priority < 7) pri = THREAD_PRIORITY_NORMAL;
30 else if (priority < 9) pri = THREAD_PRIORITY_ABOVE_NORMAL;
31 else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST;
32
33 return SetThreadPriority (handle, pri) != FALSE;
34 }
35#else
36 template<typename HandleType>
37 bool setThreadPriority (HandleType handle, int priority)
38 {
39 assert (handle != HandleType());
40
41 struct sched_param param;
42 int policy;
43 priority = std::max (0, std::min (10, priority));
44
45 if (pthread_getschedparam ((pthread_t) handle, &policy, &param) != 0)
46 return false;
47
48 policy = priority == 0 ? SCHED_OTHER : SCHED_RR;
49
50 const int minPriority = sched_get_priority_min (policy);
51 const int maxPriority = sched_get_priority_max (policy);
52
53 param.sched_priority = ((maxPriority - minPriority) * priority) / 10 + minPriority;
54 return pthread_setschedparam ((pthread_t) handle, policy, &param) == 0;
55 }
56#endif
57
58#if JUCE_MAC
59 template<typename Type>
60 std::optional<Type> firstOptionalWithValue (const std::initializer_list<std::optional<Type>>& optionals)
61 {
62 for (const auto& optional : optionals)
63 if (optional.has_value())
64 return optional;
65
66 return {};
67 }
68
70 {
71 const auto periodMs = options.getPeriodMs().value_or (0.0);
72
73 const auto processingTimeMs = firstOptionalWithValue (
74 {
75 options.getProcessingTimeMs(),
77 options.getPeriodMs()
78 }).value_or (10.0);
79
80 const auto maxProcessingTimeMs = options.getMaximumProcessingTimeMs()
81 .value_or (processingTimeMs);
82
83 // The processing time can not exceed the maximum processing time!
84 jassert (maxProcessingTimeMs >= processingTimeMs);
85
86 thread_time_constraint_policy_data_t policy;
87 policy.period = (uint32_t) juce::Time::secondsToHighResolutionTicks (periodMs / 1'000.0);
88 policy.computation = (uint32_t) juce::Time::secondsToHighResolutionTicks (processingTimeMs / 1'000.0);
89 policy.constraint = (uint32_t) juce::Time::secondsToHighResolutionTicks (maxProcessingTimeMs / 1'000.0);
90 policy.preemptible = true;
91
92 const auto result = thread_policy_set (pthread_mach_thread_np (pthread_self()),
93 THREAD_TIME_CONSTRAINT_POLICY,
94 (thread_policy_t) &policy,
95 THREAD_TIME_CONSTRAINT_POLICY_COUNT);
96
97 if (result == KERN_SUCCESS)
98 return true;
99
100 // testing has shown that passing a computation value > 50ms can
101 // lead to thread_policy_set returning an error indicating that an
102 // invalid argument was passed. If that happens this code tries to
103 // limit that value in the hope of resolving the issue.
104
105 if (result == KERN_INVALID_ARGUMENT && options.getProcessingTimeMs() > 50.0)
107
108 return false;
109 }
110#else
112 {
113 return false;
114 }
115#endif
116
117bool setThreadPriority (std::thread& t, int priority)
118{
119 return setThreadPriority (t.native_handle(), priority);
120}
121
122}} // namespace tracktion_engine
assert
static int64 secondsToHighResolutionTicks(double seconds) noexcept
#define jassert(expression)
T max(T... args)
T min(T... args)
bool tryToUpgradeCurrentThreadToRealtime(const juce::Thread::RealtimeOptions &)
Tries to upgrade the current thread to realtime priority.
pthread_self
sched_get_priority_min
typedef uint32_t
std::optional< double > getMaximumProcessingTimeMs() const
std::optional< double > getPeriodMs() const
std::optional< double > getProcessingTimeMs() const
RealtimeOptions withProcessingTimeMs(double newProcessingTimeMs) const
T value_or(T... args)