valuemutex.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. Call for work with data stored in mutex.
  20. Returns pointer to data if success, NULL otherwise.
  21. */
  22. void* acquire_mutex(ValueMutex* valuemutex, uint32_t timeout);
  23. /*
  24. Helper: infinitly wait for mutex
  25. */
  26. static inline void* acquire_mutex_block(ValueMutex* valuemutex) {
  27. return acquire_mutex(valuemutex, osWaitForever);
  28. }
  29. /*
  30. Release mutex after end of work with data.
  31. Call `release_mutex` and pass ValueData instance and pointer to data.
  32. */
  33. bool release_mutex(ValueMutex* valuemutex, void* value);
  34. /*
  35. Instead of take-access-give sequence you can use `read_mutex` and `write_mutex` functions.
  36. Both functions return true in case of success, false otherwise.
  37. */
  38. bool read_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeout);
  39. bool write_mutex(ValueMutex* valuemutex, void* data, size_t len, uint32_t timeout);
  40. inline static bool write_mutex_block(ValueMutex* valuemutex, void* data, size_t len) {
  41. return write_mutex(valuemutex, data, len, osWaitForever);
  42. }
  43. inline static bool read_mutex_block(ValueMutex* valuemutex, void* data, size_t len) {
  44. return read_mutex(valuemutex, data, len, osWaitForever);
  45. }
  46. /*
  47. Usage example
  48. ```C
  49. // MANIFEST
  50. // name="example-provider-app"
  51. // stack=128
  52. void provider_app(void* _p) {
  53. // create record with mutex
  54. uint32_t example_value = 0;
  55. ValueMutex example_mutex;
  56. // call `init_mutex`.
  57. if(!init_mutex(&example_mutex, (void*)&example_value, sizeof(uint32_t))) {
  58. printf("critical error\n");
  59. flapp_exit(NULL);
  60. }
  61. if(furi_create("provider/example", (void*)&example_mutex)) {
  62. printf("critical error\n");
  63. flapp_exit(NULL);
  64. }
  65. // we are ready to provide record to other apps
  66. flapp_ready();
  67. // get value and increment it
  68. while(1) {
  69. uint32_t* value = acquire_mutex(&example_mutex, OsWaitForever);
  70. if(value != NULL) {
  71. value++;
  72. }
  73. release_mutex(&example_mutex, value);
  74. osDelay(100);
  75. }
  76. }
  77. // MANIFEST
  78. // name="example-consumer-app"
  79. // stack=128
  80. // require="example-provider-app"
  81. void consumer_app(void* _p) {
  82. // this app run after flapp_ready call in all requirements app
  83. // open mutex value
  84. ValueMutex* counter_mutex = furi_open("provider/example");
  85. if(counter_mutex == NULL) {
  86. printf("critical error\n");
  87. flapp_exit(NULL);
  88. }
  89. // continously read value every 1s
  90. uint32_t counter;
  91. while(1) {
  92. if(read_mutex(counter_mutex, &counter, sizeof(counter), OsWaitForever)) {
  93. printf("counter value: %d\n", counter);
  94. }
  95. osDelay(1000);
  96. }
  97. }
  98. ```
  99. */