You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.1KB

  1. #pragma once
  2. // Include most of the C++ standard library for convenience
  3. #include <cstdlib>
  4. #include <cstdio>
  5. #include <cstdint>
  6. #include <cstring>
  7. #include <cassert>
  8. #include <climits>
  9. #include <string>
  10. #include <vector>
  11. #include <condition_variable>
  12. #include <mutex>
  13. #include "macros.hpp"
  14. #include "math.hpp"
  15. #include "string.hpp"
  16. #include "logger.hpp"
  17. namespace rack {
  18. ////////////////////
  19. // Template hacks
  20. ////////////////////
  21. /** C#-style property constructor
  22. Example:
  23. Foo *foo = construct<Foo>(&Foo::greeting, "Hello world");
  24. */
  25. template<typename T>
  26. T *construct() {
  27. return new T();
  28. }
  29. template<typename T, typename F, typename V, typename... Args>
  30. T *construct(F f, V v, Args... args) {
  31. T *o = construct<T>(args...);
  32. o->*f = v;
  33. return o;
  34. }
  35. /** Defers code until the scope is destructed
  36. From http://www.gingerbill.org/article/defer-in-cpp.html
  37. Example:
  38. file = fopen(...);
  39. defer({
  40. fclose(file);
  41. });
  42. */
  43. template<typename F>
  44. struct DeferWrapper {
  45. F f;
  46. DeferWrapper(F f) : f(f) {}
  47. ~DeferWrapper() { f(); }
  48. };
  49. template<typename F>
  50. DeferWrapper<F> deferWrapper(F f) {
  51. return DeferWrapper<F>(f);
  52. }
  53. #define defer(code) auto CONCAT(_defer_, __COUNTER__) = deferWrapper([&]() code)
  54. ////////////////////
  55. // Random number generator
  56. // random.cpp
  57. ////////////////////
  58. /** Seeds the RNG with the current time */
  59. void randomInit();
  60. /** Returns a uniform random uint32_t from 0 to UINT32_MAX */
  61. uint32_t randomu32();
  62. uint64_t randomu64();
  63. /** Returns a uniform random float in the interval [0.0, 1.0) */
  64. float randomUniform();
  65. /** Returns a normal random number with mean 0 and standard deviation 1 */
  66. float randomNormal();
  67. DEPRECATED inline float randomf() {return randomUniform();}
  68. ////////////////////
  69. // Operating-system specific utilities
  70. // system.cpp
  71. ////////////////////
  72. std::vector<std::string> systemListEntries(std::string path);
  73. bool systemIsFile(std::string path);
  74. bool systemIsDirectory(std::string path);
  75. void systemCopy(std::string srcPath, std::string destPath);
  76. void systemCreateDirectory(std::string path);
  77. /** Opens a URL, also happens to work with PDFs and folders.
  78. Shell injection is possible, so make sure the URL is trusted or hard coded.
  79. May block, so open in a new thread.
  80. */
  81. void systemOpenBrowser(std::string url);
  82. ////////////////////
  83. // Debug logger
  84. // logger.cpp
  85. ////////////////////
  86. ////////////////////
  87. // Thread functions
  88. ////////////////////
  89. /** Threads which obtain a VIPLock will cause wait() to block for other less important threads.
  90. This does not provide the VIPs with an exclusive lock. That should be left up to another mutex shared between the less important thread.
  91. */
  92. struct VIPMutex {
  93. int count = 0;
  94. std::condition_variable cv;
  95. std::mutex countMutex;
  96. /** Blocks until there are no remaining VIPLocks */
  97. void wait() {
  98. std::unique_lock<std::mutex> lock(countMutex);
  99. while (count > 0)
  100. cv.wait(lock);
  101. }
  102. };
  103. struct VIPLock {
  104. VIPMutex &m;
  105. VIPLock(VIPMutex &m) : m(m) {
  106. std::unique_lock<std::mutex> lock(m.countMutex);
  107. m.count++;
  108. }
  109. ~VIPLock() {
  110. std::unique_lock<std::mutex> lock(m.countMutex);
  111. m.count--;
  112. lock.unlock();
  113. m.cv.notify_all();
  114. }
  115. };
  116. } // namespace rack