NeoMutt  2024-04-25-89-g194907
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
notify.c File Reference

Notification API. More...

#include "config.h"
#include <stdbool.h>
#include <stddef.h>
#include "notify.h"
#include "logging2.h"
#include "memory.h"
#include "notify_type.h"
#include "observer.h"
#include "queue.h"
+ Include dependency graph for notify.c:

Go to the source code of this file.

Data Structures

struct  Notify
 Notification API. More...
 

Functions

struct Notifynotify_new (void)
 Create a new notifications handler.
 
void notify_free (struct Notify **ptr)
 Free a notification handler.
 
void notify_set_parent (struct Notify *notify, struct Notify *parent)
 Set the parent notification handler.
 
static bool send (struct Notify *source, struct Notify *current, enum NotifyType event_type, int event_subtype, void *event_data)
 Send out a notification message.
 
bool notify_send (struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
 Send out a notification message.
 
bool notify_observer_add (struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
 Add an observer to an object.
 
bool notify_observer_remove (struct Notify *notify, const observer_t callback, const void *global_data)
 Remove an observer from an object.
 
void notify_observer_remove_all (struct Notify *notify)
 Remove all the observers from an object.
 

Variables

static const char * NotifyTypeNames []
 Lookup table for NotifyType Must be the same size and order as NotifyType.
 

Detailed Description

Notification API.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file notify.c.

Function Documentation

◆ notify_new()

struct Notify * notify_new ( void  )

Create a new notifications handler.

Return values
ptrNew notification handler

Definition at line 62 of file notify.c.

63{
64 struct Notify *notify = mutt_mem_calloc(1, sizeof(*notify));
65
66 STAILQ_INIT(&notify->observers);
67
68 return notify;
69}
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
#define STAILQ_INIT(head)
Definition: queue.h:372
Notification API.
Definition: notify.c:53
struct ObserverList observers
List of observers of this object.
Definition: notify.c:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ notify_free()

void notify_free ( struct Notify **  ptr)

Free a notification handler.

Parameters
ptrNotification handler to free

Definition at line 75 of file notify.c.

76{
77 if (!ptr || !*ptr)
78 return;
79
80 struct Notify *notify = *ptr;
81 // NOTIFY observers
82
84
85 FREE(ptr);
86}
#define FREE(x)
Definition: memory.h:45
void notify_observer_remove_all(struct Notify *notify)
Remove all the observers from an object.
Definition: notify.c:256
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ notify_set_parent()

void notify_set_parent ( struct Notify notify,
struct Notify parent 
)

Set the parent notification handler.

Parameters
notifyNotification handler to alter
parentParent notification handler

Notifications are passed up the tree of handlers.

Definition at line 95 of file notify.c.

96{
97 if (!notify)
98 return;
99
100 notify->parent = parent;
101}
struct Notify * parent
Parent of the notification object.
Definition: notify.c:54
+ Here is the caller graph for this function:

◆ send()

static bool send ( struct Notify source,
struct Notify current,
enum NotifyType  event_type,
int  event_subtype,
void *  event_data 
)
static

Send out a notification message.

Parameters
sourceSource of the event, e.g. Account
currentCurrent handler, e.g. NeoMutt
event_typeType of event, e.g. NT_ACCOUNT
event_subtypeSubtype, e.g. NT_ACCOUNT_ADD
event_dataPrivate data associated with the event type
Return values
trueSuccessfully sent

Notifications are sent to all observers of the object, then propagated up the handler tree. For example a "new email" notification would be sent to the Mailbox that owns it, the Account (owning the Mailbox) and finally the NeoMutt object.

Note
If Observers call notify_observer_remove(), then we garbage-collect any dead list entries after we've finished.

Definition at line 120 of file notify.c.

122{
123 if (!source || !current)
124 return false;
125
126 mutt_debug(LL_NOTIFY, "send: %d, %p\n", event_type, event_data);
127 struct ObserverNode *np = NULL;
128 STAILQ_FOREACH(np, &current->observers, entries)
129 {
130 struct Observer *o = np->observer;
131 if (!o)
132 continue;
133
134 if ((o->type == NT_ALL) || (event_type == o->type))
135 {
138 if (o->callback(&nc) < 0)
139 {
140 mutt_debug(LL_DEBUG1, "failed to send notification: %s/%d, global %p, event %p\n",
142 }
143 }
144 }
145
146 if (current->parent)
148
149 // Garbage collection time
150 struct ObserverNode *tmp = NULL;
151 STAILQ_FOREACH_SAFE(np, &current->observers, entries, tmp)
152 {
153 if (np->observer)
154 continue;
155
156 STAILQ_REMOVE(&current->observers, np, ObserverNode, entries);
157 FREE(&np);
158 }
159
160 return true;
161}
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
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:120
static const char * NotifyTypeNames[]
Lookup table for NotifyType Must be the same size and order as NotifyType.
Definition: notify.c:41
@ NT_ALL
Register for all notifications.
Definition: notify_type.h:35
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
Data passed to a notification function.
Definition: observer.h:34
void * event_data
Data from notify_send()
Definition: observer.h:38
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:36
struct Notify * current
Notify object being observed.
Definition: observer.h:35
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:37
List of Observers.
Definition: observer.h:70
struct Observer * observer
An Observer.
Definition: observer.h:71
An observer of notifications.
Definition: observer.h:60
observer_t callback
Callback function for events.
Definition: observer.h:62
void * global_data
Private data to pass to callback.
Definition: observer.h:63
enum NotifyType type
Notification type to observe, e.g. NT_WINDOW.
Definition: observer.h:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ notify_send()

bool notify_send ( struct Notify notify,
enum NotifyType  event_type,
int  event_subtype,
void *  event_data 
)

Send out a notification message.

Parameters
notifyNotification handler
event_typeType of event, e.g. NT_ACCOUNT
event_subtypeSubtype, e.g. NT_ACCOUNT_ADD
event_dataPrivate data associated with the event
Return values
trueSuccessfully sent

See send() for more details.

Definition at line 173 of file notify.c.

175{
176 mutt_debug(LL_NOTIFY, "sending: %s/%d\n", NotifyTypeNames[event_type], event_subtype);
177 return send(notify, notify, event_type, event_subtype, event_data);
178}
+ Here is the call graph for this function:

◆ notify_observer_add()

bool notify_observer_add ( struct Notify notify,
enum NotifyType  type,
observer_t  callback,
void *  global_data 
)

Add an observer to an object.

Parameters
notifyNotification handler
typeNotification type to observe, e.g. NT_WINDOW
callbackFunction to call on a matching event, see observer_t
global_dataPrivate data associated with the observer
Return values
trueSuccessful

New observers are added to the front of the list, giving them higher priority than existing observers.

Definition at line 191 of file notify.c.

193{
194 if (!notify || !callback)
195 return false;
196
197 struct ObserverNode *np = NULL;
198 STAILQ_FOREACH(np, &notify->observers, entries)
199 {
200 if (!np->observer)
201 continue; // LCOV_EXCL_LINE
202
203 if ((np->observer->callback == callback) && (np->observer->global_data == global_data))
204 return true;
205 }
206
207 struct Observer *o = mutt_mem_calloc(1, sizeof(*o));
208 o->type = type;
209 o->callback = callback;
211
212 np = mutt_mem_calloc(1, sizeof(*np));
213 np->observer = o;
214 STAILQ_INSERT_HEAD(&notify->observers, np, entries);
215
216 return true;
217}
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:383
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ notify_observer_remove()

bool notify_observer_remove ( struct Notify notify,
const observer_t  callback,
const void *  global_data 
)

Remove an observer from an object.

Parameters
notifyNotification handler
callbackFunction to call on a matching event, see observer_t
global_dataPrivate data to match specific callback
Return values
trueSuccessful
Note
This function frees the Observer, but doesn't free the ObserverNode. If send() is present higher up the call stack, removing multiple entries from the list will cause it to crash.

Definition at line 230 of file notify.c.

232{
233 if (!notify || !callback)
234 return false;
235
236 struct ObserverNode *np = NULL;
237 STAILQ_FOREACH(np, &notify->observers, entries)
238 {
239 if (!np->observer)
240 continue; // LCOV_EXCL_LINE
241
242 if ((np->observer->callback == callback) && (np->observer->global_data == global_data))
243 {
244 FREE(&np->observer);
245 return true;
246 }
247 }
248
249 return false;
250}
+ Here is the caller graph for this function:

◆ notify_observer_remove_all()

void notify_observer_remove_all ( struct Notify notify)

Remove all the observers from an object.

Parameters
notifyNotification handler

Definition at line 256 of file notify.c.

257{
258 if (!notify)
259 return;
260
261 struct ObserverNode *np = NULL;
262 struct ObserverNode *tmp = NULL;
263 STAILQ_FOREACH_SAFE(np, &notify->observers, entries, tmp)
264 {
265 STAILQ_REMOVE(&notify->observers, np, ObserverNode, entries);
266 FREE(&np->observer);
267 FREE(&np);
268 }
269}
+ Here is the caller graph for this function:

Variable Documentation

◆ NotifyTypeNames

const char* NotifyTypeNames[]
static
Initial value:
= {
"NT_ALL", "NT_ACCOUNT", "NT_ALIAS", "NT_ALTERN", "NT_ATTACH",
"NT_BINDING", "NT_COLOR", "NT_COMMAND", "NT_CONFIG", "NT_CONTEXT",
"NT_EMAIL", "NT_ENVELOPE", "NT_GLOBAL", "NT_HEADER", "NT_INDEX",
"NT_MAILBOX", "NT_MENU", "NT_PAGER", "NT_RESIZE", "NT_SCORE",
"NT_SUBJRX", "NT_TIMEOUT", "NT_WINDOW",
}

Lookup table for NotifyType Must be the same size and order as NotifyType.

Definition at line 41 of file notify.c.