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 would like to use prepared statements to insert thousands of rows at once into my postgres database. The data to insert is stored in a vector of structs.
By reading the answers to How to prepare statements and bind parameters in Postgresql for C++ I thought I found the way how to do it.
Unfortunately, the current version of libpqxx I am using doesn't support pqxx::prepare::invocation anymore and I wasn't able to find any alternative in the docs/internet.
The code I tried out for my purpose is the following:
//pqxx header
#include "pqxx/connection.hxx"
#include "pqxx/transaction.hxx"
#include "pqxx/nontransaction.hxx"
#include "pqxx/compiler-public.hxx"
#include "pqxx/result.hxx"
#include "pqxx/prepared_statement.hxx"
#include "pqxx/transaction_base.hxx"
#include "pqxx/internal/statement_parameters.hxx"
...
int main(){
struct testData {
string uuid;
float rndNo;
string timestamp;
};
vector<testData> dataBuffer;
testData dbdata;
string queryStr;
const char* query;
stringstream connStream;
stringstream queryStream;
string DB_NAME = "dbname";
string DB_USER = "postgres";
string DB_PASSWORD = "password";
string DB_HOSTADDR = "127.0.0.1";
string DB_PORT = "1234";
string DB_SCHEMA = "test_schema";
string tableName = "test_table";
//Create Random data
for (int i = 0; i < 100000; i++) {
dbdata.uuid = "fe2b22ba-6ce7-4bbc-8226-d7696fe7a047";
dbdata.rndNo = i / 3.123;
dbdata.timestamp = systemDateTimeSQLFormat(0);
dataBuffer.push_back(dbdata);
}
stringstream connStream;
connStream << "dbname = " << DB_NAME << " user = " << DB_USER << " password = " << DB_PASSWORD << " hostaddr = " << DB_HOSTADDR << " port = " << DB_PORT;
connection dbConn(connStream.str());
if (dbConn.is_open()) {
cout << "Opened database successfully: " << dbConn.dbname() << endl;
}
else {
cout << "Can't open database" << endl;
return;
}
pqxx::nontransaction W(dbConn);
std::string m_insertCommand = "INSERT INTO test_schema.test_table (column1, column2, column3) VALUES";
int buffSize = dataBuffer.size();
for (size_t i = 0; i < buffSize; i++)
{
unsigned int countOf$ = i * 3;
for (unsigned int i = 0; i < 3; ++i)
{
if (i == 0)
{
m_insertCommand += "(";
}
else
{
m_insertCommand += ", ";
}
m_insertCommand += "$";
std::stringstream ss;
ss << countOf$ + i + 1;
m_insertCommand += ss.str();
}
if (i < buffSize - 1)
m_insertCommand += ") ,";
}
m_insertCommand += ")";
//FOLLOWING CODE NOT POSSIBLE WITH libpqxx v12
dbConn.prepare("insert_into_db", m_insertCommand);
pqxx::prepare::invocation = W.exec_prepared("insert_into_db"); //prepare doesn't have a member "invocation"
for (size_t i = 0; i < buffSize; i++)
{
inv(dataBuffer.at(i).rndNo)(dataBuffer.at(i).timestamp)(dataBuffer.at(i).uuid); //inv not defined
}
inv.exec();
return 1;
}
pqxx::prepare::make_dynamic_params will probably solve your problem. It's solved my problem. Use this way:
for (size_t i = 0; i < buffSize; ++i)
{
auto element = dataBuffer.at(i);
vector<string> vect;
vect.reserve(3);
vect.push_back(pqxx::to_string(element.rndNo));
vect.push_back(element.timestamp);
vect.push_back(element.uuid);
work.exec_params(m_insertCommand, pqxx::prepare::make_dynamic_params(vect));
}
From the version 7.6.0 dynamic_params are deprecated. params can be used instead. Here is the new solution:
for (size_t i = 0; i < buffSize; ++i)
{
auto element = dataBuffer.at(i);
pqxx::params;
params.reserve(4);
params.append(pqxx::to_string(element.rndNo));
params.append(element.timestamp);
params.append(element.uuid);
params.append(); // For example insert null variable
work.exec_params(m_insertCommand, params);
}
I got several numbers from user by single linked list and my program's task is finding the smallest and largest number in the linked list by two classes and print them on the sreen. But after a time, my program got closed and i didn't see anything. What went wrong?
#include<iostream>
using namespace std;
struct Node
{
double Number;
struct Node *Point;
} *End = nullptr;
typedef struct Node node;
namespace Min_Max
{
class Min
{
node *Result = End;
public: Min()
{
if(Result == nullptr)
{
cout << "You didn\'t enter anything!\a";
system("pause");
exit(EXIT_FAILURE);
}
node *Counter = Result->Point;
while(Counter != nullptr)
{
if(Counter->Number < Result->Number)
Result = Counter;
Result = Result->Point;
}
}
node* Show()
{
return Result;
}
};
class Max
{
private:
node *Result = End;
public:
Max()
{
if(Result == nullptr)
{
cout << "You didn\'t enter anything!\a";
system("pause");
exit(EXIT_FAILURE);
}
node *Counter = Result->Point;
while(Counter != nullptr)
{
if(Counter->Number > Result->Number)
Result = Counter;
Result = Result->Point;
}
}
node* Show()
{
return Result;
}
};
};
int main()
{
node *linker = nullptr;
register short int Counter = 1;
while(1)
{
linker = new node;
if(linker == nullptr)
{
cout << "An error occurred during allocating memory." << endl << endl;
system("pause");
return 0;
}
cout << "Number " << Counter << ": Enter your number: ";
cin >> linker->Number;
system("cls");
if(linker->Number == 0)
{
delete linker;
break;
}
linker->Point = End;
End = linker;
Counter++;
}
Min_Max::Min Min;
Min_Max::Max Max;
cout << "The smallest number is " << (Min.Show())->Number << endl;
cout << "The largest number is " << (Max.Show())->Number << endl;
return 0;
}
My C++ compiler is GCC-C++11 and my operating system is Windows 10.
I am doing a project for a class writing C-String-editing functions. 3/5 of the functions I have to write change the size of the char arrays I have to use, and they are being read through an ifstream input. Here is the program:
#include <iostream>
#include <fstream>
using namespace std;
void stringCopy(char *A, char *B);
bool stringCompare(char *A, char *B);
void stringConcatenation(char *A, char *B); //added const to make sure b is never changed
int stringPosition(char *A, char B);
int stringLength(char *A);
//-------------------MY-FUNCTIONS----------------------
int cStringLen(const char*); //finds string length, but doesn't account for null char
void reSize(char*&, int len, int newLen);
void input(char*& A, istream& is);
void printMessage(const char* word1, const char* word2, const char* message);
int main()
{
ifstream ifs{"input.txt"};
ofstream ofs{"output.txt"};
char* word1 = "";
char* word2 = "";
input(word1, ifs);
input(word2, ifs);
printMessage(word1, word2, "stringCopy()");
stringCopy(word1, word2);
printMessage(word1, word2, "after stringCopy()");
cout << endl;
input(word1, ifs);
input(word2, ifs);
printMessage(word1, word2, "stringCompare()");
if(stringCompare(word1, word2))
{
cout << "They match!" << endl;
}
else
{
cout << "They don't match!" << endl;
}
stringCopy(word1, word2);
printMessage(word1, word2, "comparing after stringCopy()");
if(stringCompare(word1, word2))
{
cout << "They match!" << endl;
}
else
{
cout << "They don't match!" << endl;
}
cout << endl;
input(word1, ifs);
input(word2, ifs);
printMessage(word1, word2, "stringConcatenation()");
stringConcatenation(word1, word2);
printMessage(word1, word2, "after stringConcatenation()");
cout << endl;
input(word1, ifs);
input(word2, ifs);
printMessage(word1, word2, "stringPosition()");
cout << "Searching for 'm' in word1..." << endl << "position returned is: " << stringPosition(word1, 'm') << endl;
cout << "Searching for 'n' in word2..." << endl << "position returned is: " << stringPosition(word2, 'n') << endl;
cout << endl;
input(word1, ifs);
cout << "stringLength()" << endl;
cout << "word1: " << word1 << endl;
cout << "The length of word1 is: " << stringLength(word1) << endl;
cout << "after stringLength()" << endl;
cout << "word1: " << word1 << endl;
return 0;
}
void stringCopy(char *A, char *B)
{
///GETTING THE SIZES OF BOTH ARRAYS
int counterA = cStringLen(A) + 1;
int counterB = cStringLen(B) + 1;
///MAKES SURE BOTH ARE THE SAME SIZE BEFORE COPYING
if(counterA < counterB)
{
reSize(A, counterA, counterB);
}
else
{
reSize(A, counterB, counterA);
}
///THE COPY
for(int i = 0; i < counterB; i++) *(A + i) = *(B + i); //each character is copied to A from B
}
bool stringCompare(char *A, char *B)
{
///getting length of one string
int counter = cStringLen(A);
///will move through string until diff char found
for(int i = 0; i < counter + 1; i++)
{
if(*(A + i) != *(B + i))
{
return false;
}
}
return true;
}
void stringConcatenation(char *A, char *B) //added const to make sure b is never changed
{
///getting length of both strings
int counterA = cStringLen(A)+1;
int counterB = cStringLen(B)+1;
///putting the length of both together for new string
const int COUNTERS = counterA + counterB - 1;
///making A the size of both strings - 1
reSize(A, counterA, COUNTERS);
///copying b to the parts of a past the original
for(int i = 0; i < counterB; i++)
{
*(A + (counterA - 1) + i) = *(B + i); //will override the '/0' char of A
}
}
int stringPosition(char *A, char B)
{
int counter = cStringLen(A) + 1;
///searching through string for char
for(int i = 0; i < counter; i++)
{
if(*(A + i) == B)
{
return i; //found!
}
}
///checking if b == '\0' and a '\0' isn't found somewhere before last spot of A
if(B == '\0')
{
return counter;
}
return -1; //not found
}
int stringLength(char *A)
{
int counter = cStringLen(A) + 1;
char* car = new char[counter + 1];
for(int i = 0; i < counter; i++)
{
*(car + 1 + i) = *(A + i);
}
*(car + 0) = counter;
delete[] A;
A = car;
/**
* Will take string as param.
* Shifts all characters to the right by one and store the length of the string in position 0.
- Length doesn't include position 0.
*/
return counter; //temp
}
//-----------------------------------------MY FUNCTIONS---------------------------------------------------------------------------
int cStringLen(const char* A) //finds string length, but doesn't account for null char
{
int counter = 0;
while(*(A + counter) != '\0')
{
counter++;
}
return counter;
}
void reSize(char*& A, int len, int newLen)
{
char* car = new char[newLen];
for(int i = 0; i < newLen; i++)
{
if(i < len)
{
*(car + i) = *(A + i);
}
else if(i >= len && i < newLen)
{
*(car + i) = '\0';
}
}
delete[] A;
A = car;
}
void input(char*& A, istream& is)
{
int wordSize = 0;
int arrSize = 1;
char c = 'o'; //checking char
char* car = new char[arrSize];
while((!(is.eof())) && (c != ' ' && c != '\t' && c != '\n'))
{
is.unsetf(ios_base::skipws);
is >> c;
if(is.eof())
{
delete[] A;
A = car;
return;
}
if(c != ' ' && c != '\t' && c != '\n')
{
if(wordSize == arrSize)
{
reSize(car, arrSize, arrSize * 2);
}
*(car + wordSize) = c;
}
wordSize++;
}
is.setf(ios_base::skipws);
delete[] A;
A = car;
}
void printMessage(const char* word1, const char* word2, const char* message)
{
cout << message << endl;
cout << "word1: " << word1 << endl << "word2: " << word2 << endl;
}
I thought I got it all done just fine. Keep in mind that I added the "&" operator after each of the pointer parameters already. Here is how they were before:
void stringCopy(char *&A, char *B);
bool stringCompare(char *A, char *B);
void stringConcatenation(char *&A, char *B); //added const to make sure b
is never changed
int stringPosition(char *A, char B);
int stringLength(char *&A);
But, when I got to class, my teacher said we weren't allowed to change the function headers in any way. So, I am stuck passing by value for the assignment. The problem is that I have no way of changing the c-strings outside the editing functions now. Any changes I do to them stay inside there.
It all compiles just fine, and, if I make the pointers pass-by-reference, the program runs flawlessly. I am just wondering how I could change the values of the c-strings outside of the editing functions. This assignment is starting to become a pain (so many f***ing restrictions).
I think what your teacher wants you to do is to change the value at the character pointer instead of creating a new string.
So instead trying to reassigning parameter A to a new char* you change the value that A points to in memory. That way the method that called your function still points to that same memory and when they access that location the get the value you changed from within your function.
I've read on here that the /n in scanf makes the program wait for another input. my program however does not have a /n in scanf but it still waits for another input after i enter a number. Not sure why.
#include <stdio.h>
int main()
{
int inputNumber, index = 2, lowestPrime = 1, number = 1;
printf("Enter an integer: ");
scanf("%d", &inputNumber);
if(scanf("%d", &inputNumber) != 1)
{
printf("Invalid input");
return 1;
}
else
{
printf(" The prime factorization of %d is",inputNumber);
while(inputNumber > lowestPrime)
{
if(inputNumber % index != 0)
{
index += 1;
}
else
{
inputNumber = (inputNumber / index);
printf(" %d", index);
}
}
}
return 0;
}
You're calling scanf twice here, once for the original call and once in your if statement. Replace the statement inside the if parenthesis by
if (inputNumber!= 1)
and you should be fine!