valuemutex.h 3.6 KB

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