forked from Qortal/Brooklyn
123 lines
5.5 KiB
C
123 lines
5.5 KiB
C
|
|
||
|
#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__ */
|