Home | Projects | Notesk > Multi-Threading (POSIX Threads) > Notification Chains (NFC)
Notification Chain is an architectural concept (i.e., can be implemented in many other programming languages) used to notify multiple subscribers that are interested in a particular event. Basically, it is all about the communication between a publisher and the multiple subscribers.
A party which generates an event is called the Publisher, and the parties that are interested in being notified of the event are called Subscribers.
There is one publisher and multiple subscribers.
Once an event is generated/produced by the publisher, the event is pushed to the subscribers that are interested in it.
Subscribers can register and de-register for events at their will.
Publishers/subscribers could be any entities:
Multiple threads of the same process
Multiple processes running on the same system
Multiple processes running on the different systems
Different components of a big software system
NFC is a linked list of callbacks (function pointers).
xxxxxxxxxx61/* structure for NFC */2typedef struct notif_chain_3{4 char nfc_name[64]; /* optional */5 glthread_t notif_chain_head; /* head of the linked list */6} notif_chain_t;Each element in NFC is called the notification chain element.
xxxxxxxxxx121/* structure for notification chain elements */2typedef struct notif_chain_elem_3{4 char key[MAX_NOTIV_KEY_SIZE]; /* 64 or 128 bytes will be sufficient */5 size_t key_size;6 bool_t is_key_set; /* user specified the key or not? (whild card user may not) */7 nfc_app_cb app_cb; /* function pointer by which subscribers want to get notified */8 glthread_t glue;9} notif_chain_elem_t;10
11/* prototype of the function pointer must be generic so that it works for all types of data for all types of subscribers */12typedef void (*nfc_app_cb)(void *, size_t); /* 2nd arg: size of the 1st arg */
The following example of NFC implementation is completely generic and can be applied to any type of applications.
notif.h
xxxxxxxxxx391/*2 * File Name : notif.h3 * Description : Interface for generic notification chain (NFC) infrastructure4 * Author : Comments added by Kyungjae Lee (Original: Abhishek Sagar)5 * Date Created : 12/29/20226 */7
8910
11/* size_t */121314
1516
17typedef void (*nfc_app_cb)(void *, size_t);18
19typedef struct notif_chain_elem_20{21 char key[MAX_NOTIV_KEY_SIZE]; /* 64 or 128 bytes will be sufficient */22 size_t key_size;23 bool_t is_key_set; /* user specified the key or not? (whild card user may not) */24 nfc_app_cb app_cb; /* function pointer by which subscribers want to get notified */25 glthread_t glue;26} notif_chain_elem_t;27
28typedef struct notif_chain_29{30 char nfc_name[64]; /* optional */31 glthread_t notif_chain_head; /* head of the linked list */32} notif_chain_t;33
34void nfc_register_notif_chain(notif_chain_t *nfc, notif_chain_elem_t *nfce);35void nfc_invoke_notif_chain(notif_chain_t *nfc, 36 void *arg, size_t arg_size, 37 char *key, size_t key_size);38
39/* NOTIF_CHAIN */notif.c
xxxxxxxxxx651/*2 * File Name : notif.c3 * Description : Implementation of generic notification chain (NFC) infrastructure4 * Author : Comments added by Kyungjae Lee (Original: Abhishek Sagar)5 * Date Created : 12/29/20226 */7
89101112
13void nfc_register_notif_chain(notif_chain_t *nfc, notif_chain_elem_t *nfce)14{15 /* subscriber already filled up the element to insert. just make a copy */16 notif_chain_elem_t *new_nfce = calloc(1, sizeof(notif_chain_elem_t));17 memcpy(new_nfce, nfce, sizeof(notif_chain_elem_t));18 19 /* insert the new node into NFC */20 glthread_add_next(&nfc->notif_chain_head, &new_nfc->glue);21 22}23
24/* function to be invoked by the publisher to notify the subscriber */25/* publisher will traverse the entire linked list passed as the 1st arg, match each 26 notification element with the key, and if there's a match, the callback registered27 to that element will be invoked as a means of notifying the subscriber */28void nfc_invoke_notif_chain(notif_chain_t *nfc, 29 void *arg, size_t arg_size, 30 char *key, size_t key_size)31{32 /* iterate over the NFC elements */33 glthread_t *curr;34 notif_chain_elem_t *nfce;35 assert(key_size <= MAX_NOTIF_KEY_SIZE);36 37 ITERATE_GLTHREAD_BEGIN(&nfc->notif_chain_head, curr)38 {39 /* pick up the NFC element one by one */40 nfce = glthread_glue_to_notif_chain_elem(curr);41 42 /* handle the wild card NFC element */43 if(!(key && key_size && nfce->is_key_set && (key_size == nfce->key_size)))44 {45 /* if the key is not specified OR if the key in the NFC element is not specified46 (which essentially means that it is a wild card entry) 47 then, no matter what, the publisher should invoke the callback present in the48 NFC element */49 nfce->app_cb(arg, arg_size);50 51 /* note that the publisher uses 'arg' and 'arg_size' passed by the subscriber when52 notifying the subscriber */53 }54 /* handle the situation where the key has been specified */55 else56 {57 if (memcmp(key, nfce->key, key_size) == 0)58 {59 /* invoke the callback only when the passed key matches the key in the NFC60 element */61 nfce->app_cb(arg, arg_size);62 }63 }64 }ITERATE_GLTHREAD_BEGIN(&nfc->notif_chain_head, curr);65}You are free to implement any additional routines. e.g., Unregister or unsubscription function using which a subscriber can unsubscribe from the notification chain.
Sagar, A. (2022). Part A - Multithreading & Thread Synchronization - Pthreads [Video file]. Retrieved from https://www.udemy.com/course/multithreading_parta/