Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite ARTEventEmitter per the spec and adjust Connection. #179

Merged
merged 10 commits into from
Feb 9, 2016

Conversation

tcard
Copy link
Contributor

@tcard tcard commented Feb 1, 2016

Previously, ARTConnection managed state subscriptions and
ARTEventEmitter was just a shell. Now the heavy-lifting of
passing events around is done by ARTEventEmitter, which is
generic and can be reused by others, and ARTConnection just uses
it to emit events and expose its listening interface.

This also introduces ARTConnectionStateChange, used in connection
state events' callbacks, as the spec says.

Something that went away is that starting listening to events
dispatched the current event to the callback. Now it doesn't. It
starts listening to changes from that point on. I think this
makes more sense and is consistent with what you expect from an
event emitter.

Fixes #133.

@tcard
Copy link
Contributor Author

tcard commented Feb 1, 2016

I didn't run the Objective-C test suite. Sorry. Working on that now.

@tcard tcard force-pushed the rewrite-arteventemitter branch from fa9ebd1 to 63d0cc7 Compare February 1, 2016 18:51
@tcard
Copy link
Contributor Author

tcard commented Feb 1, 2016

Passing:

captura de pantalla 2016-02-01 a les 19 51 04

// This way you can automatically "implement the EventEmitter pattern" for a class
// as the spec say. It's supposed to be used together with ART_EMBED_IMPLEMENTATION_EVENT_EMITTER
// in the implementation of the class.
#define ART_EMBED_INTERFACE_EVENT_EMITTER(EventType, ItemType) - (__GENERIC(ARTEventListener, ItemType) *)on:(EventType)event call:(void (^)(ItemType))cb;\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you not use a protocol?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I'm thinking about it and maybe it is not possible using objc protocols with generics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can protocols implement methods and have properties? I think they were just interfaces that implementors had to, well, implement themselves.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you can have properties. I guess you can have the protocol for the interface and have the macro for the implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any case, a protocol suggests that classes can (should?) bring their own implementation for the protocol, when in fact that's not the case here. In this case, they should just provide access to the ARTEventEmitter implementation.

I'd prefer not to overcomplicate the thing with a protocol besides the class.

@mattheworiordan
Copy link
Member

starts listening to changes from that point on. I think this
makes more sense and is consistent with what you expect from an
event emitter.

@tcard yes, that is correct. FYI, we have an unspecified equivalent of how this used to work though, see https://github.com/ably/ably-js/blob/master/common/lib/util/eventemitter.js#L160-L176 and https://github.com/ably/ably-ruby/blob/master/lib/ably/modules/state_emitter.rb#L61-L103. Obviously this is out of spec so not needed

- (instancetype)initWithRealtime:(ARTRealtime *)realtime;
- (id<ARTSubscription>)on:(ARTRealtimeConnectionStateCb)cb;
- (void)removeEvents;
- (__GENERIC(ARTEventListener, ItemType) *)onAll:(void (^)(ItemType))cb;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on our previous discussions about method overloading, I thought we had preferred to use overloading in the end. If so, why do we have onAll as opposed to on(void (^)(ItemType))cb?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overloading is problematic when there is a different number of arguments. Plus, I think we agreed on doing the idiomatic thing... See #158 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we agreed on something quite different, see #121 (comment). I thought #158 was an exception because it was an initializer / constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, you're right, I didn't consider that Objective-C allows overloading with different number of arguments. My previous comment makes no sense. Will change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed at 8aa38f6.

@tcard tcard force-pushed the rewrite-arteventemitter branch 2 times, most recently from 8aa38f6 to 43f6833 Compare February 4, 2016 21:14
@tcard
Copy link
Contributor Author

tcard commented Feb 4, 2016

Rebased, plus two changes: 5cba6ca and 43f6833.

@ricardopereira @mattheworiordan PTAL

- (__GENERIC(ARTEventListener, ItemType) *)once:(void (^)(ItemType __art_nullable))cb;\
\
- (void)off:(EventType)event listener:(__GENERIC(ARTEventListener, ItemType) *)listener;\
- (void)off:(__GENERIC(ARTEventListener, ItemType) *)listener;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there not also meant to be another overloaded off without any params?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(RTE5) EventEmitter#off deregisters a listener for the specified event if given, else it is deregisters that listener for all registrations (global and event-specific)

I understand from that that there is at least a listener parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed at e9f6153997cd248376bd0db611c8e77fad733e08.

@mattheworiordan
Copy link
Member

LGTM, only thing missing from what I can see is an off without any args to remove all listeners

tcard added 9 commits February 9, 2016 00:06
Previously, ARTConnection managed state subscriptions and
ARTEventEmitter was just a shell. Now the heavy-lifting of
passing events around is done by ARTEventEmitter, which is
generic and can be reused by others, and ARTConnection just uses
it to emit events and expose its listening interface.

This also introduces ARTConnectionStateChange, used in connection
state events' callbacks, as the spec says.

Something that went away is that starting listening to events
dispatched the current event to the callback. Now it doesn't. It
starts listening to _changes_ from that point on. I think this
makes more sense and is consistent with what you expect from an
event emitter.

Fixes #133.
Also, remove "ignored" list for total listeners; `off` will just
be a no-op if called with a specific event and a total listener.

See:

ably/docs#82
#179 (comment)
@tcard tcard force-pushed the rewrite-arteventemitter branch from e9f6153 to cacb6eb Compare February 8, 2016 23:06
}
@finally {
for (ARTEventEmitterEntry *entry in toRemoveFromListenersForEvent) {
[listenersForEvent removeObject:entry];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It only removes the occurrence in that array (listenersForEvent).
I think it should use self.listeners.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, good catch. Although I'm not sure what you mean. This should be calling [removeObject:entry fromArrayWithKey:event inDictionary:self.listeners], because that handles the case in which self.listeners[event] is left empty and needs to be deleted to avoid entry leaks. I fixed that at 859e474.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't thought about the special case when I wrote about it but looks great. 👍

@mattheworiordan
Copy link
Member

LGTM 👍

tcard added a commit that referenced this pull request Feb 9, 2016
Rewrite ARTEventEmitter per the spec and adjust Connection.
@tcard tcard merged commit f5b2fe2 into master Feb 9, 2016
@tcard tcard deleted the rewrite-arteventemitter branch February 9, 2016 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants