Is it possible to lock a variable?

This may be more a general C++ question, but since JUCE has some thread capability of its own, I’ll ask here.

I’m 99% done with an Arcade game. Finalizing and looking over the code to optimize, I have tried to remove as many calculations from paint() as possible, since especially at higher app solutions, it gets out of sync from my hiRes timer, or rather paint() runs slower, but it is ok since animated objects moves the same distance, only a bit less smooth.

So I have some variables that holds colors needed in paint, but they get changed over time as the game progresses.

I tried to move these color change variables to the hiRes timer thread, and it works fine, except at higher app resolution where paint() can’t keep up, and there is a slight flicker.

So my question is;

Is there anyway to, in paint() lock the variables right before use, and then unlock them after they are no longer needed.

or

Do I have to create some kind of thread function, which I then call from both my hiRes timer to set the values, and from my paint() to read the values?

https://docs.juce.com/master/classCriticalSection.html
https://docs.juce.com/master/group__juce__core-threads.html#gadd0b55041ea549cc9b1dfae71670e543

struct Foo
{
    void a() 
    {
        const ScopedLock sl(lock);
        i += 1;
    }

    void b()
    {
        const ScopedLock sl(lock);
        DBG( "i:  " << i );
    }
private:
    CriticalSection lock;
    int i;
};

Juce’s HighResolutionTimer already works from a different thread, which may be the reason you are seeing “odd” results.

Ahh yes I formulated that wrong. I meant “Do I have to create some kind of protected/locked function, which I then call from both my hiRes timer to set the values, and from my paint() to read the values?”

You definitely must somehow synchronize the variables if different threads are writing and reading them. You might get away with something like bools or floats (and even that is debatable), but something like Colour probably isn’t thread safe. (Even though I think it internally just uses a 32 bit integer for its data…)

I guess another way to formulate what I need is;

When paint() is about to use said variables, I want to “lock” then to prevent, hiRes timer from changing them. Well now thinking about it, I may just be able to use a simple flag I test in hiRes timer.

Why are you using another thread to begin with, if you just want to lock it from the GUI thread? Can that other thread do any useful work while the GUI thread is locked?

Not sure what you mean, why am I using another thread.

I only got hiResTimerCallback and paint()

Right, the HighResolutionTimer creates another thread for you, but the timer isn’t going to be that fast and high resolution anymore if you block it from running from your GUI thread. Here I am assuming you would go with the CriticalSection approach posted above to synchronize the variables. However, if you do the locking more fine grained with CriticalSection, it might not be so bad…

Actually for my particular issue, I solved it with a simple flag, testing in hiRes timer to only change color variables if not in use, and in paint() sets it to “being used” and after painting away like Picasso, sets it to clear.

Yeah, the flag thing is a typical approach that can also be used for audio apps/plugins when the GUI needs to paint something based on the audio.

Screen shot is in two player one-on-one game mode, of which there are three game modes, and with one cyan brick spawning a new ball. Black bricks is deliberately hard to see black holes that sucks in the ball and spits it out at a random place later. Red bricks gives an extra life.

1 Like

Why can’t you just use Timer?

struct Foo : Component, Timer
{
    Foo() { startTimerHz(60); }
    ~Foo() { stopTimer(); }
    void paint(Graphics& g) override { ... }
    void timerCallback() override { repaint(); }
};

everything will be called from the Message Thread, so there will be no issues with needing to have thread synchronization.

For my game I found Timer to be too susceptible to what else the OS has going on, as it sometimes slows down the system, meaning my animated objects moves less fluent, sometimes slowing down a bit if Windows hogs up my CPU.

OpenGLRenderer is probably what you ultimately want in the end. paint() is called on the message thread, so it’s still going to be susceptible to the same lag issues you’re talking about. HiResolutionTimer isn’t going to help make the paint() function run any faster since it’s not even running on the same thread.

Ok I just remember I could see a difference (animated objects appearing more fluently on the screen) in the early stages of the game development, as I first used Timer, then moved to HighResolutionTimer.

One good thing about using the HighResolutionTimer, as it uses a separate thread, is that in a system where the graphics, paint(), takes too long, or if I switch my game to higher resolution, the hiRes timer still calculates the right new coordinates for the animated objects. So once paint() gets around to finish its nap, it will draw them where they should be.

In other words if I use the regular Timer and switch to high resolution, the whole game will slow down because the drawing that is going on in paint, takes longer than what goes on in Timer. Now at least using the HighResolutionTimer it still looks, well not perfect, but great at any resolution.

I think using a separate thread to run the game engine makes good sense, for the reasons you mention. Rendering the game is like rendering audio, and the GUI is just a view into that, just like the ui for a plugin.