How can I run code block in background periodically using GCD?

后端 未结 3 1878
执念已碎
执念已碎 2021-02-08 05:55

How can I run code block in background periodically using GCD? I am trying to write a game engine with several subsystems, like rendering, physics, game logic and so on. Some ta

相关标签:
3条回答
  • 2021-02-08 06:27

    In Swift you can create timer using GCD:

    func CreateTimerDispatchSource(interval: UInt64, leeway: UInt64, queue: dispatch_queue_t, block: dispatch_block_t) -> dispatch_source_t {
        let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
        dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), interval, leeway)
        dispatch_source_set_event_handler(timer, block)
        return timer;
    }
    
    var timer = CreateTimerDispatchSource(5*NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
      // do some serious stuff
    }
    

    Start or resume timer:

    dispatch_resume(timer)
    

    Suspend timer:

    dispatch_suspend(timer)
    
    0 讨论(0)
  • 2021-02-08 06:31

    As @matt notes in the comments, you can use timer dispatch sources for this. See his answer for the right approach there.

    For posterity, here's my original answer with some alternatives:

    1. In your render callback (say, using CADisplayLink), fire off a GCD job that computes the physics for this (or the next?) frame. If you need to do more than one update per render frame, just have that job loop a couple times.

    2. Have a physics thread that sleeps itself until it next needs to do some computation. If you have a separate thread for this, NSTimer might have sufficient resolution to wake your thread up at 100 Hz. (On the main thread, this wouldn't work because other input sources on the runloop will prevent it from firing that fast consistently.) If NSTimer doesn't work, just compute how much time is left until the next physics update you need and sleep your thread (via, e.g., [NSThread sleepForTimeInterval:])

    3. Have a block that uses dispatch_after.

    Something like this:

    dispatch_time_t next = dispatch_time(DISPATCH_TIME_NOW, 0);
    block = ^{
        next = dispatch_time(next, 10000000L); // increment by 10 ms
        // do physics here
        dispatch_after(next, queue, block);
    }
    

    You might need to be a bit smarter about dropping frames, (i.e. detect if your next time is in the past before calling dispatch_after it, etc.)

    0 讨论(0)
  • 2021-02-08 06:45

    What you want is a GCD dispatch source. For sample code, see the Creating a Timer Example.

    0 讨论(0)
提交回复
热议问题