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

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 tasks should be event-driven, but some (like physics system) should be called periodically in the background with constant time (for example after 1/100 sec). I created a block of code, but how can I run this block periodically in background? Is GCD right tool here?

Answers


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


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.)


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)

Need Your Help

Hdfs File Compariosn

hadoop hive hdfs

How can i compare two HDFS files since there is no diff.

NotSupportedException for form controls after receiving data with serial port

c# multithreading serial-port controls windows-ce

I am developing a program for Windows CE with visual studio 2008 . I am using Serialport data_received event to get data but after receiving data(string) when I want to set it to Textbox or Label '...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.