BUG-1120: introduce generations to ListenerMap

This removes the synchronized block in the fast path, biasing the
implementation heavily towards fast readers.

The readers need only to take a volatile reference (AtomicReference),
at which point they have an isolated read-only view of the map.

Writers on the other hand, though, are fully synchronized and are
required to perform a full copy operation, then do the modifications and
finally reinstate the read-only view through setting the atomic
reference.

Change-Id: I5d118177c1508199b66b9e26499c9fc628d3f65e
Signed-off-by: Robert Varga <rovarga@cisco.com>
BUG-1120: fold GenerationalListenerMap back

This moves needless indirection code form GenerationalListenerMap back
to NotificaitonBrokerImpl. Now the contract is directly between
NotificationBrokerImpl and ListenerMapGeneration

Change-Id: I0b401fa4b10e06afbc7206323d1c1f4afb19d422
Signed-off-by: Robert Varga <rovarga@cisco.com>
BUG-1120: optimize notification delivery fast path

Now that the interface contract is completely separated, our fast path
is as good as it gets, except it still allocates a few objects in the
lookup path. These are expected to be generally small, but we do now
they are constant while a particular generation is in place.

This means we can stategically place a LoadingCache, which will
eliminate the need to allocate the objects for notifications which are
often used -- thus the fast path really becomes a lookup by class into a
prepared iterable of listeners. For initial implementation we will place
an upper bound of 1000 entries and see where it leads us.

Change-Id: I2cf39f0d4681aa60afb9d517fb7beef99838bbab
Signed-off-by: Robert Varga <rovarga@cisco.com>
Merge "BUG-1120: introduce generations to ListenerMap"
Merge "BUG-1120: fold GenerationalListenerMap back"
Merge "BUG-1120: optimize notification delivery fast path"