From d1a81710119ee3c3da661b4a13e4abe64d3d05ed Mon Sep 17 00:00:00 2001
From: Maxim Kostin <maxim.kostin@akvelon.com>
Date: Wed, 18 Mar 2015 15:13:08 +0300
Subject: [PATCH] Added WinRT concurrency support.

---
 modules/core/src/parallel.cpp | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/modules/core/src/parallel.cpp b/modules/core/src/parallel.cpp
index 4dde2adeae..582c7cd039 100644
--- a/modules/core/src/parallel.cpp
+++ b/modules/core/src/parallel.cpp
@@ -69,7 +69,7 @@
     #define HAVE_GCD
 #endif
 
-#if defined _MSC_VER && _MSC_VER >= 1600 && !defined(WINRT)
+#if defined _MSC_VER && _MSC_VER >= 1600
     #define HAVE_CONCURRENCY
 #endif
 
@@ -78,7 +78,8 @@
    2. HAVE_CSTRIPES    - 3rdparty library, should be explicitly enabled
    3. HAVE_OPENMP      - integrated to compiler, should be explicitly enabled
    4. HAVE_GCD         - system wide, used automatically        (APPLE only)
-   5. HAVE_CONCURRENCY - part of runtime, used automatically    (Windows only - MSVS 10, MSVS 11)
+   5. WINRT            - system wide, used automatically        (Windows RT only)
+   6. HAVE_CONCURRENCY - part of runtime, used automatically    (Windows only - MSVS 10, MSVS 11)
 */
 
 #if defined HAVE_TBB
@@ -105,6 +106,8 @@
     #elif defined HAVE_GCD
         #include <dispatch/dispatch.h>
         #include <pthread.h>
+    #elif defined WINRT
+        #include <ppltasks.h>
     #elif defined HAVE_CONCURRENCY
         #include <ppl.h>
     #endif
@@ -118,6 +121,8 @@
 #  define CV_PARALLEL_FRAMEWORK "openmp"
 #elif defined HAVE_GCD
 #  define CV_PARALLEL_FRAMEWORK "gcd"
+#elif defined WINRT
+#  define CV_PARALLEL_FRAMEWORK "winrt-concurrency"
 #elif defined HAVE_CONCURRENCY
 #  define CV_PARALLEL_FRAMEWORK "ms-concurrency"
 #endif
@@ -179,7 +184,7 @@ namespace
         ProxyLoopBody* ptr_body = static_cast<ProxyLoopBody*>(context);
         (*ptr_body)(cv::Range((int)index, (int)index + 1));
     }
-#elif defined HAVE_CONCURRENCY
+#elif defined WINRT || defined HAVE_CONCURRENCY
     class ProxyLoopBody : public ParallelLoopBodyWrapper
     {
     public:
@@ -206,7 +211,10 @@ static tbb::task_scheduler_init tbbScheduler(tbb::task_scheduler_init::deferred)
 static int numThreadsMax = omp_get_max_threads();
 #elif defined HAVE_GCD
 // nothing for GCD
+#elif defined WINRT
+// nothing for WINRT
 #elif defined HAVE_CONCURRENCY
+
 class SchedPtr
 {
     Concurrency::Scheduler* sched_;
@@ -224,6 +232,7 @@ public:
     ~SchedPtr() { *this = 0; }
 };
 static SchedPtr pplScheduler;
+
 #endif
 
 #endif // CV_PARALLEL_FRAMEWORK
@@ -272,6 +281,10 @@ void cv::parallel_for_(const cv::Range& range, const cv::ParallelLoopBody& body,
         dispatch_queue_t concurrent_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
         dispatch_apply_f(stripeRange.end - stripeRange.start, concurrent_queue, &pbody, block_function);
 
+#elif defined WINRT
+
+        Concurrency::parallel_for(stripeRange.start, stripeRange.end, pbody);
+
 #elif defined HAVE_CONCURRENCY
 
         if(!pplScheduler || pplScheduler->Id() == Concurrency::CurrentScheduler::Id())
@@ -330,11 +343,15 @@ int cv::getNumThreads(void)
 
     return 512; // the GCD thread pool limit
 
+#elif defined WINRT
+
+    return 0;
+
 #elif defined HAVE_CONCURRENCY
 
     return 1 + (pplScheduler == 0
-                ? Concurrency::CurrentScheduler::Get()->GetNumberOfVirtualProcessors()
-                : pplScheduler->GetNumberOfVirtualProcessors());
+        ? Concurrency::CurrentScheduler::Get()->GetNumberOfVirtualProcessors()
+        : pplScheduler->GetNumberOfVirtualProcessors());
 
 #else
 
@@ -371,6 +388,10 @@ void cv::setNumThreads( int threads )
     // unsupported
     // there is only private dispatch_queue_set_width() and only for desktop
 
+#elif defined WINRT
+
+    return;
+
 #elif defined HAVE_CONCURRENCY
 
     if (threads <= 0)
@@ -407,6 +428,8 @@ int cv::getThreadNum(void)
     return omp_get_thread_num();
 #elif defined HAVE_GCD
     return (int)(size_t)(void*)pthread_self(); // no zero-based indexing
+#elif defined WINRT
+    return 0;
 #elif defined HAVE_CONCURRENCY
     return std::max(0, (int)Concurrency::Context::VirtualProcessorId()); // zero for master thread, unique number for others but not necessary 1,2,3,...
 #else