NeoMutt  2020-09-25
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 
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 
107 static bool send(struct Notify *source, struct Notify *current,
108  enum NotifyType event_type, int event_subtype, void *event_data)
109 {
110  if (!source || !current)
111  return false;
112 
113  // mutt_debug(LL_NOTIFY, "send: %d, %ld\n", event_type, event_data);
114  struct ObserverNode *np = NULL;
115  STAILQ_FOREACH(np, &current->observers, entries)
116  {
117  struct Observer *o = np->observer;
118  if (!o)
119  continue;
120 
122  o->callback(&nc);
123  }
124 
125  if (current->parent)
126  return send(source, current->parent, event_type, event_subtype, event_data);
127 
128  // Garbage collection time
129  struct ObserverNode *tmp = NULL;
130  STAILQ_FOREACH_SAFE(np, &current->observers, entries, tmp)
131  {
132  if (np->observer)
133  continue;
134 
135  STAILQ_REMOVE(&current->observers, np, ObserverNode, entries);
136  FREE(&np);
137  }
138 
139  return true;
140 }
141 
152 bool notify_send(struct Notify *notify, enum NotifyType event_type,
153  int event_subtype, void *event_data)
154 {
155  return send(notify, notify, event_type, event_subtype, event_data);
156 }
157 
169 bool notify_observer_add(struct Notify *notify, enum NotifyType type,
170  observer_t callback, void *global_data)
171 {
172  if (!notify || !callback)
173  return false;
174 
175  struct ObserverNode *np = NULL;
176  STAILQ_FOREACH(np, &notify->observers, entries)
177  {
178  if (!np->observer)
179  continue;
180 
181  if (np->observer->callback == callback)
182  return true;
183  }
184 
185  struct Observer *o = mutt_mem_calloc(1, sizeof(*o));
186  o->callback = callback;
188 
189  np = mutt_mem_calloc(1, sizeof(*np));
190  np->observer = o;
191  STAILQ_INSERT_HEAD(&notify->observers, np, entries);
192 
193  return true;
194 }
195 
208 {
209  if (!notify || !callback)
210  return false;
211 
212  struct ObserverNode *np = NULL;
213  STAILQ_FOREACH(np, &notify->observers, entries)
214  {
215  if (!np->observer)
216  continue;
217 
218  if ((np->observer->callback == callback) && (np->observer->global_data == global_data))
219  {
220  FREE(&np->observer);
221  return true;
222  }
223  }
224 
225  return false;
226 }
227 
232 void notify_observer_remove_all(struct Notify *notify)
233 {
234  if (!notify)
235  return;
236 
237  struct ObserverNode *np = NULL;
238  struct ObserverNode *tmp = NULL;
239  STAILQ_FOREACH_SAFE(np, &notify->observers, entries, tmp)
240  {
241  STAILQ_REMOVE(&notify->observers, np, ObserverNode, entries);
242  FREE(&np->observer);
243  FREE(&np);
244  }
245 }
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:71
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:107
void * global_data
Private data to pass to callback.
Definition: observer.h:63
NotifyType
Notification Types.
Definition: notify_type.h:31
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:43
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
int(* observer_t)(struct NotifyCallback *nc)
Prototype for a notification callback function.
Definition: observer.h:54
#define STAILQ_INIT(head)
Definition: queue.h:369
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:169
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:359
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:59
Notification API.
Definition: notify.c:39
struct Notify * current
Notify object being observed.
Definition: observer.h:41
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
List of Observers.
Definition: observer.h:69
void * event_data
Data from notify_send()
Definition: observer.h:44
void notify_observer_remove_all(struct Notify *notify)
Remove all the observers from an object.
Definition: notify.c:232
#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:207
observer_t callback
Callback function for events.
Definition: observer.h:62
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:152