OpenShot Audio Library | OpenShotAudio 0.4.0
Loading...
Searching...
No Matches
juce_SystemStats.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
27{
28 // Some basic tests, to keep an eye on things and make sure these types work ok
29 // on all platforms. Let me know if any of these assertions fail on your system!
30 static_assert (sizeof (pointer_sized_int) == sizeof (void*), "Basic sanity test failed: please report!");
31 static_assert (sizeof (int8) == 1, "Basic sanity test failed: please report!");
32 static_assert (sizeof (uint8) == 1, "Basic sanity test failed: please report!");
33 static_assert (sizeof (int16) == 2, "Basic sanity test failed: please report!");
34 static_assert (sizeof (uint16) == 2, "Basic sanity test failed: please report!");
35 static_assert (sizeof (int32) == 4, "Basic sanity test failed: please report!");
36 static_assert (sizeof (uint32) == 4, "Basic sanity test failed: please report!");
37 static_assert (sizeof (int64) == 8, "Basic sanity test failed: please report!");
38 static_assert (sizeof (uint64) == 8, "Basic sanity test failed: please report!");
39
40 return "JUCE v" JUCE_STRINGIFY (JUCE_MAJOR_VERSION)
41 "." JUCE_STRINGIFY (JUCE_MINOR_VERSION)
42 "." JUCE_STRINGIFY (JUCE_BUILDNUMBER);
43}
44
45#if JUCE_ANDROID && ! defined (JUCE_DISABLE_JUCE_VERSION_PRINTING)
46 #define JUCE_DISABLE_JUCE_VERSION_PRINTING 1
47#endif
48
49#if JUCE_DEBUG && ! JUCE_DISABLE_JUCE_VERSION_PRINTING
50 struct JuceVersionPrinter
51 {
52 JuceVersionPrinter()
53 {
55 }
56 };
57
58 static JuceVersionPrinter juceVersionPrinter;
59#endif
60
62{
64 if (auto ids = getMachineIdentifiers (flag); ! ids.isEmpty())
65 return ids;
66
67 jassertfalse; // Failed to create any IDs!
68 return {};
69}
70
71String getLegacyUniqueDeviceID();
72
74{
75 auto macAddressProvider = [] (StringArray& arr)
76 {
77 for (const auto& mac : MACAddress::getAllAddresses())
78 arr.add (mac.toString());
79 };
80
81 auto fileSystemProvider = [] (StringArray& arr)
82 {
83 #if JUCE_WINDOWS
84 File f (File::getSpecialLocation (File::windowsSystemDirectory));
85 #else
86 File f ("~");
87 #endif
88 if (auto num = f.getFileIdentifier())
89 arr.add (String::toHexString ((int64) num));
90 };
91
92 auto legacyIdProvider = [] ([[maybe_unused]] StringArray& arr)
93 {
94 #if JUCE_WINDOWS
95 arr.add (getLegacyUniqueDeviceID());
96 #endif
97 };
98
99 auto uniqueIdProvider = [] (StringArray& arr)
100 {
101 arr.add (getUniqueDeviceID());
102 };
103
104 struct Provider { MachineIdFlags flag; void (*func) (StringArray&); };
105 static const Provider providers[] =
106 {
107 { MachineIdFlags::macAddresses, macAddressProvider },
108 { MachineIdFlags::fileSystemId, fileSystemProvider },
109 { MachineIdFlags::legacyUniqueId, legacyIdProvider },
110 { MachineIdFlags::uniqueId, uniqueIdProvider }
111 };
112
113 StringArray ids;
114
115 for (const auto& provider : providers)
116 {
117 if (hasBitValueSet (flags, provider.flag))
118 provider.func (ids);
119 }
120
121 return ids;
122}
123
124//==============================================================================
125struct CPUInformation
126{
127 CPUInformation() noexcept { initialise(); }
128
129 void initialise() noexcept;
130
131 int numLogicalCPUs = 0, numPhysicalCPUs = 0;
132
133 bool hasMMX = false, hasSSE = false, hasSSE2 = false, hasSSE3 = false,
134 has3DNow = false, hasFMA3 = false, hasFMA4 = false, hasSSSE3 = false,
135 hasSSE41 = false, hasSSE42 = false, hasAVX = false, hasAVX2 = false,
136 hasAVX512F = false, hasAVX512BW = false, hasAVX512CD = false,
137 hasAVX512DQ = false, hasAVX512ER = false, hasAVX512IFMA = false,
138 hasAVX512PF = false, hasAVX512VBMI = false, hasAVX512VL = false,
139 hasAVX512VPOPCNTDQ = false,
140 hasNeon = false;
141};
142
143static const CPUInformation& getCPUInformation() noexcept
144{
145 static CPUInformation info;
146 return info;
147}
148
149int SystemStats::getNumCpus() noexcept { return getCPUInformation().numLogicalCPUs; }
150int SystemStats::getNumPhysicalCpus() noexcept { return getCPUInformation().numPhysicalCPUs; }
151bool SystemStats::hasMMX() noexcept { return getCPUInformation().hasMMX; }
152bool SystemStats::has3DNow() noexcept { return getCPUInformation().has3DNow; }
153bool SystemStats::hasFMA3() noexcept { return getCPUInformation().hasFMA3; }
154bool SystemStats::hasFMA4() noexcept { return getCPUInformation().hasFMA4; }
155bool SystemStats::hasSSE() noexcept { return getCPUInformation().hasSSE; }
156bool SystemStats::hasSSE2() noexcept { return getCPUInformation().hasSSE2; }
157bool SystemStats::hasSSE3() noexcept { return getCPUInformation().hasSSE3; }
158bool SystemStats::hasSSSE3() noexcept { return getCPUInformation().hasSSSE3; }
159bool SystemStats::hasSSE41() noexcept { return getCPUInformation().hasSSE41; }
160bool SystemStats::hasSSE42() noexcept { return getCPUInformation().hasSSE42; }
161bool SystemStats::hasAVX() noexcept { return getCPUInformation().hasAVX; }
162bool SystemStats::hasAVX2() noexcept { return getCPUInformation().hasAVX2; }
163bool SystemStats::hasAVX512F() noexcept { return getCPUInformation().hasAVX512F; }
164bool SystemStats::hasAVX512BW() noexcept { return getCPUInformation().hasAVX512BW; }
165bool SystemStats::hasAVX512CD() noexcept { return getCPUInformation().hasAVX512CD; }
166bool SystemStats::hasAVX512DQ() noexcept { return getCPUInformation().hasAVX512DQ; }
167bool SystemStats::hasAVX512ER() noexcept { return getCPUInformation().hasAVX512ER; }
168bool SystemStats::hasAVX512IFMA() noexcept { return getCPUInformation().hasAVX512IFMA; }
169bool SystemStats::hasAVX512PF() noexcept { return getCPUInformation().hasAVX512PF; }
170bool SystemStats::hasAVX512VBMI() noexcept { return getCPUInformation().hasAVX512VBMI; }
171bool SystemStats::hasAVX512VL() noexcept { return getCPUInformation().hasAVX512VL; }
172bool SystemStats::hasAVX512VPOPCNTDQ() noexcept { return getCPUInformation().hasAVX512VPOPCNTDQ; }
173bool SystemStats::hasNeon() noexcept { return getCPUInformation().hasNeon; }
174
175
176//==============================================================================
178{
179 String result;
180
181 #if JUCE_ANDROID || JUCE_MINGW || JUCE_WASM
182 jassertfalse; // sorry, not implemented yet!
183
184 #elif JUCE_WINDOWS
185 HANDLE process = GetCurrentProcess();
186 SymInitialize (process, nullptr, TRUE);
187
188 void* stack[128];
189 int frames = (int) CaptureStackBackTrace (0, numElementsInArray (stack), stack, nullptr);
190
192 symbol.calloc (sizeof (SYMBOL_INFO) + 256, 1);
193 symbol->MaxNameLen = 255;
194 symbol->SizeOfStruct = sizeof (SYMBOL_INFO);
195
196 for (int i = 0; i < frames; ++i)
197 {
198 DWORD64 displacement = 0;
199
200 if (SymFromAddr (process, (DWORD64) stack[i], &displacement, symbol))
201 {
202 result << i << ": ";
203
204 IMAGEHLP_MODULE64 moduleInfo;
205 zerostruct (moduleInfo);
206 moduleInfo.SizeOfStruct = sizeof (moduleInfo);
207
208 if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo))
209 result << moduleInfo.ModuleName << ": ";
210
211 result << symbol->Name << " + 0x" << String::toHexString ((int64) displacement) << newLine;
212 }
213 }
214
215 #else
216 void* stack[128];
217 auto frames = backtrace (stack, numElementsInArray (stack));
218 char** frameStrings = backtrace_symbols (stack, frames);
219
220 for (auto i = (decltype (frames)) 0; i < frames; ++i)
221 result << frameStrings[i] << newLine;
222
223 ::free (frameStrings);
224 #endif
225
226 return result;
227}
228
229//==============================================================================
230#if ! JUCE_WASM
231
232static SystemStats::CrashHandlerFunction globalCrashHandler = nullptr;
233
234#if JUCE_WINDOWS
235static LONG WINAPI handleCrash (LPEXCEPTION_POINTERS ep)
236{
237 globalCrashHandler (ep);
238 return EXCEPTION_EXECUTE_HANDLER;
239}
240#else
241static void handleCrash (int signum)
242{
243 globalCrashHandler ((void*) (pointer_sized_int) signum);
244 ::kill (getpid(), SIGKILL);
245}
246
247int juce_siginterrupt (int sig, int flag);
248#endif
249
251{
252 jassert (handler != nullptr); // This must be a valid function.
253 globalCrashHandler = handler;
254
255 #if JUCE_WINDOWS
256 SetUnhandledExceptionFilter (handleCrash);
257 #else
258 const int signals[] = { SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT, SIGSYS };
259
260 for (int i = 0; i < numElementsInArray (signals); ++i)
261 {
262 ::signal (signals[i], handleCrash);
263 juce_siginterrupt (signals[i], 1);
264 }
265 #endif
266}
267
268#endif
269
271{
272 #if JUCE_MAC || JUCE_IOS
273 static bool isRunningInAppSandbox = [&]
274 {
276
277 #if JUCE_MAC
278 bundle = bundle.getParentDirectory().getParentDirectory();
279 #endif
280
281 if (bundle.isDirectory())
282 return bundle.getFileExtension() == ".appex";
283
284 return false;
285 }();
286
287 return isRunningInAppSandbox;
288 #else
289 return false;
290 #endif
291}
292
293#if JUCE_UNIT_TESTS
294
295class UniqueHardwareIDTest final : public UnitTest
296{
297public:
298 //==============================================================================
299 UniqueHardwareIDTest() : UnitTest ("UniqueHardwareID", UnitTestCategories::analytics) {}
300
301 void runTest() override
302 {
303 beginTest ("getUniqueDeviceID returns usable data.");
304 {
305 expect (SystemStats::getUniqueDeviceID().isNotEmpty());
306 }
307 }
308};
309
310static UniqueHardwareIDTest uniqueHardwareIDTest;
311
312#endif
313
314} // namespace juce
bool isDirectory() const
String getFileExtension() const
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
@ invokedExecutableFile
Definition juce_File.h:949
File getParentDirectory() const
uint64 getFileIdentifier() const
void calloc(SizeType newNumElements, const size_t elementSize=sizeof(ElementType))
static Array< MACAddress > getAllAddresses()
static String toHexString(IntegerType number)
static bool hasAVX512CD() noexcept
static String getStackBacktrace()
static bool hasMMX() noexcept
static void setApplicationCrashHandler(CrashHandlerFunction)
static int getNumPhysicalCpus() noexcept
static bool hasAVX512ER() noexcept
static bool has3DNow() noexcept
static bool hasAVX2() noexcept
static bool hasAVX512VPOPCNTDQ() noexcept
static bool hasSSE() noexcept
static bool hasAVX512DQ() noexcept
static bool isRunningInAppExtensionSandbox() noexcept
static bool hasNeon() noexcept
static bool hasAVX512F() noexcept
static bool hasSSE3() noexcept
static bool hasSSE2() noexcept
static bool hasAVX() noexcept
void(*)(void *) CrashHandlerFunction
static bool hasAVX512VBMI() noexcept
static String getUniqueDeviceID()
@ legacyUniqueId
Only implemented on Windows. A hash of the full smbios table, may be unstable on certain machines.
@ uniqueId
The most stable kind of machine identifier. A good default to use.
@ fileSystemId
The filesystem id of the user's home directory (or system directory on Windows).
@ macAddresses
All Mac addresses of the machine.
static bool hasSSSE3() noexcept
static bool hasAVX512VL() noexcept
static bool hasAVX512PF() noexcept
static bool hasSSE41() noexcept
static StringArray getDeviceIdentifiers()
static bool hasFMA4() noexcept
static String getJUCEVersion()
static bool hasSSE42() noexcept
static StringArray getMachineIdentifiers(MachineIdFlags flags)
static bool hasFMA3() noexcept
static bool hasAVX512IFMA() noexcept
static bool hasAVX512BW() noexcept
static int getNumCpus() noexcept