1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-27 02:20:05 +00:00

Fix for threading bug in GlyphCache.

This commit is contained in:
jules 2014-03-16 15:37:23 +00:00
parent 2f91b1c5f4
commit 2dbd55db3e
3 changed files with 30 additions and 33 deletions

View file

@ -105,18 +105,8 @@ void ReadWriteLock::enterWrite() const noexcept
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
const SpinLock::ScopedLockType sl (accessLock);
for (;;)
while (! tryEnterWriteInternal (threadId))
{
if (readerThreads.size() + numWriters == 0
|| threadId == writerThreadId
|| (readerThreads.size() == 1
&& readerThreads.getReference(0).threadID == threadId))
{
writerThreadId = threadId;
++numWriters;
break;
}
++numWaitingWriters;
accessLock.exit();
waitEvent.wait (100);
@ -127,13 +117,15 @@ void ReadWriteLock::enterWrite() const noexcept
bool ReadWriteLock::tryEnterWrite() const noexcept
{
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
const SpinLock::ScopedLockType sl (accessLock);
return tryEnterWriteInternal (Thread::getCurrentThreadId());
}
bool ReadWriteLock::tryEnterWriteInternal (Thread::ThreadID threadId) const noexcept
{
if (readerThreads.size() + numWriters == 0
|| threadId == writerThreadId
|| (readerThreads.size() == 1
&& readerThreads.getReference(0).threadID == threadId))
|| (readerThreads.size() == 1 && readerThreads.getReference(0).threadID == threadId))
{
writerThreadId = threadId;
++numWriters;

View file

@ -143,6 +143,8 @@ private:
mutable Array <ThreadRecursionCount> readerThreads;
bool tryEnterWriteInternal (Thread::ThreadID) const noexcept;
JUCE_DECLARE_NON_COPYABLE (ReadWriteLock)
};

View file

@ -164,30 +164,16 @@ public:
//==============================================================================
void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, Point<float> pos)
{
const ScopedReadLock srl (lock);
if (CachedGlyphType* glyph = findExistingGlyph (font, glyphNumber))
if (ReferenceCountedObjectPtr<CachedGlyphType> glyph = findOrCreateGlyph (font, glyphNumber))
{
++hits;
glyph->lastAccessCount = ++accessCounter;
glyph->draw (target, pos);
return;
}
const ScopedWriteLock swl (lock);
++misses;
CachedGlyphType* glyph = getGlyphForReuse();
jassert (glyph != nullptr);
glyph->generate (font, glyphNumber);
glyph->lastAccessCount = ++accessCounter;
glyph->draw (target, pos);
}
void reset()
{
const ScopedWriteLock swl (lock);
const ScopedLock sl (lock);
glyphs.clear();
addNewGlyphSlots (120);
hits.set (0);
@ -196,9 +182,26 @@ public:
private:
friend struct ContainerDeletePolicy<CachedGlyphType>;
OwnedArray<CachedGlyphType> glyphs;
ReferenceCountedArray<CachedGlyphType> glyphs;
Atomic<int> accessCounter, hits, misses;
ReadWriteLock lock;
CriticalSection lock;
ReferenceCountedObjectPtr<CachedGlyphType> findOrCreateGlyph (const Font& font, int glyphNumber)
{
const ScopedLock sl (lock);
if (CachedGlyphType* g = findExistingGlyph (font, glyphNumber))
{
++hits;
return g;
}
++misses;
CachedGlyphType* g = getGlyphForReuse();
jassert (g != nullptr);
g->generate (font, glyphNumber);
return g;
}
CachedGlyphType* findExistingGlyph (const Font& font, int glyphNumber) const
{
@ -267,7 +270,7 @@ private:
//==============================================================================
/** Caches a glyph as an edge-table. */
template <class RendererType>
class CachedGlyphEdgeTable
class CachedGlyphEdgeTable : public ReferenceCountedObject
{
public:
CachedGlyphEdgeTable() : glyph (0), lastAccessCount (0) {}