- "comment": "\nThis structure implements scheme 6.2 thom the\nhttp://www.cs.columbia.edu/~nahum/w6998/papers/sosp87-timing-wheels.pdf\nIt supports several primitives:\n1. schedule timer in the future.\n2. cancel timer.\n3. time step (advance) - all timers expired at current time tick are extracted from wheels.\nEach operation take O(1) time.\n\nExample:\n$(DDOX_UNITTEST_HEADER __unittest_L676_C1)\n---\nimport std;\nglobalLogLevel = LogLevel.info;\nauto rnd = Random(142);\n\n/// track execution\nint counter;\nSysTime last = Clock.currTime;\n\n/// this is our Timer\nclass Timer\n{\n static ulong __id;\n private ulong _id;\n private string _name;\n this(string name)\n {\n _id = __id++;\n _name = name;\n }\n /// must provide id() method\n ulong id()\n {\n return _id;\n }\n}\n\nenum IOWakeUpInterval = 100; // to simulate random IO wakeups in interval 0 - 100.msecs\n\n// each tick span 5 msecs - this is our link with time in reality\nenum Tick = 5.msecs;\nTimingWheels!Timer w;\n\nauto durationToTicks(Duration d)\n{\n return d/Tick;\n}\nvoid process_timer(Timer t)\n{\n switch(t._name)\n {\n case \"periodic\":\n writefln(\"@ %s - delta: %sms (should be 50ms)\", t._name, (Clock.currTime - last).split!\"msecs\".msecs);\n last = Clock.currTime;\n counter++;\n w.schedule(t, durationToTicks(50.msecs)); // rearm\n break;\n default:\n writefln(\"@ %s\", t._name);\n break;\n }\n}\n\n//\n// start one arbitrary timer and one periodic timer\n//\nauto some_timer = new Timer(\"some\");\nauto periodic_timer = new Timer(\"periodic\");\nw.schedule(some_timer, durationToTicks(32.msecs));\nw.schedule(periodic_timer, durationToTicks(50.msecs));\n\nwhile(counter < 10)\n{\n auto randomIoInterval = uniform(0, IOWakeUpInterval, rnd).msecs;\n auto nextTimerEvent = max(w.timeUntilNextEvent(Tick), 0.msecs);\n // wait for what should happen earlier\n auto time_to_sleep = min(randomIoInterval, nextTimerEvent);\n writefln(\"* sleep until timer event or random I/O for %s\", time_to_sleep);\n Thread.sleep(time_to_sleep);\n // if we waked up early by the IO event then timeUntilNextEvent will be positive\n // otherwise it will be <= 0 and we have something to process.\n while(w.timeUntilNextEvent(Tick) <= 0.msecs)\n {\n auto ticks = w.ticksUntilNextEvent();\n auto wr = w.advance(ticks);\n foreach(t; wr.timers)\n {\n process_timer(t);\n }\n }\n // some random processing time\n Thread.sleep(uniform(0, 5, rnd).msecs);\n}\n\n---\n$(DDOX_UNITTEST_FOOTER __unittest_L676_C1)\n"
0 commit comments