What is the threading model for player events?

Discussion in 'Plugin Development' started by deltahat, Feb 3, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    deltahat

    How are player events distributed across threads?
    1. All events are dispatched serially through a single event dispatch thread shared between all players.
    2. Each player's events are dispatched serially in the order created through a player's private dispatch thread.
    3. Each individual event from any player is dispatched on its own thread.
    4. Some other model I can't think of.

    The answer to this question will help in ensuring the shared state in MCStats is safe.
     
  2. Offline

    Mixcoatl

    Events could be distributed round-robin style amongst a fixed pool of dispatchers. As to how it's actually done, I have no idea. I supposed I could go dig around on GitHub to find out.
     
  3. Offline

    deltahat

    My initial research indicates that the SimplePluginManager dispatches an event serially across all plugins within the context of whatever thread called callEvent(). CallEvent is called all over within the net.minecraft.server package within the minecraft server contained in the CraftBukkit container. I don't know the threading model within the minecraft server itself - somewhere within the NetCommandReader class maybe. My best guess is that the server implements either thread-per-request or possibly a single thread model for all events.
     
  4. Offline

    eisental

    It seems that there are about 20 threads running on the server at a given time even without any players logged it. I'm not sure, but as I understand it its mostly a big mess of threads created by the original server and craftbukkit hooks to different threads for different event calls as you said. A async/sync task scheduler with a thread pool was written and will be hopefully added soon.
     
  5. Offline

    Raphfrk

    There is one main server thread. All events are (should be) handled by that thread.

    The other threads just provide support to that main thread.

    Also, calling API functions from anything other than the main thread is thread unsafe.

    P.S.
    This is the pull request that implements a scheduler :). This allows other threads to pass tasks to the main thread for execution (among other things).
     
  6. Offline

    eisental

    Thanks for clarifying...
    Well done for the latest pull request, it looks great. I really hope its good enough for the bukkit people :)
    I hope it's not too OT but is it possible to count on the game ticks being around 50ms per tick? I mean, if i'm trying to schedule something according to real world time can I just divide it by 20 and use the game ticks instead? or would it be better to maintain my own timer and call scheduleSyncDelayedTask() with no delay?

    And, if I understand correctly the async methods should never be used to call API functions, right?
     
  7. Offline

    Raphfrk

    Me too.

    Not 100% sure on that. There might be a loss of alignment when the "server can't keep up" message happens.

    Otherwise, it does use the System.currentTimeMillis() method to work out the time and keeps aligned to 50ms steps.

    Well, I guess it depends on how accurate you really need it to be :). If you do a backup every 30 mins, I don't think it should matter if it happens every 31 mins.

    Not to go from real time (in seconds) to ticks, you multiply by 20 :).

    Right, they are handled by a thread pool that is separate from the main thread. To call API functions from async threads, you would have to use the scheduler to re-align them.
     
  8. Offline

    eisental

    Ok, thanks, It's mostly for my clock circuit that should work reliably with small intervals (such as 50ms) but doesn't have to keep it up completely in sync with system time.
     
  9. Offline

    exemplar

    It would be fantastic if your request was pulled in. I can't believe this (or something along these lines) wasn't included from the start.
     
  10. Offline

    Borch

    I think it even should "lag" or whatever the server does, so that when all the game runs slow, your circuits do too.

    Btw., did I get that right that Raph's scheduler now got merged into trunk?
    If so, is there any short documentation on how to use it from an async thread?
     
  11. Offline

    eisental

    Indeed, its finally merged. I'm already using it for RedstoneChips 0.77 (I just updated).
    There's a short demo at the first post here, which shows how nicely it can work for sequencing.

    There was some documentation on using it on the craftbukkit pull request but I can't find it now.
    Anyway, it's very easy.

    You get an instance of the scheduler: getServer().getScheduler()
    And then you can use any of its methods for all kinds of sync/async scheduling.
    The javadocs explain what each method does.
     
  12. Offline

    Borch

    So I basically need to use the Sync* calls for anything critical I want to do from another thread, right?
    What would I use the Async* ones for then? Just for delayed/repeating tasks that do not interact with the server/API and I do not want to create an own thread for?
     
  13. Offline

    eisental

    Yeah, you use the sync to make changes to the server from another thread. The async could use some clarification... It's probably useful for anything else that needs to sync with the game ticks but would take too much time from the server thread if it would run in sync.
     
  14. Offline

    Afforess

    I was under the impression that calling functions that directly interacted with notch's code (like player.getHealth()) was safe, but dealing with cached objects, like Blocks was unsafe.
     
  15. Offline

    Raphfrk

    That could be true. I probably should have said "potentially" thread-unsafe.

    It would be nice if there was a list of API functions that are thread safe.
     
Thread Status:
Not open for further replies.

Share This Page