I am trying to understand how I could implement a concurrent thread for processing data in a Winrt/Cpp application.
As background
I have implemented a winRT BLE component that wraps the windows bluetooth function
I am using this component in my winrt application and successfully get a notification when the app connects to me bluetooth device
Now within the app I would like to "spawn" a process that continually sends a request to the BLE device and process the response.
To achieve #3 I thought one approach could be - within the connection notification I would invoke a function called StartDataAcq that uses the threadpool to schedule work,
to test out this approach I decided to just use the example shown here
https://learn.microsoft.com/en-us/windows/uwp/threading-async/submit-a-work-item-to-the-thread-pool
to see if it could work
So the implementation looks like this within my code
void Datamanager::BleFound(
winrt::Windows::Foundation::IInspectable const& /* sender */,
uint32_t foundFlags)
{
OutputDebugStringW((L"Member function Called from DataManager->" + hstring(std::to_wstring(foundFlags)) + L"\r\n").c_str());
if (!acqStarted)
{
StartDataAcq();
acqStarted = true;
}
}
void DataManager::StartDataAcq()
{
// The nth prime number to find.
const unsigned int n{ 99999999 };
unsigned long nthPrime{ 0 };
//submit work to thread poool
m_workItem = Windows::System::Threading::ThreadPool::RunAsync([&](Windows::Foundation::IAsyncAction const& workItem)
{
unsigned int progress = 0; // For progress reporting.
unsigned int primes = 0; // Number of primes found so far.
unsigned long int i = 2; // Number iterator.
if ((n >= 0) && (n <= 2))
{
nthPrime = n;
return;
}
while (primes < (n - 1))
{
if (workItem.Status() == Windows::Foundation::AsyncStatus::Canceled)
{
break;
}
// Go to the next number.
i++;
// Check for prime.
bool prime = true;
for (unsigned int j = 2; j < i; ++j)
{
if ((i % j) == 0)
{
prime = false;
break;
}
};
if (prime)
{
// Found another prime number.
primes++;
// Report progress at every 10 percent.
unsigned int temp = progress;
progress = static_cast<unsigned int>(10.f * primes / n);
if (progress != temp)
{
std::wstringstream updateString;
updateString << L"Progress to " << n << L"th prime: " << (10 * progress) << std::endl;
OutputDebugStringW((L"" + updateString.str() + L"\r\n").c_str());
// Update the UI thread with the CoreDispatcher.
/*
Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync(
Windows::UI::Core::CoreDispatcherPriority::High,
Windows::UI::Core::DispatchedHandler([&]()
{
UpdateUI(updateString.str());
}));
*/
}
}
}
// Return the nth prime number.
nthPrime = i;
} , Windows::System::Threading::WorkItemPriority::Normal, Windows::System::Threading::WorkItemOptions::TimeSliced);
}
I see the message for the connect notification,
This debug string - OutputDebugStringW((L"Member function Called from DataManager->" + hstring(std::to_wstring(foundFlags)) + L"\r\n").c_str());
however I never see any output from the async workitem.
Can someone please help me spot the issue?
Also are there any better ways to do this? I was reading about co-routines but seeing how the work is data processing locally I do not think a co routine would work
I also was trying to find out how I could spawn a separate thread and manage it within my code - but am not sure how to do it within the winrt/c++ framework
based on Raymond Chen's comment I converted the variables on the stack to std::shared_ptr and the sample works now...
Also stumbled upon this link that explains this better than I can...
https://learn.microsoft.com/en-us/cpp/parallel/concrt/task-parallelism-concurrency-runtime?view=msvc-170#lambdas
void DataManager::StartDataAcq()
{
auto n = make_shared<UINT32>(9999);
auto nthPrime = make_shared<UINT32>(0);
m_workItem = Windows::System::Threading::ThreadPool::RunAsync([n,nthPrime](Windows::Foundation::IAsyncAction const& workItem)
{
unsigned int progress = 0; // For progress reporting.
unsigned int primes = 0; // Number of primes found so far.
int i = 2; // Number iterator.
if ((*n >= 0) && (*n <= 2))
{
*nthPrime = *n;
//return;
}
while (primes < (*n - 1))
{
if (workItem.Status() == Windows::Foundation::AsyncStatus::Canceled)
{
break;
}
// Go to the next number.
i++;
// Check for prime.
bool prime = true;
for (unsigned int j = 2; j < i; ++j)
{
if ((i % j) == 0)
{
prime = false;
break;
}
};
if (prime)
{
// Found another prime number.
primes++;
// Report progress at every 10 percent.
unsigned int temp = progress;
progress = static_cast<unsigned int>(10.f * primes / *n);
if (progress != temp)
{
std::wstringstream updateString;
updateString << L"Progress to " << *n << L" " << i << L" th prime: " << (10 * progress) << std::endl;
OutputDebugStringW((L"" + updateString.str() + L"\r\n").c_str());
// Update the UI thread with the CoreDispatcher.
/*
Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync(
Windows::UI::Core::CoreDispatcherPriority::High,
Windows::UI::Core::DispatchedHandler([&]()
{
UpdateUI(updateString.str());
}));
*/
}
}
}
// Return the nth prime number.
*nthPrime = i;
std::wstringstream updateString;
updateString << L"Found the nth prime " << i << std::endl;
OutputDebugStringW((L"" + updateString.str() ).c_str());
} , Windows::System::Threading::WorkItemPriority::Normal, Windows::System::Threading::WorkItemOptions::TimeSliced);
}
I'm trying to build a 2D sparse matrix class using std::map, which should be called in (for example) the following way:
SparseMatrix<double> M(2,2); // Create a new sparse matrix with 2 rows and 2 columns
M[{1,1}] = 3.1; // Sets element {1,1} to 3.1
The following class can perform these tasks:
template < typename T >
class SparseMatrix
{
std::map< array<int, 2>, T> data;
const array<int, 2> size;
public:
SparseMatrix(const int rows, const int cols)
: size({ rows, cols }) {}
// []-operator to set and get values from matrix
T& operator[](const array< int,2 > indices)
{
// Check if given indices are within the size of the matrix
if(indices[0] >= size[0] || indices[1] >= size[1])
throw invalid_argument("Indices out of bounds");
return data[indices];
}
};
Using this class it is possible to create a new object and set the element, however, the []-operator is also used to get elements, for example:
std::cout << M[{1,1}] << std::endl;
The problem with this is that if this is used to get an element that is not set already, it creates a new part in the map with the given indices and a value of 0, which is undesired for a sparse matrix class, as the map should only contain the non-zero elements.
Is it possible to solve this problem with the []-operator by making a distinction between 'setting' and 'getting'? In case of 'getting' should the operator only return a 0 without adding it to the map.
You can differentiate between reading and writing by using a proxy instead of a T&. Only showing the relevant code:
template <typename T>
class SparseMatrixProxy {
public:
//for reading an element:
operator T() const {
// Check if given indices are within the size of the matrix
if (indices[0] >= matrix.size[0] || indices[1] >= matrix.size[1])
throw std::invalid_argument("Indices out of bounds");
auto map_it = matrix.data.find(indices);
if (map_it == matrix.data.end()) {
return T{};
}
return map_it->second;
}
//for writing an element:
auto operator=(const T &t) {
//optional: when setting a value to 0 erase it from the map
if (t == T{}) {
matrix.data.erase(indices);
} else {
matrix.data[indices] = t;
}
return *this;
}
};
to be used in SparseMatrix like this:
// []-operator to set and get values from matrix
SparseMatrixProxy<T> operator[](const std::array<int, 2> indices) {
return {*this, indices};
}
With usage:
SparseMatrix<double> M(2, 2); // Create a new sparse matrix with 2 rows and 2 columns
M[{{1, 1}}] = 3.1; // Sets element {1,1} to 3.1
std::cout << M[{{1, 1}}] << '\n';
assert(M.mapsize() == 1); //1 element for index {1,1}
std::cout << M[{{0, 0}}] << '\n';
assert(M.mapsize() == 1); //still 1 element because reading doesn't insert an element
M[{{1, 1}}] = 0;
assert(M.mapsize() == 0); //0 elements because we set the only non-0 element to 0
Complete example.
There is std::map::find method. It returns an iterator and if it equals to map.end() then it means that the element is absent in the map.
Yup, it's a pain in the backside. Luckily the clever C++11 bods realised this and gave us a new method: at.
Use the at method (available from the C++11 standard onwards), which does not do any insertion, although you still need a catch handler for a possible std::out_of_range exception.
See http://en.cppreference.com/w/cpp/container/map/at
It's cheaper from performance point of view to implement sparse matrix by creating own mapping, e.g via storing indices.
template<typename T>
class SparseMatrix
{
...
int m, n;
vector<T> values;
vector<int> cols;
vector<int> rows;
}
template<typename T>
T SparseMatrix<T>::get(int row, int col) const
{
this->validateCoordinates(row, col);
int currCol = 0;
for (int pos = rows.at(row - 1) - 1; pos < rows.at(row) - 1; pos++)
{
currCol = cols.at(pos);
if (currCol == col)
return vals.at(pos);
else if (currCol > col)
break;
}
return T();
}
template<typename T>
SparseMatrix<T> & SparseMatrix<T>::set(T val, int row, int col)
{
// Validate coordinates here?
int pos = rows.at(row - 1) - 1;
int currCol = 0;
for (; pos < rows.at(row) - 1; pos++) {
currCol = cols.at(pos);
if (currCol >= col) {
break;
}
}
if (currCol != col) {
if (!(val == T())) {
this->insert(pos, row, col, val);
}
} else if (val == T()) {
this->remove(pos, row);
} else {
vals.at(pos) = val;
}
return *this;
}
template<typename T>
void SparseMatrix<T>::insert(int index, int row, int col, T val)
{
vals.insert(vals.begin() + index, val);
cols.insert(cols.begin() + index, col);
for (int i = row; i <= this->m; i++)
rows.at(i) = rows.at(i) + 1;
}
And so on...
I'm creating a random number generator which then sorts the digits from largest to smallest. Initially it worked but then I changed a few things. As far as I'm aware I undid all the changes (ctrl + z) but now I have errors at the points where i try to call the methods. This is probably a very amateur problem but I haven't found an answer. The error i'm met with is "method in class cannot be applied to given types"
Here's my code:
public class RandomMath {
public static void main(String[] args) {
String bigger = bigger(); /*ERROR HERE*/
System.out.println(bigger);
}
//create method for generating random numbers
public static int generator(int n){
Random randomGen = new Random();
//set max int to 10000 as generator works between 0 and n-1
for(int i=0; i<1; i++){
n = randomGen.nextInt(10000);
// exclude 1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 0000
if((n==1111 || n==2222 || n==3333 || n ==4444 || n==5555)
||(n==6666 || n==7777 || n==8888 || n==9999 || n==0000)){
i--;
}
}
return n;
}
//create method for denoting the bigger number
public static String bigger(int generated){
generated = generator(); /*ERROR HERE*/
System.out.println(generated);
int[] times = new int[10];
while (generated != 0) {
int val = generated % 10;
times[val]++;
generated /= 10;
}
String bigger = "";
for (int i = 9; i >= 0; i--) {
for (int j = 0; j < times[i]; j++) {
bigger += i;
}
}
return bigger;
}
}
You have not defined a method bigger(), only bigger(int generated). Therefore, you must call your bigger method with an integer parameter.
any help please, so i already wrote the prog but my if statement in my for loop is not working. the prog need to generate 6 random nos,then apply bubble sort which i already did.then the user must enter 6 numbers and these numbers must be compared against the random numbers and must say whether numbers are found in the random numbers or not. here's the code. something is wrong with the if statement ` public static void main(String[] args) {
try {
int numbers[] = new int[6]; //random numbers will be stored in new array
//2 loop will be created to avoid duplication of numbers
System.out.println("Array before Bubble sort");
for (int i = 0; i < 6; i++) {
numbers[i] = (int) (Math.random() * 40);
if (i > 0) {
for (int b = 0; b < i; b++) { //
if (numbers[b] == numbers[i]) {
i--; //decrement to continue the for loop if the integer has been repeated
}
}
}
System.out.print(numbers[i] + ","); //random numbers will be printed before using sorting bubble sort
}
//sort an array using bubble sort
bubbleSort(numbers);
System.out.println(" \nArray after bubble sort");
for (int i = 0; i < 6; i++) {
System.out.print(numbers[i] + ",");
}
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
System.out.println("\ninput 6 number between 1 and 40");
int inputNumber = Integer.parseInt(input.readLine());
for (int b = 0; b < 6; b++) {
System.out.println("number:");
int outcome=Integer.parseInt(input.readLine());
if(outcome==numbers){
System.out.println("found in random numbers");
}else{
System.out.println("not found in random numbers");
}
}
} catch (Exception e) {
System.out.println("error");
}
}
public static void bubbleSort(int[] numbers) {
int n = numbers.length;
int temp = 0;
for (int i = 0; i < n; i++) {
for (int j = 1; j < (n - i); j++) {
if (numbers[j - 1] > numbers[j]) { //swap the element
temp = numbers[j - 1];
numbers[j - 1] = numbers[j];
numbers[j] = temp;
}
}
}
}
}`
System.out.println("\ninput 6 number between 1 and 40");
//Scanner is specifically designed for getting an input purpose and introduced in Java 5,so better use it
Scanner s = new Scanner(System.in);
//you need to have nested loop here
//But the best way to search is use binary search,as you have already sorted the array
while (s.hasNextInt()) {
//one at a time from the input is put to outcome
int outcome = s.nextInt();
boolean found = false;
for (int b = 0; b < 6; b++) {
found = false;
if (outcome == numbers[b]) {
found = true;
//remember to break the inner loop if a match is found
break;
} else {
found = false;
}
}
if (found == true) {
System.out.println("found in random numbers");
} else {
System.out.println("not found in random numbers");
}
How do I make it so I can plug in the random value of a and b into the system.out.println so it will display in the console window what the random number was?
public class MoreIfStmts {
/* Chase Pittman
* This program compares two variables and tells which one is greater or if they're equal.
*/
public static void main(String[] args) {
int q=0;
while (q < 10) {
q=q+1;
int a=0;
int b=0;
a=(int) (Math.random() * 10);
b=(int) (Math.random() * 10);
if (a > b)
{
System.out.println ("Blue is better than red.");
} // This is the end of the then clause.
else
{
if (a < b)
{
System.out.println ("Red is better than blue.");
} // This is the end of the if clause.
else
if (a == b)
{
System.out.println ("Blue is as good as red.");
} // This is the end of the second else clause.
} // This is the end of the first else clause.
} // This is the end of while statement.
} // This is the end of main.
} // This is the end of class MoreIfStmts.
System.out.println ("Red is better than blue."+ " a="+a+ " b="+b);
You may also use formatted output:
System.out.printf("Blue is better than red. a = %d, b = %d\n", a, b);