Оптимизатор перенес переменную из памяти в регистры. Как результат — изменение значения в памяти другим потоком ничего не дает. Почитайте про специальный модификатор volatile — поймете суть проблемы.
Хорошо. Volatile, так volatile. Спасибо за него, кстати.
Но кто-нибудь может объяснить, почему этого в debug build не происходит, а только в release? Перепроверил все флаги и build settings — все одинаково для обеих конфигураций
Здесь идет работа в рамках одного потока. Но, насколько я понимаю, поставщиком задач является другой поток. В целом, все сводится к задаче «производители/потребители», которая на iOS решается с помощью GCD и sequential очереди задач. Ну, или NSOperationQueue для слабых духом.
За подсказку с NSLock спасибо, в авральном режиме работаем, вылетела из головы эта фича.
По поводу GCD: изначально все писалось на нем, были красивые конструкции вроде dispatch_group_wait и так далее. Но у GCD проблема с рендерингом вьюшек. Поэтому был создан свой класс, унаследованный от NSThread и там была реализована человеческая очередь на выполнение.
Да, вы меня сейчас забросаете помидорами за использование UIKit вне главного потока, но все же это не критично. Ибо главное не обращаться к одной и той же вьюшке из конкурирующих потоков.
У GCD проблемы нет, это у вас проблемы с рендерингом.
Правильный рендеринг на GCD выглядит так:
1. Создаем ContextRef через CreateBitmapContext
2. Рисуем в него как в любой нормальный контекст
3. Создаем из контекста ImageRef
4. Передаем его в основной поток и
4.1. Ставим его в view.layer.contents
4.2. Преобразуем в UIImage и используем в слое-подложке на базе ImageView
А то, что вы делаете — это непонятно что. И оно может отвалиться в любой момент, причем совершенно недетерминированно.
По симптомам — скорее всего компилятор действительно выбросил этот цикл при оптимизации. Тогда вам совершенно необязательно вставлять в цикл sleep, достаточно будет любого выполняемого кода, чтобы компилятор не счел, что цикл ничего не делает. Это если вам именно припекает поскорей залить продукт в App Store.
А вообще в свободное время нужно бы переделать это добро на GCD или NSOperation. Чтобы быстро въехать, что к чему, можно посмотреть эпловое видео, если английский позволяет (https://developer.apple.com/videos/wwdc/2012/, например см. сессию 712)
А вы dead code разве не репортите? А вообще, ИМХО, замечательный пример необходимости образования — не верю, что про такие вещи в ВУЗ'ах не рассказывают совсем.
Dead code — понятие растяжимое. Если имеется в виду бессмысленный код, то что-то ловим, что-то нет. Многий бессмысленный код это продукт использования разнообразных макросов. Таких, например, как UNREFERENCED_PARAMETER. Если речь идёт о недостижимом коде, то с этой задачей хорошо справляются компиляторы. Пока не видно смысла дублировать эту функциональность.
Странности с циклами: в debug работает, в release нет