record.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "record.h"
  2. #include "check.h"
  3. #include "memmgr.h"
  4. #include <cmsis_os2.h>
  5. #include <m-string.h>
  6. #include <m-dict.h>
  7. #define FURI_RECORD_FLAG_UPDATED 0x00000001U
  8. DICT_SET_DEF(osThreadIdSet, uint32_t)
  9. typedef struct {
  10. void* data;
  11. osThreadId_t owner;
  12. osThreadIdSet_t holders;
  13. } FuriRecord;
  14. DICT_DEF2(FuriRecordDict, string_t, STRING_OPLIST, FuriRecord, M_POD_OPLIST)
  15. typedef struct {
  16. osMutexId_t records_mutex;
  17. FuriRecordDict_t records;
  18. } FuriRecordData;
  19. static FuriRecordData* furi_record_data = NULL;
  20. void furi_record_init() {
  21. furi_record_data = furi_alloc(sizeof(FuriRecordData));
  22. furi_record_data->records_mutex = osMutexNew(NULL);
  23. furi_check(furi_record_data->records_mutex);
  24. FuriRecordDict_init(furi_record_data->records);
  25. }
  26. FuriRecord* furi_record_get_or_create(string_t name_str) {
  27. furi_assert(furi_record_data);
  28. FuriRecord* record = FuriRecordDict_get(furi_record_data->records, name_str);
  29. if(!record) {
  30. FuriRecord new_record;
  31. new_record.data = NULL;
  32. new_record.owner = NULL;
  33. osThreadIdSet_init(new_record.holders);
  34. FuriRecordDict_set_at(furi_record_data->records, name_str, new_record);
  35. record = FuriRecordDict_get(furi_record_data->records, name_str);
  36. }
  37. return record;
  38. }
  39. void furi_record_create(const char* name, void* data) {
  40. furi_assert(furi_record_data);
  41. osThreadId_t thread_id = osThreadGetId();
  42. string_t name_str;
  43. string_init_set_str(name_str, name);
  44. // Acquire mutex
  45. furi_check(osMutexAcquire(furi_record_data->records_mutex, osWaitForever) == osOK);
  46. FuriRecord* record = furi_record_get_or_create(name_str);
  47. record->data = data;
  48. record->owner = thread_id;
  49. // For each holder set event flag
  50. osThreadIdSet_it_t it;
  51. for(osThreadIdSet_it(it, record->holders); !osThreadIdSet_end_p(it); osThreadIdSet_next(it)) {
  52. osThreadFlagsSet((osThreadId_t)*osThreadIdSet_ref(it), FURI_RECORD_FLAG_UPDATED);
  53. }
  54. // Release mutex
  55. furi_check(osMutexRelease(furi_record_data->records_mutex) == osOK);
  56. string_clear(name_str);
  57. }
  58. bool furi_record_destroy(const char* name) {
  59. furi_assert(furi_record_data);
  60. osThreadId_t thread_id = osThreadGetId();
  61. string_t name_str;
  62. string_init_set_str(name_str, name);
  63. bool destroyed = false;
  64. furi_check(osMutexAcquire(furi_record_data->records_mutex, osWaitForever) == osOK);
  65. FuriRecord* record = FuriRecordDict_get(furi_record_data->records, name_str);
  66. if(record && record->owner == thread_id && osThreadIdSet_size(record->holders) == 0) {
  67. osThreadIdSet_clear(record->holders);
  68. FuriRecordDict_erase(furi_record_data->records, name_str);
  69. destroyed = true;
  70. }
  71. furi_check(osMutexRelease(furi_record_data->records_mutex) == osOK);
  72. string_clear(name_str);
  73. return destroyed;
  74. }
  75. void* furi_record_open(const char* name) {
  76. furi_assert(furi_record_data);
  77. osThreadId_t thread_id = osThreadGetId();
  78. string_t name_str;
  79. string_init_set_str(name_str, name);
  80. FuriRecord* record = NULL;
  81. while(1) {
  82. furi_check(osMutexAcquire(furi_record_data->records_mutex, osWaitForever) == osOK);
  83. record = furi_record_get_or_create(name_str);
  84. osThreadIdSet_push(record->holders, (uint32_t)thread_id);
  85. furi_check(osMutexRelease(furi_record_data->records_mutex) == osOK);
  86. // Check if owner is already arrived
  87. if(record->owner) {
  88. break;
  89. }
  90. // Wait for thread flag to appear
  91. osThreadFlagsWait(FURI_RECORD_FLAG_UPDATED, osFlagsWaitAny, osWaitForever);
  92. }
  93. string_clear(name_str);
  94. return record->data;
  95. }
  96. void furi_record_close(const char* name) {
  97. furi_assert(furi_record_data);
  98. osThreadId_t thread_id = osThreadGetId();
  99. string_t name_str;
  100. string_init_set_str(name_str, name);
  101. furi_check(osMutexAcquire(furi_record_data->records_mutex, osWaitForever) == osOK);
  102. FuriRecord* record = FuriRecordDict_get(furi_record_data->records, name_str);
  103. osThreadIdSet_erase(record->holders, (uint32_t)thread_id);
  104. furi_check(osMutexRelease(furi_record_data->records_mutex) == osOK);
  105. string_clear(name_str);
  106. }