#include "record.h" #include "check.h" #include "memmgr.h" #include <cmsis_os2.h> #include <m-string.h> #include <m-dict.h> #define FURI_RECORD_FLAG_READY (0x1) typedef struct { osEventFlagsId_t flags; void* data; size_t holders_count; } FuriRecordData; DICT_DEF2(FuriRecordDataDict, string_t, STRING_OPLIST, FuriRecordData, M_POD_OPLIST) typedef struct { osMutexId_t mutex; FuriRecordDataDict_t records; } FuriRecord; static FuriRecord* furi_record = NULL; void furi_record_init() { furi_record = malloc(sizeof(FuriRecord)); furi_record->mutex = osMutexNew(NULL); furi_check(furi_record->mutex); FuriRecordDataDict_init(furi_record->records); } static FuriRecordData* furi_record_data_get_or_create(string_t name_str) { furi_assert(furi_record); FuriRecordData* record_data = FuriRecordDataDict_get(furi_record->records, name_str); if(!record_data) { FuriRecordData new_record; new_record.flags = osEventFlagsNew(NULL); new_record.data = NULL; new_record.holders_count = 0; FuriRecordDataDict_set_at(furi_record->records, name_str, new_record); record_data = FuriRecordDataDict_get(furi_record->records, name_str); } return record_data; } static void furi_record_lock() { furi_check(osMutexAcquire(furi_record->mutex, osWaitForever) == osOK); } static void furi_record_unlock() { furi_check(osMutexRelease(furi_record->mutex) == osOK); } bool furi_record_exists(const char* name) { furi_assert(furi_record); furi_assert(name); bool ret = false; string_t name_str; string_init_set_str(name_str, name); furi_record_lock(); ret = (FuriRecordDataDict_get(furi_record->records, name_str) != NULL); furi_record_unlock(); string_clear(name_str); return ret; } void furi_record_create(const char* name, void* data) { furi_assert(furi_record); string_t name_str; string_init_set_str(name_str, name); furi_record_lock(); // Get record data and fill it FuriRecordData* record_data = furi_record_data_get_or_create(name_str); furi_assert(record_data->data == NULL); record_data->data = data; osEventFlagsSet(record_data->flags, FURI_RECORD_FLAG_READY); furi_record_unlock(); string_clear(name_str); } bool furi_record_destroy(const char* name) { furi_assert(furi_record); bool ret = false; string_t name_str; string_init_set_str(name_str, name); furi_record_lock(); FuriRecordData* record_data = FuriRecordDataDict_get(furi_record->records, name_str); furi_assert(record_data); if(record_data->holders_count == 0) { furi_check(osOK == osEventFlagsDelete(record_data->flags)); FuriRecordDataDict_erase(furi_record->records, name_str); ret = true; } furi_record_unlock(); string_clear(name_str); return ret; } void* furi_record_open(const char* name) { furi_assert(furi_record); string_t name_str; string_init_set_str(name_str, name); furi_record_lock(); FuriRecordData* record_data = furi_record_data_get_or_create(name_str); record_data->holders_count++; furi_record_unlock(); // Wait for record to become ready furi_check( osEventFlagsWait( record_data->flags, FURI_RECORD_FLAG_READY, osFlagsWaitAny | osFlagsNoClear, osWaitForever) == FURI_RECORD_FLAG_READY); string_clear(name_str); return record_data->data; } void furi_record_close(const char* name) { furi_assert(furi_record); string_t name_str; string_init_set_str(name_str, name); furi_record_lock(); FuriRecordData* record_data = FuriRecordDataDict_get(furi_record->records, name_str); furi_assert(record_data); record_data->holders_count--; furi_record_unlock(); string_clear(name_str); }