From 230224bf82ad8f65051476f7331f181f85f8f1c2 Mon Sep 17 00:00:00 2001 From: Constantin Shalnev Date: Wed, 5 Aug 2015 14:30:30 +0300 Subject: [PATCH] Implemented SimpleThread which is the same as std::thread but executes callable object in a JVM environment --- base/base_tests/threads_test.cpp | 57 ++++++++++++++++++++++++++++++++ base/thread.cpp | 19 +++++++++++ base/thread.hpp | 41 +++++++++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/base/base_tests/threads_test.cpp b/base/base_tests/threads_test.cpp index a72d42f9ff..6a70938b63 100644 --- a/base/base_tests/threads_test.cpp +++ b/base/base_tests/threads_test.cpp @@ -58,3 +58,60 @@ UNIT_TEST(Simple_Threads) TEST_EQUAL(vec.size(), MAX_COUNT, ("vector size")); TEST_EQUAL(summ, checkSumm, ("check summ")); } + +class SomeClass +{ +public: + void Increment(int * a, int b) + { + *a = *a + b; + } +}; + +static void Increment(int * a, int b) +{ + *a = *a + b; +} + +UNIT_TEST(SimpleThreadTest1) +{ + int a = 0; + + auto fn = [&a](){ a = 1; }; + + threads::SimpleThread t(fn); + t.join(); + + TEST_EQUAL(a, 1, ("test a")); +} + +UNIT_TEST(SimpleThreadTest2) +{ + int a = 0; + + threads::SimpleThread t([&a](){ a = 1; }); + t.join(); + + TEST_EQUAL(a, 1, ("test a")); +} + +UNIT_TEST(SimpleThreadTest3) +{ + int a = 0; + + SomeClass instance; + threads::SimpleThread t(&SomeClass::Increment, &instance, &a, 1); + t.join(); + + TEST_EQUAL(a, 1, ("test a")); +} + +UNIT_TEST(SimpleThreadTest4) +{ + int a = 0; + + threads::SimpleThread t(&Increment, &a, 1); + t.join(); + + TEST_EQUAL(a, 1, ("test a")); +} diff --git a/base/thread.cpp b/base/thread.cpp index 16880cdb1a..7ca97a895f 100644 --- a/base/thread.cpp +++ b/base/thread.cpp @@ -79,6 +79,9 @@ void Thread::Join() IRoutine * Thread::GetRoutine() { return m_routine.get(); } +///////////////////////////////////////////////////////////////////// +// SimpleThreadPool implementation + SimpleThreadPool::SimpleThreadPool(size_t reserve) { m_pool.reserve(reserve); } void SimpleThreadPool::Add(unique_ptr && routine) @@ -98,4 +101,20 @@ IRoutine * SimpleThreadPool::GetRoutine(size_t i) const { return m_pool[i]->GetR void Sleep(size_t ms) { this_thread::sleep_for(milliseconds(ms)); } ThreadID GetCurrentThreadID() { return this_thread::get_id(); } + +///////////////////////////////////////////////////////////////////// +// SimpleThread implementation + +void SimpleThread::ThreadFunc(function fn) +{ +#if defined(OMIM_OS_ANDROID) + AndroidThreadAttachToJVM(); +#endif // defined(OMIM_OS_ANDROID) + + fn(); + +#if defined(OMIM_OS_ANDROID) + AndroidThreadDetachFromJVM(); +#endif // defined(OMIM_OS_ANDROID) +} } diff --git a/base/thread.hpp b/base/thread.hpp index 654dea5d81..2ec7b8b835 100644 --- a/base/thread.hpp +++ b/base/thread.hpp @@ -4,7 +4,9 @@ #include "base/cancellable.hpp" #include "base/macros.hpp" +#include "std/bind.hpp" #include "std/cstdint.hpp" +#include "std/function.hpp" #include "std/noncopyable.hpp" #include "std/shared_ptr.hpp" #include "std/target_os.hpp" @@ -94,4 +96,43 @@ typedef thread::id ThreadID; ThreadID GetCurrentThreadID(); +/// A wrapper around a std thread which executes callable object in android envorinment +/// Class has the same interface as std::thread +class SimpleThread +{ +public: + using id = thread::id; + using native_handle_type = thread::native_handle_type; + + SimpleThread() noexcept {} + SimpleThread(SimpleThread && x) noexcept + : m_thread(move(x.m_thread)) + {} + + template + explicit SimpleThread(Fn && fn, Args &&... args) + : m_thread(&SimpleThread::ThreadFunc, bind(forward(fn), forward(args)...)) + {} + + SimpleThread & operator= (SimpleThread && x) noexcept + { + m_thread = move(x.m_thread); + return *this; + } + + SimpleThread(const SimpleThread &) = delete; + SimpleThread & operator= (const SimpleThread &) = delete; + + void detach() { m_thread.detach(); } + id get_id() const noexcept { return m_thread.get_id(); } + void join() { m_thread.join(); } + bool joinable() const noexcept { return m_thread.joinable(); } + native_handle_type native_handle() { return m_thread.native_handle(); } + void swap(SimpleThread & x) noexcept { m_thread.swap(x.m_thread); } + +private: + static void ThreadFunc(function fn); + + thread m_thread; +}; } // namespace threads