This is a combination of 4 commits.
Fix deadlock issue of AsyncTaskThread
mDestroyThread may be changed to true after while(!mDestroyThread)
because we don't lock the part.
Support to load an image from uint8_t* encoded buffer.
Fix coverity issue : Adaptor available check in async task manager
Add GetCallbackInvocationThread() for AsyncTaskMananager
When AsyncTaskManager use other thread, no need to wake up main thread.
Change-Id: I17cf6d123304e5bef991afdd692dd25222ceace7
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
return Dali::Devel::PixelBuffer();
}
+Devel::PixelBuffer LoadImageFromBuffer(uint8_t* buffer, size_t bufferSize, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection)
+{
+ if(buffer == nullptr)
+ {
+ DALI_LOG_ERROR("buffer is empty!\n");
+ return Dali::Devel::PixelBuffer();
+ }
+ Integration::BitmapResourceType resourceType(size, fittingMode, samplingMode, orientationCorrection);
+
+ Internal::Platform::FileReader fileReader(buffer, bufferSize);
+ FILE* const fp = fileReader.GetFile();
+ if(fp != NULL)
+ {
+ Dali::Devel::PixelBuffer bitmap;
+ // Make path as empty string. Path information just for file format hint.
+ bool success = TizenPlatform::ImageLoader::ConvertStreamToBitmap(resourceType, std::string(""), fp, bitmap);
+ if(success && bitmap)
+ {
+ return bitmap;
+ }
+ }
+ return Dali::Devel::PixelBuffer();
+}
+
ImageDimensions GetClosestImageSize(const std::string& filename,
ImageDimensions size,
FittingMode::Type fittingMode,
bool orientationCorrection = true);
/**
+ * @brief Load an image synchronously from encoded buffer.
+ *
+ * @note This method is thread safe, i.e. can be called from any thread.
+ *
+ * @param [in] buffer The encoded buffer of the image to load.
+ * The buffer is not owned by FileStream and must be valid for entire lifetime of FileStream
+ * @param [in] bufferSize Size of the encoded buffer.
+ * @param [in] size The width and height to fit the loaded image to, 0.0 means whole image
+ * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
+ * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
+ * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
+ * @return handle to the loaded PixelBuffer object or an empty handle in case loading failed.
+ */
+DALI_ADAPTOR_API Devel::PixelBuffer LoadImageFromBuffer(
+ uint8_t* buffer,
+ size_t bufferSize,
+ ImageDimensions size = ImageDimensions(0, 0),
+ FittingMode::Type fittingMode = FittingMode::DEFAULT,
+ SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR,
+ bool orientationCorrection = true);
+
+/**
* @brief Determine the size of an image that LoadImageFromFile will provide when
* given the same image loading parameters.
*
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "async-task-manager-impl.h"
// EXTERNAL INCLUDES
-#include <dali/devel-api/common/singleton-service.h>
#include <dali/devel-api/adaptor-framework/environment-variable.h>
#include <dali/devel-api/adaptor-framework/thread-settings.h>
+#include <dali/devel-api/common/singleton-service.h>
#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <dali/integration-api/debug.h>
if(!task)
{
ConditionalWait::ScopedLock lock(mConditionalWait);
- mIsThreadIdle = true;
- mConditionalWait.Wait(lock);
+ if(!mDestroyThread)
+ {
+ mIsThreadIdle = true;
+ mConditionalWait.Wait(lock);
+ }
}
else
{
Dali::AsyncTaskManager AsyncTaskManager::Get()
{
Dali::AsyncTaskManager manager;
- SingletonService singletonService(SingletonService::Get());
+ SingletonService singletonService(SingletonService::Get());
if(singletonService)
{
// Check whether the async task manager is already created
{
// If not, create the async task manager and register it as a singleton
Internal::Adaptor::AsyncTaskManager* internalAsyncTaskManager = new Internal::Adaptor::AsyncTaskManager();
- manager = Dali::AsyncTaskManager(internalAsyncTaskManager);
+ manager = Dali::AsyncTaskManager(internalAsyncTaskManager);
singletonService.Register(typeid(manager), manager);
}
}
AsyncTaskManager::~AsyncTaskManager()
{
- if(mProcessorRegistered)
+ if(mProcessorRegistered && Dali::Adaptor::IsAvailable())
{
Dali::Adaptor::Get().UnregisterProcessor(*this);
}
// If all threads are busy, then it's ok just to push the task because they will try to get the next job.
}
- if(!mProcessorRegistered)
+ if(!mProcessorRegistered && Dali::Adaptor::IsAvailable())
{
Dali::Adaptor::Get().RegisterProcessor(*this);
mProcessorRegistered = true;
void AsyncTaskManager::CompleteTask(AsyncTaskPtr task)
{
// Lock while adding task to the queue
- Mutex::ScopedLock lock(mMutex);
- for(auto iter = mRunningTasks.begin(), endIter = mRunningTasks.end(); iter != endIter; ++iter)
{
- if((*iter).first == task)
+ Mutex::ScopedLock lock(mMutex);
+ for(auto iter = mRunningTasks.begin(), endIter = mRunningTasks.end(); iter != endIter; ++iter)
{
- if(!(*iter).second)
+ if((*iter).first == task)
{
- mCompletedTasks.push_back(task);
- }
+ if(!(*iter).second)
+ {
+ if(task->GetCallbackInvocationThread() == AsyncTask::ThreadType::MAIN_THREAD)
+ {
+ mCompletedTasks.push_back(task);
+ }
+ }
- // Delete this task in running queue
- mRunningTasks.erase(iter);
- break;
+ // Delete this task in running queue
+ mRunningTasks.erase(iter);
+ break;
+ }
}
}
// wake up the main thread
- mTrigger->Trigger();
+ if(task->GetCallbackInvocationThread() == AsyncTask::ThreadType::MAIN_THREAD)
+ {
+ mTrigger->Trigger();
+ }
+ else
+ {
+ CallbackBase::Execute(*(task->GetCompletedCallback()), task);
+ }
}
void AsyncTaskManager::UnregisterProcessor()
{
- if(mProcessorRegistered)
+ if(mProcessorRegistered && Dali::Adaptor::IsAvailable())
{
Mutex::ScopedLock lock(mMutex);
if(mWaitingTasks.empty() && mCompletedTasks.empty() && mRunningTasks.empty())
{
while(AsyncTaskPtr task = PopNextCompletedTask())
{
- CallbackBase::Execute(*(task->GetCompletedCallback()),task);
+ CallbackBase::Execute(*(task->GetCompletedCallback()), task);
}
UnregisterProcessor();
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
namespace Dali
{
-
-AsyncTask::AsyncTask(CallbackBase* callback)
-: mCompletedCallback(std::unique_ptr<CallbackBase>(callback))
+AsyncTask::AsyncTask(CallbackBase* callback, ThreadType threadType)
+: mCompletedCallback(std::unique_ptr<CallbackBase>(callback)),
+ mThreadType(threadType)
{
}
return mCompletedCallback.get();
}
+AsyncTask::ThreadType AsyncTask::GetCallbackInvocationThread()
+{
+ return mThreadType;
+}
+
AsyncTaskManager::AsyncTaskManager() = default;
AsyncTaskManager::~AsyncTaskManager() = default;
#define DALI_ASYNC_TASK_MANAGER_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
class DALI_ADAPTOR_API AsyncTask : public RefObject
{
public:
+ // The Type of invocation thread
+ enum class ThreadType
+ {
+ MAIN_THREAD,
+ WORKER_THREAD
+ };
+
/**
* Constructor
* @SINCE_2_2.3
- * @param[in] callback The callback to up the main thread. The ownership of callback is taken by this class
+ * @param[in] callback The callback to invoke on task completion, either on the main thread on the worker thread. The ownership of callback is taken by this class.
+ * @param[in] threadType The thread type of invocation callback.
*/
- AsyncTask(CallbackBase* callback);
+ AsyncTask(CallbackBase* callback, ThreadType threadType = AsyncTask::ThreadType::MAIN_THREAD);
/**
* Get the complated callback
CallbackBase* GetCompletedCallback();
/**
+ * Get the thread of the invocation callback
+ * @SINCE_2_2.9
+ * @return the type of invocation callback.
+ */
+ ThreadType GetCallbackInvocationThread();
+
+ /**
* Destructor.
* @SINCE_2_2.3
*/
private:
std::unique_ptr<CallbackBase> mCompletedCallback;
+ ThreadType mThreadType;
// Undefined
AsyncTask(const AsyncTask& task) = delete;