NeoMutt  2019-12-07-168-gc45f47
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 <stdint.h>
33 #include "notify.h"
34 #include "memory.h"
35 #include "queue.h"
36 
40 struct Notify
41 {
42  struct Notify *parent;
43  struct ObserverList observers;
44 };
45 
50 struct Notify *notify_new(void)
51 {
52  struct Notify *notify = mutt_mem_calloc(1, sizeof(*notify));
53 
54  STAILQ_INIT(&notify->observers);
55 
56  return notify;
57 }
58 
63 void notify_free(struct Notify **ptr)
64 {
65  if (!ptr || !*ptr)
66  return;
67 
68  struct Notify *notify = *ptr;
69  // NOTIFY observers
70 
71  notify_observer_remove(notify, NULL, NULL);
72 
73  FREE(ptr);
74 }
75 
83 void notify_set_parent(struct Notify *notify, struct Notify *parent)
84 {
85  if (!notify || !parent)
86  return;
87 
88  notify->parent = parent;
89 }
90 
105 static bool send(struct Notify *source, struct Notify *current,
106  enum NotifyType event_type, int event_subtype, void *event_data)
107 {
108  if (!source || !current)
109  return false;
110 
111  // mutt_debug(LL_NOTIFY, "send: %d, %ld\n", event_type, event_data);
112  struct ObserverNode *np = NULL;
113  struct ObserverNode *tmp = NULL;
114  // We use the `_SAFE` version in case an event causes an observer to be deleted
115  STAILQ_FOREACH_SAFE(np, &current->observers, entries, tmp)
116  {
117  struct Observer *o = np->observer;
118 
120  o->callback(&nc);
121  }
122 
123  if (current->parent)
124  return send(source, current->parent, event_type, event_subtype, event_data);
125  return true;
126 }
127 
138 bool notify_send(struct Notify *notify, enum NotifyType event_type,
139  int event_subtype, void *event_data)
140 {
141  return send(notify, notify, event_type, event_subtype, event_data);
142 }
143 
154 bool notify_observer_add(struct Notify *notify, observer_t callback, void *global_data)
155 {
156  if (!notify || !callback)
157  return false;
158 
159  struct ObserverNode *np = NULL;
160  STAILQ_FOREACH(np, &notify->observers, entries)
161  {
162  if (np->observer->callback == callback)
163  return true;
164  }
165 
166  struct Observer *o = mutt_mem_calloc(1, sizeof(*o));
167  o->callback = callback;
169 
170  np = mutt_mem_calloc(1, sizeof(*np));
171  np->observer = o;
172  STAILQ_INSERT_HEAD(&notify->observers, np, entries);
173 
174  return true;
175 }
176 
187 {
188  if (!notify)
189  return false;
190 
191  bool result = false;
192  struct ObserverNode *np = NULL;
193  struct ObserverNode *tmp = NULL;
194  STAILQ_FOREACH_SAFE(np, &notify->observers, entries, tmp)
195  {
196  if (!callback || ((np->observer->callback == callback) &&
197  (np->observer->global_data == global_data)))
198  {
199  STAILQ_REMOVE(&notify->observers, np, ObserverNode, entries);
200  FREE(&np->observer);
201  FREE(&np);
202  result = true;
203  if (callback)
204  break;
205  }
206  }
207 
208  return result;
209 }
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:40
struct Observer * observer
An Observer.
Definition: observer.h:70
void * global_data
Private data to pass to callback.
Definition: observer.h:62
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:83
bool notify_observer_add(struct Notify *notify, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:154
NotifyType
Notification Types.
Definition: notify_type.h:29
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)
typedef observer_t - Prototype for a notification callback function
Definition: observer.h:54
#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:45
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:186
struct Notify * parent
Definition: notify.c:42
struct ObserverList observers
Definition: notify.c:43
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:380
An observer of notifications.
Definition: observer.h:59
Notification API.
Definition: notify.c:40
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
List of Observers.
Definition: observer.h:68
void * event_data
Data from notify_send()
Definition: observer.h:44
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:63
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:138
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:50
#define FREE(x)
Definition: memory.h:40
observer_t callback
Callback function for events.
Definition: observer.h:61
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:105