By example:
with KSock(0, 'rw') as sender:
with KSock(0, 'rw') as listener:
listener.kernel_module_verbose(True)
listener.bind('$.Fred')
id1 = sender.send_msg(Message('$.Fred'))
# One message for $.Fred
assert listener.num_messages() == 1
listener.bind('$.*')
id2 = sender.send_msg(Message('$.Fred'))
# One message for $.Fred, one for $.*
assert listener.num_messages() == 3
id3 = sender.send_msg(Message('$.Fred'))
# One message for $.Fred, one for $.*
assert listener.num_messages() == 5
listener.unbind('$.Fred')
# The documentation says: "Any messages in the listener's
# message queue which match that unbinding will be removed
# from the queue". But actually the code is just trying to
# remove any messages that match the message name.
#
# XXX BUG
# With the current code, we keep all of the messages because
# they still match $.*. But *some* of them were added for
# $.Fred and some for $.*, so we really shouldn't be keeping
# all of them...
print listener.num_messages()
listener.unbind('$.*')
# And the following prints 5 as well!
#
# XXX BUG
# The code in kbus_forget_matching_messages() compares
# against the "unbind" message name by strncmp() - it doesn't
# check for wildcard matching. So we don't remove any of the
# messages because none of them match the string '$.*'. Oops.
print listener.num_messages()
Fixes:
1. It is wrong that the current code doesn't understand
comparing message names with wildcards.
2. But the correct solution is to make each item in the
message queue remember the message and its reason for
inclusion (i.e., a pointer to the relevant binding
datastructure). Then when we want to remove messages
because of unbinding, we can remove them iff they "belong"
to the binding we're removing. Which may make (1) moot, as
we may not need to compare on message name at all...
Now, consider, what if we bind to $.Fred twice?
Should we:
a. not allow that
b. silently ignore the second binding (ick)
c. allow it, and mark each message with which binding
it belongs to, so we can remove only the messages
we need to when we unbind
(a) feels wrong (although it might be simplest!), since
we're already allowing "overlapping" bindings with wildcards.
(b) just sounds plain wrong, since silent ignoring is the worst
of all worlds.
(c) sounds nice, and comes for free with the Fix proposed
above, but what if we:
1. bind to $.Fred
2. get lots of $.Fred messages in our queue
3. bind to $.Fred again
4. get one more $.Fred message in our queue
5. unbind from $.Fred
Does that choose the most recent or the earlier unbinding
to "undo"? (in other words, how many messages does it
remove). Hmm - I can argue either case, so it's probably
sensible to choose whichever the implementation suggests (!),
so long as it is predictable...