NeoMutt  2020-06-26-89-g172cd3
Teaching an old dog new tricks
DOXYGEN
notify.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <stddef.h>
31 #include <stdbool.h>
32 #include "notify.h"
33 #include "memory.h"
34 #include "queue.h"
35 
39 struct Notify
40 {
41  struct Notify *parent;
42  struct ObserverList observers;
43 };
44 
49 struct Notify *notify_new(void)
50 {
51  struct Notify *notify = mutt_mem_calloc(1, sizeof(*notify));
52 
53  STAILQ_INIT(&notify->observers);
54 
55  return notify;
56 }
57 
62 void notify_free(struct Notify **ptr)
63 {
64  if (!ptr || !*ptr)
65  return;
66 
67  struct Notify *notify = *ptr;
68  // NOTIFY observers
69 
70  notify_observer_remove(notify, NULL, NULL);
71 
72  FREE(ptr);
73 }
74 
82 void notify_set_parent(struct Notify *notify, struct Notify *parent)
83 {
84  if (!notify)
85  return;
86 
87  notify->parent = parent;
88 }
89 
104 static bool send(struct Notify *source, struct Notify *current,
105  enum NotifyType event_type, int event_subtype, void *event_data)
106 {
107  if (!source || !current)
108  return false;
109 
110  // mutt_debug(LL_NOTIFY, "send: %d, %ld\n", event_type, event_data);
111  struct ObserverNode *np = NULL;
112  struct ObserverNode *tmp = NULL;
113  // We use the `_SAFE` version in case an event causes an observer to be deleted
114  STAILQ_FOREACH_SAFE(np, &current->observers, entries, tmp)
115  {
116  struct Observer *o = np->observer;
117 
119  o->callback(&nc);
120  }
121 
122  if (current->parent)
123  return send(source, current->parent, event_type, event_subtype, event_data);
124  return true;
125 }
126 
137 bool notify_send(struct Notify *notify, enum NotifyType event_type,
138  int event_subtype, void *event_data)
139 {
140  return send(notify, notify, event_type, event_subtype, event_data);
141 }
142 
153 bool notify_observer_add(struct Notify *notify, observer_t callback, void *global_data)
154 {
155  if (!notify || !callback)
156  return false;
157 
158  struct ObserverNode *np = NULL;
159  STAILQ_FOREACH(np, &notify->observers, entries)
160  {
161  if (np->observer->callback == callback)
162  return true;
163  }
164 
165  struct Observer *o = mutt_mem_calloc(1, sizeof(*o));
166  o->callback = callback;
168 
169  np = mutt_mem_calloc(1, sizeof(*np));
170  np->observer = o;
171  STAILQ_INSERT_HEAD(&notify->observers, np, entries);
172 
173  return true;
174 }
175 
186 {
187  if (!notify)
188  return false;
189 
190  bool result = false;
191  struct ObserverNode *np = NULL;
192  struct ObserverNode *tmp = NULL;
193  STAILQ_FOREACH_SAFE(np, &notify->observers, entries, tmp)
194  {
195  if (!callback || ((np->observer->callback == callback) &&
196  (np->observer->global_data == global_data)))
197  {
198  STAILQ_REMOVE(&notify->observers, np, ObserverNode, entries);
199  FREE(&np->observer);
200  FREE(&np);
201  result = true;
202  if (callback)
203  break;
204  }
205  }
206 
207  return result;
208 }
Notification API.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:399
Memory management wrappers.
Data passed to a notification function.
Definition: observer.h:39
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:62
struct Observer * observer
An Observer.
Definition: observer.h:69
static bool send(struct Notify *source, struct Notify *current, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:104
void * global_data
Private data to pass to callback.
Definition: observer.h:61
NotifyType
Notification Types.
Definition: notify_type.h:31
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:42
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:41
int(* observer_t)(struct NotifyCallback *nc)
Prototype for a notification callback function.
Definition: observer.h:53
#define STAILQ_INIT(head)
Definition: queue.h:369
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:359
void * global_data
Data from notify_observer_add()
Definition: observer.h:44
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:49
struct Notify * parent
Definition: notify.c:41
struct ObserverList observers
Definition: notify.c:42
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:380
An observer of notifications.
Definition: observer.h:58
Notification API.
Definition: notify.c:39
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
List of Observers.
Definition: observer.h:67
bool notify_observer_add(struct Notify *notify, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:153
void * event_data
Data from notify_send()
Definition: observer.h:43
#define FREE(x)
Definition: memory.h:40
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:185
observer_t callback
Callback function for events.
Definition: observer.h:60
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:82
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:137