Tor
0.4.7.0-alpha-dev
|
Macros to help with the publish/subscribe dispatch API. More...
#include "lib/cc/compat_compiler.h"
#include "lib/dispatch/dispatch_naming.h"
#include "lib/pubsub/pub_binding_st.h"
#include "lib/pubsub/pubsub_connect.h"
#include "lib/pubsub/pubsub_flags.h"
#include "lib/pubsub/pubsub_publish.h"
Go to the source code of this file.
Macros | |
#define | DECLARE_MESSAGE_COMMON__(messagename, typename, c_type) |
#define | DECLARE_MESSAGE(messagename, typename, c_ptr_type) |
#define | DECLARE_MESSAGE_INT(messagename, typename, c_type) |
#define | DECLARE_PUBLISH(messagename) |
#define | DECLARE_SUBSCRIBE(messagename, hookfn) |
#define | DISPATCH__FAKE_USE_OF_PUBFN_(messagename) |
#define | DISPATCH_ADD_PUB_(connector, channel, messagename, flags) |
#define | DISPATCH_ADD_PUB(connector, channel, messagename) DISPATCH_ADD_PUB_(connector, channel, messagename, 0) |
#define | DISPATCH_ADD_PUB_EXCL(connector, channel, messagename) DISPATCH_ADD_PUB_(connector, channel, messagename, DISP_FLAG_EXCL) |
#define | DISPATCH_ADD_SUB_(connector, channel, messagename, flags) |
#define | DISPATCH_ADD_SUB(connector, channel, messagename) DISPATCH_ADD_SUB_(connector, channel, messagename, 0) |
#define | DISPATCH_ADD_SUB_EXCL(connector, channel, messagename) DISPATCH_ADD_SUB_(connector, channel, messagename, DISP_FLAG_EXCL) |
#define | PUBLISH(messagename, arg) publish_fn__ ##messagename(arg) |
#define | DISPATCH_REGISTER_TYPE(con, type, fns) |
Macros to help with the publish/subscribe dispatch API.
The dispatch API allows different subsystems of Tor to communicate with another asynchronously via a shared "message" system. Some subsystems declare that they publish a given message, and others declare that they subscribe to it. Both subsystems depend on the message, but not upon one another.
To declare a message, use DECLARE_MESSAGE() (for messages that take their data as a pointer) or DECLARE_MESSAGE_INT() (for messages that take their data as an integer. For example, you might say
DECLARE_MESSAGE(new_circuit, circ, circuit_handle_t *);
or DECLARE_MESSAGE_INT(shutdown_requested, boolean, bool);
Every message has a unique name, a "type name" that the dispatch system uses to manage associated data, and a C type name. You'll want to put these declarations in a header, to be included by all publishers and all subscribers.
When a subsystem wants to publish a message, it uses DECLARE_PUBLISH() at file scope to create necessary static functions. Then, in its subsystem initialization (in the "bind to dispatcher" callback) (TODO: name this properly!), it calls DISPATCH_ADD_PUB() to tell the dispatcher about its intent to publish. When it actually wants to publish, it uses the PUBLISH() macro. For example:
// At file scope DECLARE_PUBLISH(shutdown_requested); static void bind_to_dispatcher(pubsub_connector_t *con) { DISPATCH_ADD_PUB(con, mainchannel, shutdown_requested); } // somewhere in a function { PUBLISH(shutdown_requested, true); }
When a subsystem wants to subscribe to a message, it uses DECLARE_SUBSCRIBE() at file scope to declare static functions. It must declare a hook function that receives the message type. Then, in its "bind to dispatcher" function, it calls DISPATCHER_ADD_SUB() to tell the dispatcher about its intent to subscribe. When another module publishes the message, the dispatcher will call the provided hook function.
// At file scope. The first argument is the message that you're // subscribing to; the second argument is the hook function to declare. DECLARE_SUBSCRIBE(shutdown_requested, on_shutdown_req_cb); // You need to declare this function. static void on_shutdown_req_cb(const msg_t *msg, bool value) { // (do something here.) } static void bind_to_dispatcher(pubsub_connector_t *con) { DISPATCH_ADD_SUB(con, mainchannel, shutdown_requested); }
Where did these types come from? Somewhere in the code, you need to call DISPATCH_REGISTER_TYPE() to make sure that the dispatcher can manage the message auxiliary data. It associates a vtbl-like structure with the type name, so that the dispatcher knows how to manipulate the type you're giving it.
For example, the "boolean" type we're using above could be defined as:
static char *boolean_fmt(msg_aux_data_t d) { // This is used for debugging and dumping messages. if (d.u64) return tor_strdup("true"); else return tor_strdup("false"); }
static void boolean_free(msg_aux_data_t d) { // We don't actually need to do anything to free a boolean. // We could use "NULL" instead of this function, but I'm including // it as an example. }
static void bind_to_dispatcher(pubsub_connector_t *con) { dispatch_typefns_t boolean_fns = { .fmt_fn = boolean_fmt, .free_fn = boolean_free, }; DISPATCH_REGISTER_TYPE(con, boolean, &boolean_fns); }
So, how does this all work? (You can stop reading here, unless you're debugging something.)
When you declare a message in a header with DECLARE_MESSAGE() or DECLARE_MESSAGE_INT(), it creates five things:
All of these declarations have names based on the message name.
Later, when you say DECLARE_PUBLISH() or DECLARE_SUBSCRIBE(), we use the elements defined by DECLARE_MESSAGE() to make sure that the publish function takes the correct argument type, and that the subscription hook is declared with the right argument type.
Definition in file pubsub_macros.h.
#define DECLARE_MESSAGE | ( | messagename, | |
typename, | |||
c_ptr_type | |||
) |
Use this macro in a header to declare the existence of a given message, taking a pointer as auxiliary data.
"messagename" is a unique identifier for the message; it must be a valid C identifier.
"typename" is a unique identifier for the type of the auxiliary data. It needs to be defined somewhere in Tor, using "DISPATCH_REGISTER_TYPE."
"c_ptr_type" is a C pointer type (like "char *" or "struct foo *"). The "*" needs to be included.
Definition at line 192 of file pubsub_macros.h.
#define DECLARE_MESSAGE_COMMON__ | ( | messagename, | |
typename, | |||
c_type | |||
) |
Macro to declare common elements shared by DECLARE_MESSAGE and DECLARE_MESSAGE_INT. Don't call this directly.
Note that the "msg_arg_name" string constant is defined in each translation unit. This might be undesirable; we can tweak it in the future if need be.
Definition at line 173 of file pubsub_macros.h.
#define DECLARE_MESSAGE_INT | ( | messagename, | |
typename, | |||
c_type | |||
) |
Use this macro in a header to declare the existence of a given message, taking an integer as auxiliary data.
"messagename" is a unique identifier for the message; it must be a valid C identifier.
"typename" is a unique identifier for the type of the auxiliary data. It needs to be defined somewhere in Tor, using "DISPATCH_REGISTER_TYPE."
"c_type" is a C integer type, like "int" or "bool". It needs to fit inside a uint64_t.
Definition at line 219 of file pubsub_macros.h.
#define DECLARE_PUBLISH | ( | messagename | ) |
Use this macro inside a C module declare that we'll be publishing a given message type from within this module.
It creates necessary functions and wrappers to publish a message whose unique identifier is "messagename".
Before you use this, you need to include the header where DECLARE_MESSAGE*() was used for this message.
You can only use this once per message in each subsystem.
Definition at line 245 of file pubsub_macros.h.
#define DECLARE_SUBSCRIBE | ( | messagename, | |
hookfn | |||
) |
Use this macro inside a C file to declare that we're subscribing to a given message and associating it with a given "hook function". It declares the hook function static, and helps with strong typing.
Before you use this, you need to include the header where DECLARE_MESSAGE*() was used for the message whose unique identifier is "messagename".
You will need to define a function with the name that you provide for "hookfn". The type of this function will be: static void hookfn(const msg_t *, const c_type) where c_type is the c type that you declared in the header.
You can only use this once per message in each subsystem.
Definition at line 272 of file pubsub_macros.h.
#define DISPATCH__FAKE_USE_OF_PUBFN_ | ( | messagename | ) |
Add a fake use of the publish function for 'messagename', so that the compiler does not call it unused.
Definition at line 287 of file pubsub_macros.h.
#define DISPATCH_ADD_PUB | ( | connector, | |
channel, | |||
messagename | |||
) | DISPATCH_ADD_PUB_(connector, channel, messagename, 0) |
Use a given connector and channel name to declare that this subsystem will publish a given message type.
Call this macro from within the add_subscriptions() function of a module.
Definition at line 313 of file pubsub_macros.h.
#define DISPATCH_ADD_PUB_ | ( | connector, | |
channel, | |||
messagename, | |||
flags | |||
) |
This macro is for internal use. It backs DISPATCH_ADD_PUB*()
Definition at line 294 of file pubsub_macros.h.
#define DISPATCH_ADD_PUB_EXCL | ( | connector, | |
channel, | |||
messagename | |||
) | DISPATCH_ADD_PUB_(connector, channel, messagename, DISP_FLAG_EXCL) |
Use a given connector and channel name to declare that this subsystem will publish a given message type, and that no other subsystem is allowed to.
Call this macro from within the add_subscriptions() function of a module.
Definition at line 322 of file pubsub_macros.h.
#define DISPATCH_ADD_SUB | ( | connector, | |
channel, | |||
messagename | |||
) | DISPATCH_ADD_SUB_(connector, channel, messagename, 0) |
Use a given connector and channel name to declare that this subsystem will receive a given message type.
Call this macro from within the add_subscriptions() function of a module.
Definition at line 343 of file pubsub_macros.h.
#define DISPATCH_ADD_SUB_ | ( | connector, | |
channel, | |||
messagename, | |||
flags | |||
) |
This macro is for internal use. It backs DISPATCH_ADD_SUB*()
Definition at line 328 of file pubsub_macros.h.
#define DISPATCH_ADD_SUB_EXCL | ( | connector, | |
channel, | |||
messagename | |||
) | DISPATCH_ADD_SUB_(connector, channel, messagename, DISP_FLAG_EXCL) |
Use a given connector and channel name to declare that this subsystem will receive a given message type, and that no other subsystem is allowed to do so.
Call this macro from within the add_subscriptions() function of a module.
Definition at line 352 of file pubsub_macros.h.
#define DISPATCH_REGISTER_TYPE | ( | con, | |
type, | |||
fns | |||
) |
Use a given connector to declare that the functions to be used to manipuate a certain C type.
Definition at line 366 of file pubsub_macros.h.
#define PUBLISH | ( | messagename, | |
arg | |||
) | publish_fn__ ##messagename(arg) |
Publish a given message with a given argument. (Takes ownership of the argument if it is a pointer.)
Definition at line 359 of file pubsub_macros.h.