I am writing a game server on twisted, I got to the part when I need to make an event mechanism. This mechanism should create any events that should occur in the future. For example, a player decided to build a building, the building will be built in an hour. Accordingly, in an hour the event “construction” should occur; you can cancel it. There can be a lot of such events, all of them need to be monitored and reported on and canceled. The question is how to organize it? Are there any articles or examples?

  • 2
    I do not know how this is specifically done in python, but in general it is usually like this: you start a counter in each event. Once in some time, dt (usually several seconds) bypass the list of all events and reduce the counter of each event by dt. if the event counter has become less than zero, then you execute the event. second option (slightly more general and slightly less fast): you calculate in advance the time when an event should occur (it is convenient to unixtime) and, again, periodically compare this time for each event with the time on the server. after execution, the event (as a rule) is thrown from the event list. that's all. - alphard
  • If there are A LOT of events, you can organize the list in a special way and bypass it only partially. For example, break it down into sub-lists: "events that should occur in less than 10 minutes", "events that should occur in 10-20 minutes", etc .. You can use other ways to split the list (for example: "events , which should be checked as often as possible "," events that should be checked at least once a minute ", etc.) - alphard
  • Thanks, alphard, could and as the answer to issue. Only the second variant came to my mind, but I began to worry that each run on the list also takes time. That is, it is possible to be late to the accomplishment of any event. Just your second option seems to me much faster than the first. Dividing into groups is a great idea; only these groups, such as in your description, will also have to be managed. Transferring from the event "which should happen in 10-20 minutes" to "in less than 10 minutes" at the right moment, that is, the enumeration of all groups in the background ... - rnd_d
  • you can not divide into groups, but simply sort the list by time of events. and break the loop at a remote time. but the sorting will leave something too. I am glad that I helped with something, I did not single out in a separate answer, because I thought the question was more python-specific :) - alphard

2 answers 2

(The answer is belated, heh, but why not? On SO it was unseen to give answers to old questions, because the wiki is the same.)

I would suggest building a sorted list queue (you can skip to make inserts cheaper) and see, say, once a second, at its end ( O(1) ) is it time to process the next event. The time has come - take the elements from the list (again, O(1) ) until you stumble upon another element whose time has not yet come.

As a result, we have an insert for O(log n) (and even then we can try to optimize it by holding “pointers” to typical places of “60 minutes” type inserts, and update them when we insert / take away, making some inserts for O(1) ), and a sample of the next event (it is also a check whether it is time to do something) for O(1) .

    In twisted there was a method for such things.

     reactor.callLater(3600, createBuilding) 

    after 60 minutes, the createBuilding function will be executed, more details here .

    • one
      The key point - and if the server crashes? - drdaeman
    • collapsed == panic =) Put the description of the task in the database / file, and after it is done, delete it from the file / database. When initiating the north, look into these files / bdshki, call the necessary callLater, or if already createBuilding. - that's what I thought when I tried to do everything on deferreds. In reality, it turned out that for any substantial load this is not applicable, 100-1000 such defaults are still ok, and then a substantial load on the percent. - rnd_d