pubsub.c 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include "pubsub.h"
  2. #include "memmgr.h"
  3. #include "check.h"
  4. #include "mutex.h"
  5. #include <m-list.h>
  6. struct FuriPubSubSubscription {
  7. FuriPubSubCallback callback;
  8. void* callback_context;
  9. };
  10. LIST_DEF(FuriPubSubSubscriptionList, FuriPubSubSubscription, M_POD_OPLIST);
  11. struct FuriPubSub {
  12. FuriPubSubSubscriptionList_t items;
  13. FuriMutex* mutex;
  14. };
  15. FuriPubSub* furi_pubsub_alloc() {
  16. FuriPubSub* pubsub = malloc(sizeof(FuriPubSub));
  17. pubsub->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  18. furi_assert(pubsub->mutex);
  19. FuriPubSubSubscriptionList_init(pubsub->items);
  20. return pubsub;
  21. }
  22. void furi_pubsub_free(FuriPubSub* pubsub) {
  23. furi_assert(pubsub);
  24. furi_check(FuriPubSubSubscriptionList_size(pubsub->items) == 0);
  25. FuriPubSubSubscriptionList_clear(pubsub->items);
  26. furi_mutex_free(pubsub->mutex);
  27. free(pubsub);
  28. }
  29. FuriPubSubSubscription*
  30. furi_pubsub_subscribe(FuriPubSub* pubsub, FuriPubSubCallback callback, void* callback_context) {
  31. furi_check(furi_mutex_acquire(pubsub->mutex, FuriWaitForever) == FuriStatusOk);
  32. // put uninitialized item to the list
  33. FuriPubSubSubscription* item = FuriPubSubSubscriptionList_push_raw(pubsub->items);
  34. // initialize item
  35. item->callback = callback;
  36. item->callback_context = callback_context;
  37. furi_check(furi_mutex_release(pubsub->mutex) == FuriStatusOk);
  38. return item;
  39. }
  40. void furi_pubsub_unsubscribe(FuriPubSub* pubsub, FuriPubSubSubscription* pubsub_subscription) {
  41. furi_assert(pubsub);
  42. furi_assert(pubsub_subscription);
  43. furi_check(furi_mutex_acquire(pubsub->mutex, FuriWaitForever) == FuriStatusOk);
  44. bool result = false;
  45. // iterate over items
  46. FuriPubSubSubscriptionList_it_t it;
  47. for(FuriPubSubSubscriptionList_it(it, pubsub->items); !FuriPubSubSubscriptionList_end_p(it);
  48. FuriPubSubSubscriptionList_next(it)) {
  49. const FuriPubSubSubscription* item = FuriPubSubSubscriptionList_cref(it);
  50. // if the iterator is equal to our element
  51. if(item == pubsub_subscription) {
  52. FuriPubSubSubscriptionList_remove(pubsub->items, it);
  53. result = true;
  54. break;
  55. }
  56. }
  57. furi_check(furi_mutex_release(pubsub->mutex) == FuriStatusOk);
  58. furi_check(result);
  59. }
  60. void furi_pubsub_publish(FuriPubSub* pubsub, void* message) {
  61. furi_check(furi_mutex_acquire(pubsub->mutex, FuriWaitForever) == FuriStatusOk);
  62. // iterate over subscribers
  63. FuriPubSubSubscriptionList_it_t it;
  64. for(FuriPubSubSubscriptionList_it(it, pubsub->items); !FuriPubSubSubscriptionList_end_p(it);
  65. FuriPubSubSubscriptionList_next(it)) {
  66. const FuriPubSubSubscription* item = FuriPubSubSubscriptionList_cref(it);
  67. item->callback(message, item->callback_context);
  68. }
  69. furi_check(furi_mutex_release(pubsub->mutex) == FuriStatusOk);
  70. }