167 lines
4.7 KiB
C++
167 lines
4.7 KiB
C++
#include "pch.h"
|
|
#include "Class1.h"
|
|
|
|
#include <ppltasks.h>
|
|
#include <concurrent_vector.h>
|
|
|
|
using namespace concurrency;
|
|
using namespace Platform::Collections;
|
|
using namespace Windows::Foundation::Collections;
|
|
using namespace Windows::Foundation;
|
|
using namespace Windows::UI::Core;
|
|
|
|
using namespace UwpTestWinRtComponentCpp;
|
|
using namespace Platform;
|
|
|
|
Class1::Class1()
|
|
{
|
|
|
|
}
|
|
|
|
//Public API
|
|
IVector<double>^ Class1::ComputeResult(double input)
|
|
{
|
|
// Implement your function in ISO C++ or
|
|
// call into your C++ lib or DLL here. This example uses AMP.
|
|
float numbers[] = { 1.0, 10.0, 60.0, 100.0, 600.0, 10000.0 };
|
|
array_view<float, 1> logs(6, numbers);
|
|
|
|
// See http://msdn.microsoft.com/en-us/library/hh305254.aspx
|
|
parallel_for_each(
|
|
logs.extent,
|
|
[=](index<1> idx) restrict(amp)
|
|
{
|
|
logs[idx] = concurrency::fast_math::log10(logs[idx]);
|
|
}
|
|
);
|
|
|
|
// Return a Windows Runtime-compatible type across the ABI
|
|
auto res = ref new Vector<double>();
|
|
int len = safe_cast<int>(logs.extent.size());
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
res->Append(logs[i]);
|
|
}
|
|
|
|
// res is implicitly cast to IVector<double>
|
|
return res;
|
|
}
|
|
|
|
// Determines whether the input value is prime.
|
|
bool Class1::is_prime(int n)
|
|
{
|
|
if (n < 2)
|
|
return false;
|
|
for (int i = 2; i < n; ++i)
|
|
{
|
|
if ((n % i) == 0)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// This method computes all primes, orders them, then returns the ordered results.
|
|
IAsyncOperationWithProgress<IVector<int>^, double>^ Class1::GetPrimesOrdered(int first, int last)
|
|
{
|
|
return create_async([this, first, last]
|
|
(progress_reporter<double> reporter) -> IVector<int>^ {
|
|
// Ensure that the input values are in range.
|
|
if (first < 0 || last < 0) {
|
|
throw ref new InvalidArgumentException();
|
|
}
|
|
// Perform the computation in parallel.
|
|
concurrent_vector<int> primes;
|
|
long operation = 0;
|
|
long range = last - first + 1;
|
|
double lastPercent = 0.0;
|
|
|
|
parallel_for(first, last + 1, [this, &primes, &operation,
|
|
range, &lastPercent, reporter](int n) {
|
|
|
|
// Increment and store the number of times the parallel
|
|
// loop has been called on all threads combined. There
|
|
// is a performance cost to maintaining a count, and
|
|
// passing the delegate back to the UI thread, but it's
|
|
// necessary if we want to display a determinate progress
|
|
// bar that goes from 0 to 100%. We can avoid the cost by
|
|
// setting the ProgressBar IsDeterminate property to false
|
|
// or by using a ProgressRing.
|
|
if (InterlockedIncrement(&operation) % 100 == 0)
|
|
{
|
|
reporter.report(100.0 * operation / range);
|
|
}
|
|
|
|
// If the value is prime, add it to the local vector.
|
|
if (is_prime(n)) {
|
|
primes.push_back(n);
|
|
}
|
|
});
|
|
|
|
// Sort the results.
|
|
std::sort(begin(primes), end(primes), std::less<int>());
|
|
reporter.report(100.0);
|
|
|
|
// Copy the results to a Vector object, which is
|
|
// implicitly converted to the IVector return type. IVector
|
|
// makes collections of data available to other
|
|
// Windows Runtime components.
|
|
return ref new Vector<int>(primes.begin(), primes.end());
|
|
});
|
|
}
|
|
|
|
// This method returns no value. Instead, it fires an event each time a
|
|
// prime is found, and passes the prime through the event.
|
|
// It also passes progress info.
|
|
IAsyncActionWithProgress<double>^ Class1::GetPrimesUnordered(int first, int last)
|
|
{
|
|
|
|
auto window = Windows::UI::Core::CoreWindow::GetForCurrentThread();
|
|
m_dispatcher = window->Dispatcher;
|
|
|
|
|
|
return create_async([this, first, last](progress_reporter<double> reporter) {
|
|
|
|
// Ensure that the input values are in range.
|
|
if (first < 0 || last < 0) {
|
|
throw ref new InvalidArgumentException();
|
|
}
|
|
|
|
// In this particular example, we don't actually use this to store
|
|
// results since we pass results one at a time directly back to
|
|
// UI as they are found. However, we have to provide this variable
|
|
// as a parameter to parallel_for.
|
|
concurrent_vector<int> primes;
|
|
long operation = 0;
|
|
long range = last - first + 1;
|
|
double lastPercent = 0.0;
|
|
|
|
// Perform the computation in parallel.
|
|
parallel_for(first, last + 1,
|
|
[this, &primes, &operation, range, &lastPercent, reporter](int n)
|
|
{
|
|
// Store the number of times the parallel loop has been called
|
|
// on all threads combined. See comment in previous method.
|
|
if (InterlockedIncrement(&operation) % 100 == 0)
|
|
{
|
|
reporter.report(100.0 * operation / range);
|
|
}
|
|
|
|
// If the value is prime, pass it immediately to the UI thread.
|
|
if (is_prime(n))
|
|
{
|
|
// Since this code is probably running on a worker
|
|
// thread, and we are passing the data back to the
|
|
// UI thread, we have to use a CoreDispatcher object.
|
|
m_dispatcher->RunAsync(CoreDispatcherPriority::Normal,
|
|
ref new DispatchedHandler([this, n, operation, range]()
|
|
{
|
|
this->primeFoundEvent(n);
|
|
|
|
}, Platform::CallbackContext::Any));
|
|
|
|
}
|
|
});
|
|
reporter.report(100.0);
|
|
});
|
|
}
|