Overte C++ Documentation
SharedUtil.h
1 //
2 // SharedUtil.h
3 // libraries/shared/src
4 //
5 // Created by Stephen Birarda on 2/22/13.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_SharedUtil_h
13 #define hifi_SharedUtil_h
14 
15 #include <memory>
16 #include <mutex>
17 #include <math.h>
18 #include <stdint.h>
19 
20 #ifndef _WIN32
21 #include <unistd.h> // not on windows, not needed for mac or windows
22 #endif
23 
24 #include <QtCore/QDebug>
25 #include <QtCore/QCoreApplication>
26 #include <QUuid>
27 
28 #include "NumericalConstants.h"
29 // When writing out avatarEntities to a QByteArray, if the parentID is the ID of MyAvatar, use this ID instead. This allows
30 // the value to be reset when the sessionID changes.
31 const QUuid AVATAR_SELF_ID = QUuid("{00000000-0000-0000-0000-000000000001}");
32 
33 // Access to the global instance pointer to enable setting / unsetting
34 template <typename T>
35 std::unique_ptr<T>& globalInstancePointer() {
36  static std::unique_ptr<T> instancePtr;
37  return instancePtr;
38 }
39 
40 // Sets up the global instances for use
41 // This NEEDS to be called on startup
42 // for any binary planing on using global instances
43 // More details in cpp file
44 void setupGlobalInstances();
45 
46 std::mutex& globalInstancesMutex();
47 QVariant getGlobalInstance(const char* propertyName);
48 void setGlobalInstance(const char* propertyName, const QVariant& variant);
49 
50 // Provides efficient access to a named global type. By storing the value
51 // in the QApplication by name we can implement the singleton pattern and
52 // have the single instance function across DLL boundaries.
53 template <typename T, typename... Args>
54 T* globalInstance(const char* propertyName, Args&&... args) {
55  static T* resultInstance { nullptr };
56  if (!resultInstance) {
57  std::unique_lock<std::mutex> lock(globalInstancesMutex());
58  if (!resultInstance) {
59  auto variant = getGlobalInstance(propertyName);
60  if (variant.isNull()) {
61  std::unique_ptr<T>& instancePtr = globalInstancePointer<T>();
62  if (!instancePtr.get()) {
63  // Since we're building the object, store it in a shared_ptr so it's
64  // destroyed by the destructor of the static instancePtr
65  instancePtr = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
66  }
67  void* voidInstance = &(*instancePtr);
68  variant = QVariant::fromValue(voidInstance);
69  setGlobalInstance(propertyName, variant);
70  }
71  void* returnedVoidInstance = variant.value<void*>();
72  resultInstance = static_cast<T*>(returnedVoidInstance);
73  }
74  }
75  return resultInstance;
76 }
77 
78 
79 const int BYTES_PER_COLOR = 3;
80 const int BYTES_PER_FLAGS = 1;
81 typedef unsigned char colorPart;
82 typedef unsigned char nodeColor[BYTES_PER_COLOR + BYTES_PER_FLAGS];
83 
84 // Equivalent to time_t but in usecs instead of secs
85 quint64 usecTimestampNow(bool wantDebug = false);
86 void usecTimestampNowForceClockSkew(qint64 clockSkew);
87 
88 inline bool afterUsecs(quint64& startUsecs, quint64 maxIntervalUecs) {
89  auto now = usecTimestampNow();
90  auto interval = now - startUsecs;
91  if (interval > maxIntervalUecs) {
92  startUsecs = now;
93  return true;
94  }
95  return false;
96 }
97 
98 inline bool afterSecs(quint64& startUsecs, quint64 maxIntervalSecs) {
99  return afterUsecs(startUsecs, maxIntervalSecs * USECS_PER_SECOND);
100 }
101 
102 template <typename F>
103 void doEvery(quint64& lastReportUsecs, quint64 secs, F lamdba) {
104  if (afterSecs(lastReportUsecs, secs)) {
105  lamdba();
106  }
107 }
108 
109 // Number of seconds expressed since the first call to this function, expressed as a float
110 // Maximum accuracy in msecs
111 float secTimestampNow();
112 
113 // Custom deleter for QObjects that calls deleteLater
114 struct LaterDeleter {
115  void operator()(QObject* ptr) {
116  ptr->deleteLater();
117  }
118 };
119 
120 float randFloat();
121 int randIntInRange (int min, int max);
122 float randFloatInRange (float min,float max);
123 float randomSign();
124 unsigned char randomColorValue(int minimum = 0);
125 bool randomBoolean();
126 
127 bool shouldDo(float desiredInterval, float deltaTime);
128 
129 void outputBufferBits(const unsigned char* buffer, int length, QDebug* continuedDebug = NULL);
130 void outputBits(unsigned char byte, QDebug* continuedDebug = NULL);
131 void printVoxelCode(unsigned char* voxelCode);
132 int numberOfOnes(unsigned char byte);
133 bool oneAtBit(unsigned char byte, int bitIndex);
134 void setAtBit(unsigned char& byte, int bitIndex);
135 bool oneAtBit16(unsigned short word, int bitIndex);
136 void setAtBit16(unsigned short& word, int bitIndex);
137 void clearAtBit(unsigned char& byte, int bitIndex);
138 int getSemiNibbleAt(unsigned short word, int bitIndex);
139 void setSemiNibbleAt(unsigned short& word, int bitIndex, int value);
140 
141 int getNthBit(unsigned char byte, int ordinal);
142 
143 bool isInEnvironment(const char* environment);
144 
145 const char* getCmdOption(int argc, const char * argv[],const char* option);
146 bool cmdOptionExists(int argc, const char * argv[],const char* option);
147 
148 void sharedMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message);
149 
150 unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r = 0, unsigned char g = 0, unsigned char b = 0);
151 unsigned char* pointToOctalCode(float x, float y, float z, float s);
152 
153 #ifdef _WIN32
154 void usleep(int waitTime);
155 #endif
156 
157 int insertIntoSortedArrays(void* value, float key, int originalIndex,
158  void** valueArray, float* keyArray, int* originalIndexArray,
159  int currentCount, int maxCount);
160 
161 int removeFromSortedArrays(void* value, void** valueArray, float* keyArray, int* originalIndexArray,
162  int currentCount, int maxCount);
163 
164 // Helper Class for debugging
165 class debug {
166 public:
167  static const char* valueOf(bool checkValue) { return checkValue ? "yes" : "no"; }
168  static void setDeadBeef(void* memoryVoid, int size);
169  static void checkDeadBeef(void* memoryVoid, int size);
170 private:
171  static unsigned char DEADBEEF[];
172  static int DEADBEEF_SIZE;
173 };
174 
176 inline bool isBetween(int64_t value, int64_t max, int64_t min) { return ((value <= max) && (value >= min)); }
177 
179 inline bool isNaN(float value) { return value != value; }
180 
181 QString formatUsecTime(float usecs);
182 QString formatUsecTime(double usecs);
183 QString formatUsecTime(quint64 usecs);
184 QString formatUsecTime(qint64 usecs);
185 QString formatSecTime(qint64 secs);
186 
187 QString formatSecondsElapsed(float seconds);
188 bool similarStrings(const QString& stringA, const QString& stringB);
189 
190 template <typename T>
191 uint qHash(const std::shared_ptr<T>& ptr, uint seed = 0)
192 {
193  return qHash(ptr.get(), seed);
194 }
195 
196 void disableQtBearerPoll();
197 
198 void printSystemInformation();
199 
200 struct MemoryInfo {
201  uint64_t totalMemoryBytes;
202  uint64_t availMemoryBytes;
203  uint64_t usedMemoryBytes;
204  uint64_t processUsedMemoryBytes;
205  uint64_t processPeakUsedMemoryBytes;
206 };
207 
208 bool getMemoryInfo(MemoryInfo& info);
209 
210 struct ProcessorInfo {
211  int32_t numPhysicalProcessorPackages;
212  int32_t numProcessorCores;
213  int32_t numLogicalProcessors;
214  int32_t numProcessorCachesL1;
215  int32_t numProcessorCachesL2;
216  int32_t numProcessorCachesL3;
217 };
218 
219 bool getProcessorInfo(ProcessorInfo& info);
220 
221 const QString& getInterfaceSharedMemoryName();
222 
223 void setMaxCores(uint8_t maxCores);
224 
225 const QString PARENT_PID_OPTION = "parent-pid";
226 void watchParentProcess(int parentPID);
227 
228 bool processIsRunning(int64_t pid);
229 
230 void setupHifiApplication(QString applicationName);
231 
232 #ifdef Q_OS_WIN
233 void* createProcessGroup();
234 void addProcessToGroup(void* processGroup, qint64 processId);
235 #endif
236 
237 #endif // hifi_SharedUtil_h