common taskscheduler: revise functionalities. 48/241448/10
authorHermet Park <chuneon.park@samsung.com>
Thu, 20 Aug 2020 08:04:32 +0000 (17:04 +0900)
committerHermet Park <chuneon.park@samsung.com>
Fri, 21 Aug 2020 03:26:57 +0000 (12:26 +0900)
initialization interfaces has been changed for threads count.

if you want to set concrete threads count by system, please specify thread count with it.

std threads:
tvg::Initializer::init(tvg::CanvasEngine::Sw, std::thread::hardware_concurrency());

if your system provides designed threads info, you can use it.

efl:
tvg_engine_init(TVG_ENGINE_SW, eina_cpu_count());

I recommend to avoid max threads usage for better performance.

Change-Id: I22cfa315768f73fa941be136956cdbb2cf837c20

34 files changed:
inc/thorvg.h
inc/thorvg_capi.h
src/bindings/capi/tvgCapi.cpp
src/lib/meson.build
src/lib/tvgCommon.h
src/lib/tvgInitializer.cpp
src/lib/tvgShapePath.h
src/lib/tvgTask.cpp [deleted file]
src/lib/tvgTask.h [deleted file]
src/lib/tvgTaskScheduler.cpp [new file with mode: 0644]
src/lib/tvgTaskScheduler.h [new file with mode: 0644]
test/testArc.cpp
test/testAsync.cpp
test/testBlending.cpp
test/testBoundary.cpp
test/testCapi.c
test/testCommon.h
test/testCustomTransform.cpp
test/testDirectUpdate.cpp
test/testGradientTransform.cpp
test/testLinearGradient.cpp
test/testMultiShapes.cpp
test/testPath.cpp
test/testPathCopy.cpp
test/testRadialGradient.cpp
test/testScene.cpp
test/testSceneTransform.cpp
test/testShape.cpp
test/testStroke.cpp
test/testStrokeLine.cpp
test/testSvg.cpp
test/testSvg2.cpp
test/testTransform.cpp
test/testUpdate.cpp

index 18013fa..0de9bc0 100644 (file)
@@ -366,10 +366,8 @@ public:
      *
      * @see ...
      */
-    static Result init(CanvasEngine engine) noexcept;
+    static Result init(CanvasEngine engine, uint32_t threads) noexcept;
     static Result term(CanvasEngine engine) noexcept;
-    static Result threads(uint32_t cnt) noexcept;
-    static uint32_t threads() noexcept;
 
     _TVG_DISABLE_CTOR(Initializer);
 };
index 811c82e..afc294a 100644 (file)
@@ -88,7 +88,7 @@ typedef struct
 /************************************************************************/
 /* Engine API                                                           */
 /************************************************************************/
-TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method);
+TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method, unsigned threads);
 TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method);
 
 
index ac8cdcb..0155196 100644 (file)
@@ -50,13 +50,13 @@ struct _Tvg_Gradient
 /* Engine API                                                           */
 /************************************************************************/
 
-TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) {
+TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method, unsigned threads) {
     Result ret = Result::Success;
 
-    if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw);
+    if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw, threads);
     if (ret != Result::Success) return (Tvg_Result) ret;
 
-    if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl);
+    if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl, threads);
     return (Tvg_Result) ret;
 }
 
@@ -64,10 +64,10 @@ TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) {
 TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method) {
     Result ret = Result::Success;
 
-    if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw);
+    if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::term(tvg::CanvasEngine::Sw);
     if (ret != Result::Success) return (Tvg_Result) ret;
 
-    if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl);
+    if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::term(tvg::CanvasEngine::Gl);
     return (Tvg_Result) ret;
 }
 
index 503c35e..bc0d959 100644 (file)
@@ -21,6 +21,7 @@ source_file = [
    'tvgSceneImpl.h',
    'tvgShapePath.h',
    'tvgShapeImpl.h',
+   'tvgTaskScheduler.h',
    'tvgBezier.cpp',
    'tvgCanvas.cpp',
    'tvgFill.cpp',
@@ -35,7 +36,7 @@ source_file = [
    'tvgScene.cpp',
    'tvgShape.cpp',
    'tvgSwCanvas.cpp',
-   'tvgTask.cpp',
+   'tvgTaskScheduler.cpp',
 ]
 
 common_dep = declare_dependency(
index 66e08bf..c07a4ca 100644 (file)
@@ -29,6 +29,9 @@
 #include <math.h>
 #include <float.h>
 #include <string.h>
+#include <memory>
+#include <future>
+
 #include "thorvg.h"
 
 using namespace std;
@@ -46,5 +49,6 @@ using namespace tvg;
 #include "tvgLoaderMgr.h"
 #include "tvgRender.h"
 #include "tvgPaint.h"
+#include "tvgTaskScheduler.h"
 
 #endif //_TVG_COMMON_H_
index 2185c0f..17b91a0 100644 (file)
 /* Internal Class Implementation                                        */
 /************************************************************************/
 
-static uint32_t threadCnt = 0;
 
 /************************************************************************/
 /* External Class Implementation                                        */
 /************************************************************************/
 
-Result Initializer::init(CanvasEngine engine) noexcept
+Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept
 {
     auto nonSupport = true;
 
@@ -63,6 +62,8 @@ Result Initializer::init(CanvasEngine engine) noexcept
 
     if (!LoaderMgr::init()) return Result::Unknown;
 
+    TaskScheduler::init(threads);
+
     return Result::Success;
 }
 
@@ -87,21 +88,9 @@ Result Initializer::term(CanvasEngine engine) noexcept
 
     if (nonSupport) return Result::NonSupport;
 
-    if (!LoaderMgr::term()) return Result::Unknown;
-
-    return Result::Success;
-}
-
+    TaskScheduler::term();
 
-Result Initializer::threads(uint32_t cnt) noexcept
-{
-    threadCnt = cnt;
+    if (!LoaderMgr::term()) return Result::Unknown;
 
     return Result::Success;
-}
-
-
-uint32_t Initializer::threads() noexcept
-{
-    return threadCnt;
 }
\ No newline at end of file
index 04934dc..f3e0ae5 100644 (file)
@@ -19,8 +19,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#ifndef _TVG_SHAPE_PATH_CPP_
-#define _TVG_SHAPE_PATH_CPP_
+#ifndef _TVG_SHAPE_PATH_H_
+#define _TVG_SHAPE_PATH_H_
 
 #include "tvgCommon.h"
 
@@ -139,4 +139,4 @@ struct ShapePath
     }
 };
 
-#endif //_TVG_SHAPE_PATH_CPP_
+#endif //_TVG_SHAPE_PATH_H_
diff --git a/src/lib/tvgTask.cpp b/src/lib/tvgTask.cpp
deleted file mode 100644 (file)
index 81ce22e..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *               http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- */
-
-#include <tvgTask.h>
-
-#include <deque>
-
-template <typename Task>
-class TaskQueue {
-    using lock_t = std::unique_lock<std::mutex>;
-    std::deque<Task>        _q;
-    bool                    _done{false};
-    std::mutex              _mutex;
-    std::condition_variable _ready;
-
-public:
-    bool try_pop(Task &task)
-    {
-        lock_t lock{_mutex, std::try_to_lock};
-        if (!lock || _q.empty()) return false;
-        task = std::move(_q.front());
-        _q.pop_front();
-        return true;
-    }
-
-    bool try_push(Task &&task)
-    {
-        {
-            lock_t lock{_mutex, std::try_to_lock};
-            if (!lock) return false;
-            _q.push_back(std::move(task));
-        }
-        _ready.notify_one();
-        return true;
-    }
-
-    void done()
-    {
-        {
-            lock_t lock{_mutex};
-            _done = true;
-        }
-        _ready.notify_all();
-    }
-
-    bool pop(Task &task)
-    {
-        lock_t lock{_mutex};
-        while (_q.empty() && !_done) _ready.wait(lock);
-        if (_q.empty()) return false;
-        task = std::move(_q.front());
-        _q.pop_front();
-        return true;
-    }
-
-    void push(Task &&task)
-    {
-        {
-            lock_t lock{_mutex};
-            _q.push_back(std::move(task));
-        }
-        _ready.notify_one();
-    }
-
-};
-
-#include <thread>
-#include <vector>
-
-namespace tvg
-{
-
-class Executor
-{
-    const unsigned                      _count{std::thread::hardware_concurrency()};
-    std::vector<std::thread>            _threads;
-    std::vector<TaskQueue<shared_task>> _q{_count};
-    std::atomic<unsigned>               _index{0};
-    void run(unsigned i)
-    {
-        // Task Loop
-        shared_task task;
-        while (true) {
-            bool success = false;
-
-            for (unsigned n = 0; n != _count * 2; ++n) {
-                if (_q[(i + n) % _count].try_pop(task)) {
-                    success = true;
-                    break;
-                }
-            }
-
-            if (!success && !_q[i].pop(task)) break;
-
-            (*task)();
-        }
-    }
-
-    Executor()
-    {
-        for (unsigned n = 0; n != _count; ++n) {
-            _threads.emplace_back([&, n] { run(n); });
-        }
-    }
-    ~Executor()
-    {
-        for (auto &e : _q) e.done();
-
-        for (auto &e : _threads) e.join();
-    }
-
-public:
-
-    static Executor& instance() {
-        static Executor singleton;
-        return singleton;
-    }
-
-    void post(shared_task task)
-    {
-        task->prepare();
-
-        auto i = _index++;
-
-        for (unsigned n = 0; n != _count; ++n) {
-            if (_q[(i + n) % _count].try_push(std::move(task))) return;
-        }
-
-        if (_count > 0) {
-            _q[i % _count].push(std::move(task));
-        }
-    }
-};
-
-void async(shared_task task)
-{
-    Executor::instance().post(std::move(task));
-}
-
-}
-
-
diff --git a/src/lib/tvgTask.h b/src/lib/tvgTask.h
deleted file mode 100644 (file)
index 9fb250e..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *               http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- */
-#ifndef _TVG_TASK_H_
-#define _TVG_TASK_H_
-
-#include <memory>
-#include <future>
-
-namespace tvg
-{
-
-/*
-  Task Interface.
-  Able to run a task in the thread pool. derive from the
-  task interface and implement run method.
-
-  To get the result call task->get() which will return immidiately if the
-  task is already finishd otherwise will wait till task completion.
- */
-
-class Task
-{
-public:
-    virtual ~Task() = default;
-    void get() { if (_receiver.valid()) _receiver.get(); }
-
-protected:
-    virtual void run() = 0;
-private:
-    void operator()()
-    {
-        run();
-        _sender.set_value();
-    }
-    void prepare()
-    {
-        _sender = std::promise<void>();
-        _receiver = _sender.get_future();
-    }
-    friend class Executor;
-
-    std::promise<void> _sender;
-    std::future<void>  _receiver;
-};
-
-
-using shared_task = std::shared_ptr<Task>;
-
-/*
-  async() function takes a shared task and runs it in
-  a thread pool asyncronously. call get() on the shared_task
-  to get the ressult out of the shared_task.
- */
-void async(shared_task task);
-
-}
-
-#endif //_TVG_TASK_H_
\ No newline at end of file
diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp
new file mode 100644 (file)
index 0000000..31b1e84
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <deque>
+#include <thread>
+#include "tvgCommon.h"
+
+/************************************************************************/
+/* Internal Class Implementation                                        */
+/************************************************************************/
+
+namespace tvg {
+
+struct TaskQueue {
+    deque<shared_ptr<Task>>  taskDeque;
+    mutex                    mtx;
+    condition_variable       ready;
+    bool                     done = false;
+
+    bool tryPop(shared_ptr<Task> &task)
+    {
+        unique_lock<mutex> lock{mtx, try_to_lock};
+        if (!lock || taskDeque.empty()) return false;
+        task = move(taskDeque.front());
+        taskDeque.pop_front();
+
+        return true;
+    }
+
+    bool tryPush(shared_ptr<Task> &&task)
+    {
+        {
+            unique_lock<mutex> lock{mtx, try_to_lock};
+            if (!lock) return false;
+            taskDeque.push_back(move(task));
+        }
+
+        ready.notify_one();
+
+        return true;
+    }
+
+    void complete()
+    {
+        {
+            unique_lock<mutex> lock{mtx};
+            done = true;
+        }
+        ready.notify_all();
+    }
+
+    bool pop(shared_ptr<Task> &task)
+    {
+        unique_lock<mutex> lock{mtx};
+
+        while (taskDeque.empty() && !done) {
+            ready.wait(lock);
+        }
+
+        if (taskDeque.empty()) return false;
+
+        task = move(taskDeque.front());
+        taskDeque.pop_front();
+
+        return true;
+    }
+
+    void push(shared_ptr<Task> &&task)
+    {
+        {
+            unique_lock<mutex> lock{mtx};
+            taskDeque.push_back(move(task));
+        }
+
+        ready.notify_one();
+    }
+
+};
+
+
+class TaskSchedulerImpl
+{
+public:
+    unsigned                       threadCnt;
+    vector<thread>                 threads;
+    vector<TaskQueue>              taskQueues{threadCnt};
+    atomic<unsigned>               idx{0};
+
+    TaskSchedulerImpl()
+    {
+        for (unsigned i = 0; i < threadCnt; ++i) {
+            threads.emplace_back([&, i] { run(i); });
+        }
+    }
+
+    ~TaskSchedulerImpl()
+    {
+        for (auto& queue : taskQueues) queue.complete();
+        for (auto& thread : threads) thread.join();
+    }
+
+    void run(unsigned i)
+    {
+        shared_ptr<Task> task;
+
+        //Thread Loop
+        while (true) {
+            auto success = false;
+
+            for (unsigned i = 0; i < threadCnt * 2; ++i) {
+                if (taskQueues[(i + i) % threadCnt].tryPop(task)) {
+                    success = true;
+                    break;
+                }
+            }
+
+            if (!success && !taskQueues[i].pop(task)) break;
+
+            (*task)();
+        }
+    }
+
+    void request(shared_ptr<Task> task)
+    {
+        //Async
+        if (threadCnt > 0) {
+            task->prepare();
+            auto i = idx++;
+            for (unsigned n = 0; n < threadCnt; ++n) {
+                if (taskQueues[(i + n) % threadCnt].tryPush(move(task))) return;
+            }
+
+            taskQueues[i % threadCnt].push(move(task));
+
+        //Sync
+        } else {
+            task->run();
+        }
+    }
+};
+
+}
+
+static TaskSchedulerImpl* inst = nullptr;
+
+/************************************************************************/
+/* External Class Implementation                                        */
+/************************************************************************/
+
+void TaskScheduler::init(unsigned threads)
+{
+    if (inst) return;
+    inst = new TaskSchedulerImpl;
+    inst->threadCnt = threads;
+}
+
+
+void TaskScheduler::term()
+{
+    if (!inst) return;
+    delete(inst);
+    inst = nullptr;
+}
+
+
+void TaskScheduler::request(shared_ptr<Task> task)
+{
+    if (inst) {
+        inst->request(move(task));
+    }
+}
\ No newline at end of file
diff --git a/src/lib/tvgTaskScheduler.h b/src/lib/tvgTaskScheduler.h
new file mode 100644 (file)
index 0000000..4380a9c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef _TVG_TASK_SCHEDULER_H_
+#define _TVG_TASK_SCHEDULER_H_
+
+#include "tvgCommon.h"
+
+namespace tvg
+{
+
+struct Task
+{
+private:
+    std::promise<void> sender;
+    std::future<void>  receiver;
+
+public:
+    virtual ~Task() = default;
+
+    void get()
+    {
+        if (receiver.valid()) receiver.get();
+    }
+
+protected:
+    virtual void run() = 0;
+
+private:
+    void operator()()
+    {
+        run();
+        sender.set_value();
+    }
+
+    void prepare()
+    {
+        sender = std::promise<void>();
+        receiver = sender.get_future();
+    }
+
+    friend class TaskSchedulerImpl;
+};
+
+struct TaskScheduler
+{
+    static void init(unsigned threads);
+    static void term();
+    static void request(shared_ptr<Task> task);
+};
+
+}
+
+#endif //_TVG_TASK_SCHEDULER_H_
\ No newline at end of file
index 1f15812..9c307d4 100644 (file)
@@ -148,8 +148,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 608cefb..25e57ba 100644 (file)
@@ -151,8 +151,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 743b1e0..68623dc 100644 (file)
@@ -131,8 +131,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 3830687..e2ed1c0 100644 (file)
@@ -120,8 +120,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index c6df396..1b0018d 100644 (file)
@@ -13,7 +13,7 @@ static uint32_t buffer[WIDTH * HEIGHT];
 \r
 void testCapi()\r
 {\r
-    tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL);\r
+    tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL, 0);\r
 \r
     Tvg_Canvas* canvas = tvg_swcanvas_create();\r
     tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888);\r
index 13ac86a..a5f222e 100644 (file)
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <thread>
 #include <Elementary.h>
 #include <thorvg.h>
 
index 9daa6fc..50033f9 100644 (file)
@@ -176,8 +176,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 8dcc474..69105c3 100644 (file)
@@ -139,8 +139,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 77d5f6a..45431e3 100644 (file)
@@ -204,31 +204,34 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
-    elm_init(argc, argv);
+        elm_init(argc, argv);
 
-    Elm_Transit *transit = elm_transit_add();
+        Elm_Transit *transit = elm_transit_add();
 
-    if (tvgEngine == tvg::CanvasEngine::Sw) {
-        auto view = createSwView();
-        elm_transit_effect_add(transit, transitSwCb, view, nullptr);
-    } else {
-        auto view = createGlView();
-        elm_transit_effect_add(transit, transitGlCb, view, nullptr);
-    }
+        if (tvgEngine == tvg::CanvasEngine::Sw) {
+            auto view = createSwView();
+            elm_transit_effect_add(transit, transitSwCb, view, nullptr);
+        } else {
+            auto view = createGlView();
+            elm_transit_effect_add(transit, transitGlCb, view, nullptr);
+        }
 
-    elm_transit_duration_set(transit, 2);
-    elm_transit_repeat_times_set(transit, -1);
-    elm_transit_auto_reverse_set(transit, EINA_TRUE);
-    elm_transit_go(transit);
+        elm_transit_duration_set(transit, 2);
+        elm_transit_repeat_times_set(transit, -1);
+        elm_transit_auto_reverse_set(transit, EINA_TRUE);
+        elm_transit_go(transit);
 
-    elm_run();
-    elm_shutdown();
+        elm_run();
+        elm_shutdown();
 
-    //Terminate ThorVG Engine
-    tvg::Initializer::term(tvgEngine);
+        //Terminate ThorVG Engine
+        tvg::Initializer::term(tvgEngine);
 
     } else {
         cout << "engine is not supported" << endl;
index db11682..d1ed5fa 100644 (file)
@@ -149,8 +149,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 12009bc..3db41b9 100644 (file)
@@ -109,8 +109,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index de6ef60..a265d03 100644 (file)
@@ -126,8 +126,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index fb1080b..b5d97cf 100644 (file)
@@ -163,8 +163,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 6e77291..a64e47b 100644 (file)
@@ -149,8 +149,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index daa5d86..8c46428 100644 (file)
@@ -156,8 +156,12 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
+
 
         elm_init(argc, argv);
 
index e64fa9a..ef6c157 100644 (file)
@@ -200,8 +200,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index af4d0c4..56acfd5 100644 (file)
@@ -99,8 +99,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 778d7c7..5ac2265 100644 (file)
@@ -146,8 +146,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 1205bb1..8cc16d0 100644 (file)
@@ -183,8 +183,12 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
+
 
         elm_init(argc, argv);
 
index 06fe350..ad72027 100644 (file)
@@ -141,8 +141,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 2300f21..c859b04 100644 (file)
@@ -124,8 +124,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 5ef33f4..6cd9be6 100644 (file)
@@ -167,8 +167,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);
 
index 3ff6c24..6df8533 100644 (file)
@@ -128,8 +128,11 @@ int main(int argc, char **argv)
         cout << "tvg engine: opengl" << endl;
     }
 
+    //Threads Count
+    auto threads = std::thread::hardware_concurrency();
+
     //Initialize ThorVG Engine
-    if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
+    if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
 
         elm_init(argc, argv);