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.

124 lines
2.8KB

  1. #pragma once
  2. // Include most of the C standard library for convenience
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <stdint.h>
  6. #include <assert.h>
  7. #include <string>
  8. #include <condition_variable>
  9. #include <mutex>
  10. /** Surrounds raw text with quotes
  11. Example:
  12. printf("Hello " STRINGIFY(world))
  13. will expand to
  14. printf("Hello " "world")
  15. and of course the C++ lexer/parser will then concatenate the string literals
  16. */
  17. #define STRINGIFY(x) #x
  18. /** Converts a macro to a string literal
  19. Example:
  20. #define NAME "world"
  21. printf("Hello " TOSTRING(NAME))
  22. will expand to
  23. printf("Hello " "world")
  24. */
  25. #define TOSTRING(x) STRINGIFY(x)
  26. #define LENGTHOF(arr) (sizeof(arr) / sizeof((arr)[0]))
  27. namespace rack {
  28. /** C#-style property constructor
  29. Example:
  30. Foo *foo = construct<Foo>(&Foo::greeting, "Hello world");
  31. */
  32. template<typename T>
  33. T *construct() {
  34. return new T();
  35. }
  36. template<typename T, typename F, typename V, typename... Args>
  37. T *construct(F f, V v, Args... args) {
  38. T *o = construct<T>(args...);
  39. o->*f = v;
  40. return o;
  41. }
  42. ////////////////////
  43. // RNG
  44. ////////////////////
  45. uint32_t randomu32();
  46. /** Returns a uniform random float in the interval [0.0, 1.0) */
  47. float randomf();
  48. /** Returns a normal random number with mean 0 and std dev 1 */
  49. float randomNormal();
  50. ////////////////////
  51. // String functions
  52. ////////////////////
  53. /** Converts a printf format string and optional arguments into a std::string */
  54. std::string stringf(const char *format, ...);
  55. /** Truncates and adds "..." to a string, not exceeding `len` characters */
  56. std::string ellipsize(std::string s, size_t len);
  57. std::string extractDirectory(std::string path);
  58. std::string extractFilename(std::string path);
  59. std::string extractExtension(std::string path);
  60. ////////////////////
  61. // Operating system functions
  62. ////////////////////
  63. /** Opens a URL, also happens to work with PDFs and folders.
  64. Shell injection is possible, so make sure the URL is trusted or hard coded.
  65. May block, so open in a new thread.
  66. */
  67. void openBrowser(std::string url);
  68. ////////////////////
  69. // Thread functions
  70. ////////////////////
  71. /** Threads which obtain a VIPLock will cause wait() to block for other less important threads.
  72. This does not provide the VIPs with an exclusive lock. That should be left up to another mutex shared between the less important thread.
  73. */
  74. struct VIPMutex {
  75. int count = 0;
  76. std::condition_variable cv;
  77. std::mutex countMutex;
  78. /** Blocks until there are no remaining VIPLocks */
  79. void wait() {
  80. std::unique_lock<std::mutex> lock(countMutex);
  81. while (count > 0)
  82. cv.wait(lock);
  83. }
  84. };
  85. struct VIPLock {
  86. VIPMutex &m;
  87. VIPLock(VIPMutex &m) : m(m) {
  88. std::unique_lock<std::mutex> lock(m.countMutex);
  89. m.count++;
  90. }
  91. ~VIPLock() {
  92. std::unique_lock<std::mutex> lock(m.countMutex);
  93. m.count--;
  94. lock.unlock();
  95. m.cv.notify_all();
  96. }
  97. };
  98. } // namespace rack