In certain cases where the font thread is not joined,
such as when there is no UI or when the font client is not used.
this patch ensures the join of the font thread by invoking the join method in the destructor.
Change-Id: I8ffcf21ab9dcc1b1e4de54e50adb23d0796b996e
Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
Internal::FontClient::PreLoad(fontPathList, memoryFontPathList, useThread, syncCreation);
}
Internal::FontClient::PreLoad(fontPathList, memoryFontPathList, useThread, syncCreation);
}
+void FontClientJoinFontThreads()
+{
+ Internal::FontClient::JoinFontThreads();
+}
+
} // namespace TextAbstraction
} // namespace Dali
} // namespace TextAbstraction
} // namespace Dali
*/
DALI_ADAPTOR_API void FontClientFontPreLoad(const FontPathList& fontPathList, const FontPathList& memoryFontPathList, bool useThread, bool syncCreation);
*/
DALI_ADAPTOR_API void FontClientFontPreLoad(const FontPathList& fontPathList, const FontPathList& memoryFontPathList, bool useThread, bool syncCreation);
+/**
+ * @brief Joins font threads, waiting for their execution to complete.
+ */
+DALI_ADAPTOR_API void FontClientJoinFontThreads();
+
} // namespace TextAbstraction
} // namespace Dali
} // namespace TextAbstraction
} // namespace Dali
DALI_TRACE_END(gTraceFilter, "DALI_APP_EMIT_INIT_SIGNAL");
mAdaptor->NotifySceneCreated();
DALI_TRACE_END(gTraceFilter, "DALI_APP_EMIT_INIT_SIGNAL");
mAdaptor->NotifySceneCreated();
+
+ // Ensure the join of Font thread at this point
+ Dali::TextAbstraction::FontClientJoinFontThreads();
}
void Application::OnTerminate()
}
void Application::OnTerminate()
+class FontThread
+{
+/*
+ * There are cases in the candidate process where the font thread is
+ * no UI or when the font client is not used.
+ * In such cases, we can ensure the join of the font thread
+ * by calling the join method in the destructor of this class.
+ */
+public:
+ FontThread()
+ {
+ }
+ ~FontThread()
+ {
+ if(mThread.joinable())
+ {
+ mThread.join();
+ }
+ }
+ std::thread mThread;
+};
+
Dali::TextAbstraction::FontClient FontClient::gPreCreatedFontClient(NULL);
Dali::TextAbstraction::FontClient FontClient::gPreCreatedFontClient(NULL);
-std::thread gPreCacheThread;
-std::thread gPreLoadThread;
+
+FontThread gPreCacheThread;
+FontThread gPreLoadThread;
std::mutex gMutex;
std::condition_variable gPreCacheCond;
std::condition_variable gPreLoadCond;
std::mutex gMutex;
std::condition_variable gPreCacheCond;
std::condition_variable gPreLoadCond;
}
else // create and register the object
{
}
else // create and register the object
{
- if(gPreCacheThread.joinable())
- {
- gPreCacheThread.join();
- FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreCache thread join\n");
- }
-
- if(gPreLoadThread.joinable())
- {
- gPreLoadThread.join();
- FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreLoad thread join\n");
- }
+ // Check the joinable status of PreCahe and PreLoad thread, and join them
+ JoinFontThreads();
if(gPreCreatedFontClient)
{
if(gPreCreatedFontClient)
{
- if(gPreCacheThread.joinable())
+ if(gPreCacheThread.mThread.joinable())
{
FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient pre-cache thread already running.\n");
{
FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient pre-cache thread already running.\n");
}
if(!gPreCreatedFontClient)
}
if(!gPreCreatedFontClient)
gPreCacheThreadReady = false;
std::unique_lock<std::mutex> lock(gMutex);
FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "BEGIN: DALI_TEXT_PRECACHE_THREAD_SYNC_CREATION\n");
gPreCacheThreadReady = false;
std::unique_lock<std::mutex> lock(gMutex);
FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "BEGIN: DALI_TEXT_PRECACHE_THREAD_SYNC_CREATION\n");
- gPreCacheThread = std::thread(PreCacheRun, fallbackFamilyList, extraFamilyList, localeFamily, syncCreation);
+ gPreCacheThread.mThread = std::thread(PreCacheRun, fallbackFamilyList, extraFamilyList, localeFamily, syncCreation);
gPreCacheCond.wait_for(lock, timeout, []{return gPreCacheThreadReady;});
FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "END: DALI_TEXT_PRECACHE_THREAD_SYNC_CREATION\n");
}
else
{
gPreCacheCond.wait_for(lock, timeout, []{return gPreCacheThreadReady;});
FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "END: DALI_TEXT_PRECACHE_THREAD_SYNC_CREATION\n");
}
else
{
- gPreCacheThread = std::thread(PreCacheRun, fallbackFamilyList, extraFamilyList, localeFamily, syncCreation);
+ gPreCacheThread.mThread = std::thread(PreCacheRun, fallbackFamilyList, extraFamilyList, localeFamily, syncCreation);
- if(gPreLoadThread.joinable())
+ if(gPreLoadThread.mThread.joinable())
{
FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient font pre-load thread already running.\n");
return;
{
FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient font pre-load thread already running.\n");
return;
gPreLoadThreadReady = false;
std::unique_lock<std::mutex> lock(gMutex);
FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "BEGIN: DALI_TEXT_FONT_PRELOAD_THREAD_SYNC_CREATION\n");
gPreLoadThreadReady = false;
std::unique_lock<std::mutex> lock(gMutex);
FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "BEGIN: DALI_TEXT_FONT_PRELOAD_THREAD_SYNC_CREATION\n");
- gPreLoadThread = std::thread(PreLoadRun, fontPathList, memoryFontPathList, syncCreation);
+ gPreLoadThread.mThread = std::thread(PreLoadRun, fontPathList, memoryFontPathList, syncCreation);
gPreLoadCond.wait_for(lock, timeout, []{return gPreLoadThreadReady;});
FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "END: DALI_TEXT_FONT_PRELOAD_THREAD_SYNC_CREATION\n");
}
else
{
gPreLoadCond.wait_for(lock, timeout, []{return gPreLoadThreadReady;});
FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "END: DALI_TEXT_FONT_PRELOAD_THREAD_SYNC_CREATION\n");
}
else
{
- gPreLoadThread = std::thread(PreLoadRun, fontPathList, memoryFontPathList, syncCreation);
+ gPreLoadThread.mThread = std::thread(PreLoadRun, fontPathList, memoryFontPathList, syncCreation);
+void FontClient::JoinFontThreads()
+{
+ if(gPreCacheThread.mThread.joinable())
+ {
+ gPreCacheThread.mThread.join();
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreCache thread join\n");
+ }
+
+ if(gPreLoadThread.mThread.joinable())
+ {
+ gPreLoadThread.mThread.join();
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreLoad thread join\n");
+ }
+}
+
void FontClient::ClearCache()
{
if(mPlugin)
void FontClient::ClearCache()
{
if(mPlugin)
static void PreLoadRun(const FontPathList& fontPathList, const FontPathList& memoryFontPathList, bool syncCreation);
/**
static void PreLoadRun(const FontPathList& fontPathList, const FontPathList& memoryFontPathList, bool syncCreation);
/**
+ * @brief Joins font threads, waiting for their execution to complete.
+ */
+ static void JoinFontThreads();
+
+ /**
* @copydoc Dali::TextAbstraction::FontClient::ClearCache()
*/
void ClearCache();
* @copydoc Dali::TextAbstraction::FontClient::ClearCache()
*/
void ClearCache();
{
if(Dali::FileLoader::ReadFile(fontPath, dataSize, fontDataBuffer, Dali::FileLoader::BINARY))
{
{
if(Dali::FileLoader::ReadFile(fontPath, dataSize, fontDataBuffer, Dali::FileLoader::BINARY))
{
- FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "PreLoad font file buffer : %lu, size : %ld, path : %s\n", fontDataBuffer.Size(), static_cast<long>(dataSize), fontPath.c_str());
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "PreLoad font file buffer : %zu, size : %ld, path : %s\n", fontDataBuffer.Size(), static_cast<long>(dataSize), fontPath.c_str());