Graphics::setFont and MessageManager Locking

Dear Jules, Roli Team and Community,

I have updated Juce library to the last commit and I observed there is a jassert done in the c786c commit.

Such (two) jassert are in juce_font.cpp:

void Font::getGlyphPositions (const String& text, Array& glyphs, Array& xOffsets) const
{
// This call isn’t thread-safe when there’s a message thread running
jassert (MessageManager::getInstanceWithoutCreating() == nullptr
|| MessageManager::getInstanceWithoutCreating()->currentThreadHasLockedMessageManager());

At this point, it results that my code raise and exception in such assertion when before of that cited commit, it worked flawlessly (IMHO).

Here are the details:

  • On one hand, of course I have a JUCE GUI (Working in Windows, OSX and Linuxes) with the appropiate MessageManager.
  • On the other hand, I have several Graphics contexts not related to any GUI component (so not related with MessageManager). They are created and managed in/by a Job Pool for video ouputting in a Video Broadcast card.

So, when I want to use fonts in such JobPool/Image environments, the assertion jumps warning that the MessageManager is not locked. Do I need to to lock it? I have tried but I cannnot get the lock, alledgelly because there is no relation?

To sum up:
Do i need to lock the message manager?
Is it needed to refine such assertion in order to contemplate the use of a Graphic/Image context not related to any component and so, not related to the message manager (but there is one!)

Thank you in advance,

Gabriel Solsona
Madrid

Yes you need to either run this function on the message thread or get a MessageManager lock. We added this assertion because there can be subtle race conditions when calling the underlying native functions from different threads (as has been reported on the forum). Why can’t you grab the MessageManagerLock?

We’re running into a similar issue where we occasionally need to get some glyph paths in an OpenGL rendering callback. We could grab a MessageManagerLock but that sort of defeats the purpose of rendering this on the OpenGL thread to begin with, and I’m sure it’ll slow down 60 fps rendering once multiple UI’s are open. Are there any other workarounds for this?

If it’s only occasional, couldn’t you have the paths generated by the message thread ready for use by the GL thread somehow…?

It really depends on what you’re trying to do… e.g. if you’re drawing some text over the top of your GL scene as paths, and changing it sometimes, I’d personally avoid generating that on the GL thread, and just have a path that the message thread is in charge of updating.

That makes sense. We’re animating some text behind a complicated OpenGL scene, and the drawText call is what is tripping the assert. When I say occasionally, I mean it’s static most of the time, but in bursts it’s animating at 60 Hz.

It’d certainly be possible to have that text drawing (or getting the paths) happen on the message thread, but there’d have to be some synchronization method (unless I’m overlooking some simpler solution), which may end up being pretty similar to the MessageManagerLock.

Could this somehow be confirmed.
Use a lot of glyph background rendering for years, and didn‘t had any problems with it so far.

1 Like

Looks like this issue is leading to some more serious issues for us. Namely, in some hosts, grabbing a MessageManagerLock on the OpenGL thread can cause a deadlock if the plugin is simultaneously being destroyed.

Is there any other workaround for this? I would imagine other folks also want to animate text on the OpenGL thread without locking the message thread.

1 Like

Worth mentioning that @fabian explicitly suggested NOT locking the message thread here: Another OpenGL deadlock. So it appears that there’s not really a way to call something like setFont in OpenGL in JUCE at the moment.

Sorry to bump an old thread, but we’re running into this issue again. Are there any new solutions to this?

I am also facing a problem with this assert. I am running some background thread that needs to refresh the screen, so I do something like:

void myThread::run()
{
… some processing …

{
const MessageManagerLock mml;

  ... some processing that needs to refresh screen ....

}
}

But when it runs, I get an assertion on getGlyphPositions for every component being redrawn:

jassert (MessageManager::getInstanceWithoutCreating() == nullptr
           || MessageManager::getInstanceWithoutCreating()->currentThreadHasLockedMessageManager());

It seems like at the time these components are drawn, the thread has finished running, and the MessageManager has been therefore unlocked.

I am a bit confused, because that’s how I thought it should be done, but I am probably missing something. Thanks for any help you can provide on this.