| |
| #ifndef __DWC_NOTIFIER_H__ |
| #define __DWC_NOTIFIER_H__ |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include "dwc_os.h" |
| |
| /** @file |
| * |
| * A simple implementation of the Observer pattern. Any "module" can |
| * register as an observer or notifier. The notion of "module" is abstract and |
| * can mean anything used to identify either an observer or notifier. Usually |
| * it will be a pointer to a data structure which contains some state, ie an |
| * object. |
| * |
| * Before any notifiers can be added, the global notification manager must be |
| * brought up with dwc_alloc_notification_manager(). |
| * dwc_free_notification_manager() will bring it down and free all resources. |
| * These would typically be called upon module load and unload. The |
| * notification manager is a single global instance that handles all registered |
| * observable modules and observers so this should be done only once. |
| * |
| * A module can be observable by using Notifications to publicize some general |
| * information about it's state or operation. It does not care who listens, or |
| * even if anyone listens, or what they do with the information. The observable |
| * modules do not need to know any information about it's observers or their |
| * interface, or their state or data. |
| * |
| * Any module can register to emit Notifications. It should publish a list of |
| * notifications that it can emit and their behavior, such as when they will get |
| * triggered, and what information will be provided to the observer. Then it |
| * should register itself as an observable module. See dwc_register_notifier(). |
| * |
| * Any module can observe any observable, registered module, provided it has a |
| * handle to the other module and knows what notifications to observe. See |
| * dwc_add_observer(). |
| * |
| * A function of type dwc_notifier_callback_t is called whenever a notification |
| * is triggered with one or more observers observing it. This function is |
| * called in it's own process so it may sleep or block if needed. It is |
| * guaranteed to be called sometime after the notification has occurred and will |
| * be called once per each time the notification is triggered. It will NOT be |
| * called in the same process context used to trigger the notification. |
| * |
| * @section Limitiations |
| * |
| * Keep in mind that Notifications that can be triggered in rapid sucession may |
| * schedule too many processes too handle. Be aware of this limitation when |
| * designing to use notifications, and only add notifications for appropriate |
| * observable information. |
| * |
| * Also Notification callbacks are not synchronous. If you need to synchronize |
| * the behavior between module/observer you must use other means. And perhaps |
| * that will mean Notifications are not the proper solution. |
| */ |
| |
| struct dwc_notifier; |
| typedef struct dwc_notifier dwc_notifier_t; |
| |
| /** The callback function must be of this type. |
| * |
| * @param object This is the object that is being observed. |
| * @param notification This is the notification that was triggered. |
| * @param observer This is the observer |
| * @param notification_data This is notification-specific data that the notifier |
| * has included in this notification. The value of this should be published in |
| * the documentation of the observable module with the notifications. |
| * @param user_data This is any custom data that the observer provided when |
| * adding itself as an observer to the notification. */ |
| typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, |
| void *notification_data, void *user_data); |
| |
| /** Brings up the notification manager. */ |
| extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx); |
| /** Brings down the notification manager. */ |
| extern void dwc_free_notification_manager(void); |
| |
| /** This function registers an observable module. A dwc_notifier_t object is |
| * returned to the observable module. This is an opaque object that is used by |
| * the observable module to trigger notifications. This object should only be |
| * accessible to functions that are authorized to trigger notifications for this |
| * module. Observers do not need this object. */ |
| extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object); |
| |
| /** This function unregisters an observable module. All observers have to be |
| * removed prior to unregistration. */ |
| extern void dwc_unregister_notifier(dwc_notifier_t *notifier); |
| |
| /** Add a module as an observer to the observable module. The observable module |
| * needs to have previously registered with the notification manager. |
| * |
| * @param observer The observer module |
| * @param object The module to observe |
| * @param notification The notification to observe |
| * @param callback The callback function to call |
| * @param user_data Any additional user data to pass into the callback function */ |
| extern int dwc_add_observer(void *observer, void *object, char *notification, |
| dwc_notifier_callback_t callback, void *user_data); |
| |
| /** Removes the specified observer from all notifications that it is currently |
| * observing. */ |
| extern int dwc_remove_observer(void *observer); |
| |
| /** This function triggers a Notification. It should be called by the |
| * observable module, or any module or library which the observable module |
| * allows to trigger notification on it's behalf. Such as the dwc_cc_t. |
| * |
| * dwc_notify is a non-blocking function. Callbacks are scheduled called in |
| * their own process context for each trigger. Callbacks can be blocking. |
| * dwc_notify can be called from interrupt context if needed. |
| * |
| */ |
| void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* __DWC_NOTIFIER_H__ */ |