tor  master
Data Structures | Macros | Typedefs | Functions
pubsub.h File Reference

Macros to implement publish/subscribe abstractions. More...

#include "torint.h"
Include dependency graph for pubsub.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pubsub_subscriber_t
 
struct  pubsub_topic_t
 

Macros

#define SUBSCRIBE_ATSTART   (1u<<0)
 
#define DECLARE_PUBSUB_STRUCT_TYPES(name)
 
#define DECLARE_PUBSUB_TOPIC(name)
 
#define DECLARE_NOTIFY_PUBSUB_TOPIC(linkage, name)
 
#define IMPLEMENT_PUBSUB_TOPIC(notify_linkage, name)
 

Typedefs

typedef int(* pubsub_subscriber_fn_t) (void *, void *)
 
typedef struct pubsub_subscriber_t pubsub_subscriber_t
 
typedef struct pubsub_topic_t pubsub_topic_t
 
typedef int(* pubsub_notify_fn_t) (pubsub_subscriber_t *subscriber, void *notify_data)
 

Functions

const pubsub_subscriber_tpubsub_subscribe_ (pubsub_topic_t *topic, pubsub_subscriber_fn_t fn, void *subscriber_data, unsigned subscribe_flags, unsigned priority)
 
int pubsub_unsubscribe_ (pubsub_topic_t *topic, const pubsub_subscriber_t *sub)
 
void pubsub_clear_ (pubsub_topic_t *topic)
 
int pubsub_notify_ (pubsub_topic_t *topic, pubsub_notify_fn_t notify_fn, void *notify_data, unsigned notify_flags)
 

Detailed Description

Macros to implement publish/subscribe abstractions.

To use these macros, call DECLARE_PUBSUB_TOPIC() with an identifier to use as your topic. Below, I'm going to assume you say DECLARE_PUBSUB_TOPIC(T).

Doing this will declare the following types: typedef struct T_event_data_t T_event_data_t; // you define this struct typedef struct T_subscriber_data_t T_subscriber_data_t; // this one too. typedef struct T_subscriber_t T_subscriber_t; // opaque typedef int (T_subscriber_fn_t)(T_event_data_t, T_subscriber_data_t*);

and it will declare the following functions: const T_subscriber_t *T_subscribe(T_subscriber_fn_t, T_subscriber_data_t *, unsigned flags, unsigned priority); int T_unsubscribe(const T_subscriber_t *)

Elsewhere you can say DECLARE_NOTIFY_PUBSUB_TOPIC(static, T), which declares:

static int T_notify(T_event_data_t *, unsigned notify_flags); static void T_clear(void);

And in some C file, you would define these functions with: IMPLEMENT_PUBSUB_TOPIC(static, T).

The implementations will be small typesafe wrappers over generic versions of the above functions.

To use the typesafe functions, you add any number of subscribers with T_subscribe(). Each has an associated function pointer, data pointer, and priority. Later, you can invoke T_notify() to declare that the event has occurred. Each of the subscribers will be invoked once.

Macro Definition Documentation

◆ DECLARE_NOTIFY_PUBSUB_TOPIC

#define DECLARE_NOTIFY_PUBSUB_TOPIC (   linkage,
  name 
)
Value:
/* Call this function to notify all subscribers. Flags not yet used. */ \
linkage int name ## _notify(name ## _event_data_t *data, unsigned flags); \
/* Call this function to release storage held by the topic. */ \
linkage void name ## _clear(void);

◆ DECLARE_PUBSUB_STRUCT_TYPES

#define DECLARE_PUBSUB_STRUCT_TYPES (   name)
Value:
/* You define this type. */ \
typedef struct name ## _event_data_t name ## _event_data_t; \
/* You define this type. */ \
typedef struct name ## _subscriber_data_t name ## _subscriber_data_t;

◆ DECLARE_PUBSUB_TOPIC

#define DECLARE_PUBSUB_TOPIC (   name)
Value:
/* This type is opaque. */ \
typedef struct name ## _subscriber_t name ## _subscriber_t; \
/* You declare functions matching this type. */ \
typedef int (*name ## _subscriber_fn_t)( \
name ## _event_data_t *data, \
name ## _subscriber_data_t *extra); \
/* Call this function to subscribe to a topic. */ \
const name ## _subscriber_t *name ## _subscribe( \
name##_subscriber_fn_t subscriber, \
name##_subscriber_data_t *extra_data, \
unsigned flags, \
unsigned priority); \
/* Call this function to unsubscribe from a topic. */ \
int name ## _unsubscribe(const name##_subscriber_t *s);

◆ SUBSCRIBE_ATSTART

#define SUBSCRIBE_ATSTART   (1u<<0)

Flag for T_subscribe: die with an assertion failure if the event have ever been published before. Used when a subscriber must absolutely never have missed an event.

Typedef Documentation

◆ pubsub_subscriber_fn_t

typedef int(* pubsub_subscriber_fn_t) (void *, void *)

Type used to hold a generic function for a subscriber.

[Yes, it is safe to cast to this, so long as we cast back to the original type before calling. From C99: "A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer."]

◆ pubsub_subscriber_t

Helper type to implement pubsub abstraction. Don't use this directly. It represents a subscriber.

◆ pubsub_topic_t

Helper type to implement pubsub abstraction. Don't use this directly. It represents a topic, and keeps a record of subscribers.

Function Documentation

◆ pubsub_clear_()

void pubsub_clear_ ( pubsub_topic_t topic)

Release all storage held by topic.

◆ pubsub_notify_()

int pubsub_notify_ ( pubsub_topic_t topic,
pubsub_notify_fn_t  notify_fn,
void *  event_data,
unsigned  notify_flags 
)

For every subscriber s in topic, invoke notify_fn on s and event_data. Return 0 if there were no nonzero return values, and -1 if there were any.

◆ pubsub_subscribe_()

const pubsub_subscriber_t* pubsub_subscribe_ ( pubsub_topic_t topic,
pubsub_subscriber_fn_t  fn,
void *  subscriber_data,
unsigned  subscribe_flags,
unsigned  priority 
)

Add a new subscriber to topic, where (when an event is triggered), we'll notify the function fn by passing it subscriber_data. Return a handle to the subscribe which can later be passed to pubsub_unsubscribe_().

Functions are called in priority order, from lowest to highest.

See pubsub.h for subscribe_flags.

◆ pubsub_unsubscribe_()

int pubsub_unsubscribe_ ( pubsub_topic_t topic,
const pubsub_subscriber_t s 
)

Remove the subscriber s from topic. After calling this function, s may no longer be used.

Here is the call graph for this function: