+ Reply to Thread
Results 1 to 11 of 11

  Click here to go to the first Rift Team post in this thread.   Thread: Unsubscribing from events

  1. #1
    Rift Disciple Thorarin's Avatar
    Join Date
    Oct 2011
    Posts
    136

    Default Unsubscribing from events

    Some time ago there was a discussion about addons unsubscribing from events using table.remove.
    If I understand correctly there are actually two issues with this:
    • If the event is unsubscribed from within the event handler itself, the next event handler is skipped because it's shifted down in the event table.
    • Some addons apparently store an index to their own entry in the event table. This index would no longer be valid.

    I would say the second issue is really the fault of the other addon, the first one is a genuine problem.
    Someone suggested changing the respective entry to an empty function in order to unsubscribe...

    However, I was thinking that unsubscribing could be done safely like this:

    Code:
    local function unsubscribeEvent(eventTable, addonIdentifier, text)
    	for k,v in ipairs(eventTable) do
    		if v[2] == addonIdentifier and v[3] and v[3] == text then
    			eventTable[k] = nil
    			return true
    		end
    	end
    	return false
    end
    Rift event handling does not seem to be affected by it, so the first issue should not occur. Also, there is no renumbering, so we should be safe from the second issue as well.
    Setting the entry to nil will allow Lua to reuse the table entries (since the default table.insert position is any nil position). In any case it will keep the table cleaner.

    Thoughts?
    Last edited by Thorarin; 06-28-2012 at 12:27 PM.

  2. #2
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default

    Quote Originally Posted by Thorarin View Post
    I would say the second issue is really the fault of the other addon, the first one is a genuine problem.
    Not necessarily, as storing the index follows naturally from the table.insert idiom. So does table.remove.

    Your suggestion will not work if the event dispatcher is using ipairs() or the #-operator to traverse the table as those stop at gaps. This also affects the C-function lua_objlen. So unless Rift is internally using lua_next for event dispatching it won't work. You would basically cut off all event handlers following yours.

    MessageViewer is using a for-loop to simulate received addon messages locally. That behaviour would break it. Any addon attempting to dispatch events manually would need to consider this.

    It's still an interesting suggestion.

  3. #3
    Sword of Telara Semele's Avatar
    Join Date
    Mar 2011
    Posts
    872

    Default

    I actually changed Safe's Raid Manager to not unsubscribe, but simply change the function assigned to the Event.

    For my purpose it still goes to a new working function, but there would be nothing stopping anyone having a dummy() function that does nothing other than return. Yes, it's horrible to think of the extra CPU cycle or two, but better than the alternative at the moment. And with modern CPU's I'm confident a 1 shot function call will be fine for now.
    Rank 76 Guardian Mage

  4. #4
    Rift Disciple Thorarin's Avatar
    Join Date
    Oct 2011
    Posts
    136

    Default

    Quote Originally Posted by Imhothar View Post
    Your suggestion will not work if the event dispatcher is using ipairs() or the #-operator to traverse the table as those stop at gaps. This also affects the C-function lua_objlen. So unless Rift is internally using lua_next for event dispatching it won't work. You would basically cut off all event handlers following yours.
    At first I thought Rift wasn't using the table "length" somehow, but now I'm not so sure.
    It seems that the events just following the unsubscribe are working properly, but I think that consecutive events aren't being dispatched. I need to check again when I'm awake however

  5. #5
    Champion Lorandii's Avatar
    Join Date
    Jun 2011
    Posts
    516

    Default

    The ONLY safe way to unsubscribe to an event is to create it with LibCallbackHandler. Rift's event structure is interesting, but leaves a few things to be desired. If you are familiar with how the WoW version works, it is the exact same API. If not, don't worry, I will document as soon as I get back from vacation.

    This only works for events the addon author creates, and will not work for Rift's built in event system.

  6. #6
    Rift Disciple Thorarin's Avatar
    Join Date
    Oct 2011
    Posts
    136

    Default

    Quote Originally Posted by Lorandii View Post
    The ONLY safe way to unsubscribe to an event is to create it with LibCallbackHandler.
    I can understand you wanting to plug your library, but this statement is a slight exaggeration
    In my case I need to unsubscribe from built-in events, so I won't be able to use this unfortunately.

  7. #7
    Champion Lorandii's Avatar
    Join Date
    Jun 2011
    Posts
    516

    Default

    Yep, I know. I did mention it won't work with the built in Rift events. Unless someone with much better programming skills than I have can figure out how to code a wrapper, we are stuck not being able to unregister events. The library is a replacement for Utility.Event.Create, and that's it.

    Didn't Zorba mention recently that he wanted to look at the event system for a future patch (2.0+ ?) in order to address some issues? He didn't specifically mention unregistering, and I don't want to put words in his mouth. Can someone find what he actually said please?

  8.   This is the last Rift Team post in this thread.   #8
    Rift Team
    Join Date
    Oct 2010
    Posts
    927

    Default

    Quote Originally Posted by Lorandii View Post
    Can someone find what he actually said please?
    I don't know exactly what I said, but essentially, I'm playing around with some Event API 2.0 plans (not to be confused with Rift 2.0 - this may end up being before or after that) that will allow for some performance improvements as well as make it easier to unregister.

    These may take a bit, they're competing with a lot of other things for time.

  9. #9
    Rift Disciple Thorarin's Avatar
    Join Date
    Oct 2011
    Posts
    136

    Default

    Quote Originally Posted by ZorbaTHut View Post
    I don't know exactly what I said, but essentially, I'm playing around with some Event API 2.0 plans (not to be confused with Rift 2.0 - this may end up being before or after that) that will allow for some performance improvements as well as make it easier to unregister.

    These may take a bit, they're competing with a lot of other things for time.
    For the time being I have chosen a somewhat dirty approach, but it is unregistering (sort of).

    I replace the function with an empty one, much like Safe does. When I later resubscribe, I reuse entries that point to the empty function. That way repeated subs and unsubs would not flood the table. Subscribing is a little slower, actually handling events would be a little faster (in theory).

    Because Lua has no clean way to detect if a function is actually empty, and I want to give other authors the opportunity to reuse "my" event slots, I've added a bit of a hack... I still feel dirty :P

    Code:
    if Utility.GlobalEmptyFunction == nil then
    	Utility.GlobalEmptyFunction = function () end
    end
    By abusing the "namespace" I give other authors potential access to the empty function I use to unsubscribe. The if statement ensures it's never redefined if this code is copied into a second addon.

    Of course it would be much better if there were built-in functions for subscribing and unsubscribing
    Last edited by Thorarin; 07-02-2012 at 11:18 PM.

  10. #10
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default

    Man, you're trying to optimize something that will never have any measurable impact. Executing the event handlers is what takes time, not traversing the table. Calling an empty function is almost like a no-op. Reusing an event table entry is nice and all, just don't overengineer it.

    No one will actually use your Utility.GlobalEmptyFunction if it's not part of a dependent library (because checking whether that thing exists is actually more work than just setting the damn event variable to an empty function).

    But don't let my answer discourage your creativity ;)
    Last edited by Imhothar; 07-03-2012 at 11:15 AM.
    Author of the Imhothar's Bags addon.

  11. #11
    Rift Disciple Thorarin's Avatar
    Join Date
    Oct 2011
    Posts
    136

    Default

    The point was that anyone can create the function if it does not exist, without needing a library resulting in another file for a single line of code.
    I'm fine with people not using it... for me it was mostly about how it could be done in a way that it works across multiple addons.

+ Reply to Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts