Alexandre Janniaux
authored
Report events from a different thread than the main thread, and continue to execute the main CFRunLoop, but filter the events to only execute the ones queued by potential display, ie. those tagged with the mode "vlc_runloop". The vlc_runloop mode is designed to be executed even when an event is being reported by the vout_window used, ie. when there is a call to CFRunLoopInMode(CFRunLoopGetMain(), CFSTR("vlc_runloop"), ..). Clients should ensure they also tag their blocks with the default mode too. Otherwise, they are likely to never be executed. Async tasks can still be dispatched without the "vlc_runloop" mode but every sync tasks in the display must be done under this mode to prevent deadlock from happening between the main thread and the vout_thread, typically with the following code: /* The main loop to run the block into */ CFRunLoopRef runloop = CFRunLoopGetMain(); /* The modes to execute the block in */ CFStringRef modes_cfstrings[] = { kCFRunLoopDefaultMode, CFSTR("vlc_runloop") }; CFArrayRef modes = CFArrayCreate(NULL, (const void **)modes_cfstrings, ARRAY_SIZE(modes_cfstrings), &kCFTypeArrayCallBacks); CFRunLoopPerformBlock(runloop, modes, ^{ /* The block content to execute */ }); /* Don't forget to signal the runloop CFRunLoopWakeUp(runloop); CFRelease(modes); To achieve a blocking/sync behaviour, clients can share a binary semaphore between the block and the outside of the block. When using a vlc_sem_t object, it must be qualified with __block to be modified inside of the block. Refs #23571