📜 ⬆️ ⬇️

Strangeness with cycles: in debug it works, in release it is not

Good day, habrayuzer.

For a long time I did not write anything, but here is just a glaring case. Recently I have been writing in Objective C, I have come across many, many incomprehensible situations from which I could look for a day or two. In the end, everything was decided and turned out to be banal and simple. Moreover, “all this was already in the Simpsons” - after the problem was localized, its solution was on the first page of Google.

But here! I debugged the application, I collected it in the archive for the AppStore, I decided to double-check on the device - bugs got it.
')
What happens and how to deal with it - I propose to discuss below


So, my program did the following:
In the main thread (for simplicity I will hereafter call Threads as threads), a global UIScrollView is displayed, in which images, text, audio and video are rendered. For the currently open page, rendering is performed in the same main stream. For a smooth transition to neighboring pages, preliminary rendering is performed in separately created threads (a low-resolution photo is stretched to the screen), and full rendering. Let's call the stream with preliminary rendering by stream # 1, with full stream - stream # 2.

What is a preliminary rendering for? So that the user can quickly turn the pages and see the low-quality page, and not wait every time to download the full version.
Full rendering is understandable. A person reads one page, switches to the next page - and there everything is already loaded, and the “new” next page starts up.

By the way, it’s impossible to render one page from two streams at the same time, that’s why stream ı1 and stream ı2 were waiting for the rendering of the current page by anyone, and then they checked whether there is a preliminary / full rendering or not, and depending on this, they carried out their plans or left.
For all this, the BOOL isRendering flag was used. And in the methods - (void) preRenderPage and - (void) fullRenderPage there was such a construction:

while (! isRendering) {
}
isRendering = YES;

... // directly rendering

isRendering = NO;
return;

Everything worked fine when running from xcode, but stopped working when you started the Archive / release build.
I spent the whole working day on the localization of the problem, but after - I did not find a single mention of it. So, attention!
If the wait cycle is changed like this:
while (! isRendering) {
[NSThread sleepForTimeInterval: 0.01];
}
then everything works again, as in the developer build.

I only have a version that the while loop can be run a limited number of times. When running from xcode, after each instruction, the program communicates with the development environment, and therefore it runs slower. When launching the release version, there is no such delay; the while loop runs too many times and it is killed. Either it is suspended in suspend and is no longer executed.

That's it.

Perhaps, I basically crookedly implemented the wait for the enabling flag, and it was worth it to do it differently. Open my eyes :) Maybe there is something more banal and simpler.

PS the variant with NSRunLoop and [NSDate distantFuture] did not consider, since in the absence of commands, it is executed only once. And to do [NSDate dateWithTimeIntervalSinceNow: 0.01] - in my opinion, it does not differ from my decision, and more cumbersome.

Source: https://habr.com/ru/post/150364/


All Articles