1 /* Copyright (c) 2016, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
12 #include "container.h"
14 /** Helper: insert <b>s</b> into <b>topic's</b> list of subscribers, keeping
15 * them sorted in priority order. */
17 subscriber_insert(pubsub_topic_t
*topic
, pubsub_subscriber_t
*s
)
20 smartlist_t
*sl
= topic
->subscribers
;
21 for (i
= 0; i
< smartlist_len(sl
); ++i
) {
22 pubsub_subscriber_t
*other
= smartlist_get(sl
, i
);
23 if (s
->priority
< other
->priority
) {
27 smartlist_insert(sl
, i
, s
);
31 * Add a new subscriber to <b>topic</b>, where (when an event is triggered),
32 * we'll notify the function <b>fn</b> by passing it <b>subscriber_data</b>.
33 * Return a handle to the subscribe which can later be passed to
34 * pubsub_unsubscribe_().
36 * Functions are called in priority order, from lowest to highest.
38 * See pubsub.h for <b>subscribe_flags</b>.
40 const pubsub_subscriber_t
*
41 pubsub_subscribe_(pubsub_topic_t
*topic
,
42 pubsub_subscriber_fn_t fn
,
43 void *subscriber_data
,
44 unsigned subscribe_flags
,
47 tor_assert(! topic
->locked
);
48 if (subscribe_flags
& SUBSCRIBE_ATSTART
) {
49 tor_assert(topic
->n_events_fired
== 0);
51 pubsub_subscriber_t
*r
= tor_malloc_zero(sizeof(*r
));
52 r
->priority
= priority
;
53 r
->subscriber_flags
= subscribe_flags
;
55 r
->subscriber_data
= subscriber_data
;
56 if (topic
->subscribers
== NULL
) {
57 topic
->subscribers
= smartlist_new();
59 subscriber_insert(topic
, r
);
64 * Remove the subscriber <b>s</b> from <b>topic</b>. After calling this
65 * function, <b>s</b> may no longer be used.
68 pubsub_unsubscribe_(pubsub_topic_t
*topic
,
69 const pubsub_subscriber_t
*s
)
71 tor_assert(! topic
->locked
);
72 smartlist_t
*sl
= topic
->subscribers
;
75 int i
= smartlist_pos(sl
, s
);
78 pubsub_subscriber_t
*tmp
= smartlist_get(sl
, i
);
80 smartlist_del_keeporder(sl
, i
);
86 * For every subscriber s in <b>topic</b>, invoke notify_fn on s and
87 * event_data. Return 0 if there were no nonzero return values, and -1 if
91 pubsub_notify_(pubsub_topic_t
*topic
, pubsub_notify_fn_t notify_fn
,
92 void *event_data
, unsigned notify_flags
)
94 tor_assert(! topic
->locked
);
96 smartlist_t
*sl
= topic
->subscribers
;
98 ++topic
->n_events_fired
;
102 SMARTLIST_FOREACH_BEGIN(sl
, pubsub_subscriber_t
*, s
) {
103 int r
= notify_fn(s
, event_data
);
106 } SMARTLIST_FOREACH_END(s
);
108 return (n_bad
== 0) ? 0 : -1;
112 * Release all storage held by <b>topic</b>.
115 pubsub_clear_(pubsub_topic_t
*topic
)
117 tor_assert(! topic
->locked
);
119 smartlist_t
*sl
= topic
->subscribers
;
122 SMARTLIST_FOREACH_BEGIN(sl
, pubsub_subscriber_t
*, s
) {
124 } SMARTLIST_FOREACH_END(s
);
126 topic
->subscribers
= NULL
;
127 topic
->n_events_fired
= 0;