1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file dispatch.h
* \brief Low-level APIs for message-passing system.
*
* This module implements message dispatch based on a set of short integer
* identifiers. For a higher-level interface, see pubsub.h.
*
* Each message is represented as a generic msg_t object, and is discriminated
* by its message_id_t. Messages are delivered by a dispatch_t object, which
* delivers each message to its recipients by a configured "channel".
*
* A "channel" is a means of delivering messages. Every message_id_t must
* be associated with exactly one channel, identified by channel_id_t.
* When a channel receives messages, a callback is invoked to either process
* the messages immediately, or to cause them to be processed later.
*
* Every message_id_t has zero or more associated receiver functions set up in
* the dispatch_t object. Once the dispatch_t object is created, receivers
* can be enabled or disabled [TODO], but not added or removed.
*
* Every message_id_t has an associated datatype, identified by a
* msg_type_id_t. These datatypes can be associated with functions to
* (for example) free them, or format them for debugging.
*
* To setup a dispatch_t object, first create a dispatch_cfg_t object, and
* configure messages with their types, channels, and receivers. Then, use
* dispatch_new() with that dispatch_cfg_t to create the dispatch_t object.
*
* (We use a two-phase contruction procedure here to enable better static
* reasoning about publish/subscribe relationships.)
*
* Once you have a dispatch_t, you can queue messages on it with
* dispatch_send*(), and cause those messages to be delivered with
* dispatch_flush().
**/
/**
* A "dispatcher" is the highest-level object; it handles making sure that
* messages are received and delivered properly. Only the mainloop
* should handle this type directly.
*/
typedef struct dispatch_t dispatch_t;
;
dispatch_t *;
/**
* Free a dispatcher. Tor does this at exit.
*/
void ;
int ;
int ;
int ;
/* Flush up to <b>max_msgs</b> currently pending messages from the
* dispatcher. Messages that are not pending when this function are
* called, are not flushed by this call. Return 0 on success, -1 on
* unrecoverable error.
*/
int ;
/**
* Function callback type used to alert some other module when a channel's
* queue changes from empty to nonempty.
*
* Ex 1: To cause messages to be processed immediately on-stack, this callback
* should invoke dispatch_flush() directly.
*
* Ex 2: To cause messages to be processed very soon, from the event queue,
* this callback should schedule an event callback to run dispatch_flush().
*
* Ex 3: To cause messages to be processed periodically, this function should
* do nothing, and a periodic event should invoke dispatch_flush().
**/
typedef void ;
int ;
void ;
char *;
/* !defined(TOR_DISPATCH_H) */