valuemutex.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #pragma once
  2. #include <cmsis_os2.h>
  3. #include <stdbool.h>
  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif
  7. /*
  8. == ValueMutex ==
  9. The most simple concept is ValueMutex.
  10. It is wrapper around mutex and value pointer.
  11. You can take and give mutex to work with value and read and write value.
  12. */
  13. typedef struct {
  14. void* value;
  15. size_t size;
  16. osMutexId_t mutex;
  17. } ValueMutex;
  18. /*
  19. Creates ValueMutex.
  20. */
  21. bool init_mutex(ValueMutex* valuemutex, void* value, size_t size);
  22. /*
  23. Free resources allocated by `init_mutex`.
  24. This function doesn't free the memory occupied by `ValueMutex` itself.
  25. */
  26. bool delete_mutex(ValueMutex* valuemutex);
  27. /*
  28. Call for work with data stored in mutex.
  29. Returns pointer to data if success, NULL otherwise.
  30. */
  31. void* acquire_mutex(ValueMutex* valuemutex, uint32_t timeout);
  32. /*
  33. Helper: infinitly wait for mutex
  34. */
  35. static inline void* acquire_mutex_block(ValueMutex* valuemutex) {
  36. return acquire_mutex(valuemutex, osWaitForever);
  37. }
  38. /*
  39. * With statement for value mutex, acts as lambda
  40. * @param name a resource name, const char*
  41. * @param function_body a (){} lambda declaration,
  42. * executed within you parent function context.
  43. */
  44. #define with_value_mutex(value_mutex, function_body) \
  45. { \
  46. void* p = acquire_mutex_block(value_mutex); \
  47. furi_check(p); \
  48. ({ void __fn__ function_body __fn__; })(p); \
  49. release_mutex(value_mutex, p); \
  50. }
  51. /*
  52. Release mutex after end of work with data.
  53. Call `release_mutex` and pass ValueData instance and pointer to data.
  54. */
  55. bool release_mutex(ValueMutex* valuemutex, const void* value);
  56. /*
  57. Instead of take-access-give sequence you can use `read_mutex` and `write_mutex` functions.
  58. Both functions return true in case of success, false otherwise.
  59. */
  60. bool read_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeout);
  61. bool write_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeout);
  62. inline static bool write_mutex_block(ValueMutex* valuemutex, void* data, size_t len) {
  63. return write_mutex(valuemutex, data, len, osWaitForever);
  64. }
  65. inline static bool read_mutex_block(ValueMutex* valuemutex, void* data, size_t len) {
  66. return read_mutex(valuemutex, data, len, osWaitForever);
  67. }
  68. #ifdef __cplusplus
  69. }
  70. #endif
  71. /*
  72. Usage example
  73. ```C
  74. // MANIFEST
  75. // name="example-provider-app"
  76. // stack=128
  77. void provider_app(void* _p) {
  78. // create record with mutex
  79. uint32_t example_value = 0;
  80. ValueMutex example_mutex;
  81. // call `init_mutex`.
  82. if(!init_mutex(&example_mutex, (void*)&example_value, sizeof(uint32_t))) {
  83. printf("critical error\n");
  84. flapp_exit(NULL);
  85. }
  86. furi_record_create("provider/example", (void*)&example_mutex);
  87. // we are ready to provide record to other apps
  88. flapp_ready();
  89. // get value and increment it
  90. while(1) {
  91. uint32_t* value = acquire_mutex(&example_mutex, OsWaitForever);
  92. if(value != NULL) {
  93. value++;
  94. }
  95. release_mutex(&example_mutex, value);
  96. osDelay(100);
  97. }
  98. }
  99. // MANIFEST
  100. // name="example-consumer-app"
  101. // stack=128
  102. // require="example-provider-app"
  103. void consumer_app(void* _p) {
  104. // this app run after flapp_ready call in all requirements app
  105. // open mutex value
  106. ValueMutex* counter_mutex = furi_record_open("provider/example");
  107. if(counter_mutex == NULL) {
  108. printf("critical error\n");
  109. flapp_exit(NULL);
  110. }
  111. // continously read value every 1s
  112. uint32_t counter;
  113. while(1) {
  114. if(read_mutex(counter_mutex, &counter, sizeof(counter), OsWaitForever)) {
  115. printf("counter value: %d\n", counter);
  116. }
  117. osDelay(1000);
  118. }
  119. }
  120. ```
  121. */