Analyze concurency::task() API & why do we need this? - c++

I'm, trying to understand the syntax of the concurrency::task in the below code snippet.
I'm unable to understand this code snippet syntax.
How do we analyze this:
What is "getFileOperation" here. Is it an object of type StorageFile
class ? What does "then" keyword mean here ? There is a "{" after
then(....)? I'm unable to analyze this syntax ?
Also why do we need this concurrency::task().then().. Use case ?
concurrency::task<Windows::Storage::StorageFile^> getFileOperation(installFolder->GetFileAsync("images\\test.png"));
getFileOperation.then([](Windows::Storage::StorageFile^ file)
{
if (file != nullptr)
{
Taken from MSDN concurrency::task API
void MainPage::DefaultLaunch()
{
auto installFolder = Windows::ApplicationModel::Package::Current->InstalledLocation;
concurrency::task<Windows::Storage::StorageFile^> getFileOperation(installFolder->GetFileAsync("images\\test.png"));
getFileOperation.then([](Windows::Storage::StorageFile^ file)
{
if (file != nullptr)
{
// Set the option to show the picker
auto launchOptions = ref new Windows::System::LauncherOptions();
launchOptions->DisplayApplicationPicker = true;
// Launch the retrieved file
concurrency::task<bool> launchFileOperation(Windows::System::Launcher::LaunchFileAsync(file, launchOptions));
launchFileOperation.then([](bool success)
{
if (success)
{
// File launched
}
else
{
// File launch failed
}
});
}
else
{
// Could not find file
}
});
}

getFileOperation is an object that will return a StorageFile^ (or an error) at some point in the future. It is a C++ task<t> wrapper around the WinRT IAsyncOperation<T> object returned from GetFileAsync.
The implementation of GetFileAsync can (but isn't required to) execute on a different thread, allowing the calling thread to continue doing other work (like animating the UI or responding to user input).
The then method lets you pass a continuation function that will be called once the asynchronous operation has completed. In this case, you're passing a lambda (inline anonymous function) which is identified by the [] square brackets followed by the lambda parameter list (a StorageFile^, the object that will be returned by GetFileAsync) and then the function body. This function body will be executed once the GetFileAsync operation completes its work sometime in the future.
The code inside the continuation function passed to then typically (but not always) executes after the code that follows the call to create_task() (or in your case the task constructor).

Related

In WinRT how can I WriteValueWithResultAsync from other functions?

C++, WinRT, VS2017, Win10
In my C++ MFC app I have put C++/WinRT code into a function to find my Bluetooth LE device, create a device object, enumerate the Services and their Characteristics, and then save the txChacteristic to a characteristic object.
While still in that function, where the txChacteristic is still in scope, I can write a value with
auto status = co_await txCharacteristic.WriteValueWithResultAsync(writer.DetachBuffer(),
winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattWriteOption::WriteWithoutResponse);
The problem is that I cannot figure out a way to make a characteristic object public so that it is available for writes from other functions.
I have tried to make the txChacteristic object static and then reference it in another function but it shows as "undefined" in that other function.
Is there a way to make an empty characteristic object outside the function and then copy into it later? Or create an array or vector of this object type to copy into?
Does anyone have a suggestion on how this can be done?
I was finally able to write from another function. In the public scope I initiated empty characteristic objects like this:
winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristic pubTxCharacteristic = nullptr;
winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristic pubRxCharacteristic = nullptr;
In the OpenDevice function where we actually create the rx and txCharacteristic objects I transfered the objects to the public ones like this:
pubTxCharacteristic = txCharacteristic;
pubRxCharacteristic = rxCharacteristic;
When setting up the callback to the Rx characteristic I needed to also use the public object to keep the callback in public awareness.
GattClientCharacteristicConfigurationDescriptorValue cccdValue = GattClientCharacteristicConfigurationDescriptorValue::None;
if ((pubRxCharacteristic.CharacteristicProperties() & GattCharacteristicProperties::Notify) != GattCharacteristicProperties::None)
{
cccdValue = GattClientCharacteristicConfigurationDescriptorValue::Notify;
}
GattCommunicationStatus comStatus = co_await pubRxCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(cccdValue);
event_token etValueChangeToken;
etValueChangeToken = pubRxCharacteristic.ValueChanged([](GattCharacteristic const& charateristic,
GattValueChangedEventArgs const& args)
{
DataReader reader = DataReader::FromBuffer(args.CharacteristicValue());
//... calback code here
}
While still in this OpenDevice function that created the characteristic objects I used the new public objects in the original writes like this:
auto status = co_await pubTxCharacteristic.WriteValueWithResultAsync(writer.DetachBuffer(),
winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattWriteOption::WriteWithoutResponse);
if (status.Status() != GattCommunicationStatus::Success){}
In the other Test function, however, (still in the same .cpp as the OpenDevice function) the compiler would not allow the same syntax to write. It would not allow the co_await and the Status() referred to a different enumeration.
Here is where it stands as of now:
auto status = ubTxCharacteristic.WriteValueWithResultAsync(writer.DetachBuffer(),
winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattWriteOption::WriteWithoutResponse);
if (status.Status() == winrt::Windows::Foundation::AsyncStatus::Error) {}
The write is successful and the callback shows the reply from the device.
Just out of curiosity, however, does anybody have a guess as to why in one function the auto status = co_await pubTxCharacteristic.WriteValueWithResultAsync would have the status.Status() as a GattCommunicationStatus and the same call in a different function but in the same cpp (without the co_await) has the statue.Status() as a winrt::Windows::Foundation::AsyncStatus enumeration?
I mean, its working, but I'm just curious why this would change.
As for the question posed at the end of my original question, #IInspectable was correct about the IAsyncAction it was just that I was not looking at the cause of the problem.
As it turns out:
The OpenDevice function mentioned in the post as the function that created the device, services, and characteristics objects was:
winrt::Windows::Foundation::IAsyncAction OpenDevice(unsigned long long deviceAddress){}
while the other function was bool return bool WriteCommand() and that was the difference.
I changed the other function to
winrt::Windows::Foundation::IAsyncAction WriteCommend()
and that solved the 2nd part of the problem.

Flutter/Dart: Concurrent Modification Exception without changing list elements

During testing and debugging of an app, i noticed there was an Exception that mostly happens during debug testing only, inside a for-loop that iterates over a list:
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: Concurrent modification during iteration: Instance(length:0) of '_GrowableList'.
I have searched around and found that it mostly happens if you change the list itself during the iteration, but i cannot see where it happens in the code:
Main function:
static Future<void> save(EntryModel entry) async {
...
List<TagModel> tagsList = entry.tags;
List<int> tagIdsInserted = [];
if (tagsList != null && tagsList.isNotEmpty) {
for (TagModel tag in tagsList) {
//Error happens inside this loop
int tagIdInserted = await TagContract.save(tag); //this function does not alter the tag in any way.
if (tagIdInserted == null || tagIdInserted <= 0) {
throw Exception('Invalid TagID!');
}
tagIdsInserted.add(tagIdInserted);
}
}
What happen is during the first iteration it runs fine, but the second or third one the List<TagModel> tagsList suddenly becomes empty, including from the initial object (the entry passed to the function).
Also i noticed that during runs without debugging it runs mostly fine, but i am not sure if that is because i am not catching the error.
Thanks in advance.
Try to avoid using await inside a loop, it is just too dangerous.
You have to understand how asynchronous code execute. If an await is encountered and the Future is unable to return synchronously, the runtime will suspend the execution of this function and jump to whatever other jobs that are on the top of the queue.
So when the await is encountered, the runtime will start executing some god-knows-where code and those code touched your tagsList.
Try to understand the following example. This will directly triggers the exception.
void main() {
List<int> ids = [1,2,3];
test(ids);
ids.add(1); // If the async function get suspended, this becomes the top of the queue.
}
void test(List<int> ids) async {
for (final id in ids) {
await Future.delayed(Duration(milliseconds: 10));
}
}
In async programming, avoid writing an await who depends on exposed shared states.
For a list of async tasks, always prepare them in an Iterable<Future>, then use Future.wait to synchronize them and get the result in a single await.
For your code
final results = await Future.wait(tagsList.map((tag)=>TagContract.save(tag)))

Native v8::Promise Result

I'm trying to call a JS-function from C++ using v8/Nan which in turn returns a Promise.
Assuming I have a generic Nan Callback
Nan::Callback fn
I then call this function using the following code
Nan::AsyncResource resource(Nan::New<v8::String>("myresource").ToLocalChecked());
Nan::MaybeLocal<v8::Value> value = resource.runInAsyncScope(Nan::GetCurrentContext()->Global(), fn, 0, 0);
The function is being called correctly, and I receive the promise on the C++ side
v8::Handle<v8::Promise> promiseReturnObject =
v8::Handle<v8::Promise>::Cast ( value.ToLocalChecked() );
I can then check the state of the promise using
v8::Promise::PromiseState promiseState = promiseReturnObject->State();
Of course at the time the promise is still pending, and I can't access it's result. The only way I've found so far to receive the result of that promise is by using the Then method on the promiseReturnObject.
promiseReturnObject->Then(Nan::GetCurrentContext(), callbackFn);
Is there any way to retreive that result synchronously in the scope of the function that calls fn? I've tried using std::promise and passing it to as a data argument to v8::FunctionTemplate of callbackFn, but calling wait or get on the respective std::future blocks the execution and the promise is never fulfilled. Do I need to resort to callbacks?
Any help or idea on how I could set this up would be much appreciated.
I derived an answer from https://github.com/nodejs/node/issues/5691
if (result->IsPromise()) {
Local<Promise> promise = result.As<Promise>();
if (promise->HasHandler()) {
while (promise->State() == Promise::kPending) {
Isolate::GetCurrent()->RunMicrotasks();
}
if (promise->State() == Promise::kRejected) {
Nan::ThrowError(promise->Result());
}
else
{
// ... procses promise->Result() ...
}
}
}

What's a proper way to use set_alert_notify to wake up main thread?

I'm trying to write my own torrent program based on libtorrent rasterbar and I'm having problems getting the alert mechanism working correctly. Libtorrent offers function
void set_alert_notify (boost::function<void()> const& fun);
which is supposed to
The intention of of the function is that the client wakes up its main thread, to poll for more alerts using pop_alerts(). If the notify function fails to do so, it won't be called again, until pop_alerts is called for some other reason.
so far so good, I think I understand the intention behind this function. However, my actual implementation doesn't work so good. My code so far is like this:
std::unique_lock<std::mutex> ul(_alert_m);
session.set_alert_notify([&]() { _alert_cv.notify_one(); });
while (!_alert_loop_should_stop) {
if (!session.wait_for_alert(std::chrono::seconds(0))) {
_alert_cv.wait(ul);
}
std::vector<libtorrent::alert*> alerts;
session.pop_alerts(&alerts);
for (auto alert : alerts) {
LTi_ << alert->message();
}
}
however there is a race condition. If wait_for_alert returns NULL (since no alerts yet) but the function passed to set_alert_notify is called before _alert_cw.wait(ul);, the whole loop waits forever (because of second sentence from the quote).
For the moment my solution is just changing _alert_cv.wait(ul); to _alert_cv.wait_for(ul, std::chrono::milliseconds(250)); which reduces number of loops per second enough while keeping latency low enough.
But it's really more workaround then solution and I keep thinking there must be proper way to handle this.
You need a variable to record the notification. It should be protected by the same mutex that owns the condition variable.
bool _alert_pending;
session.set_alert_notify([&]() {
std::lock_guard<std::mutex> lg(_alert_m);
_alert_pending = true;
_alert_cv.notify_one();
});
std::unique_lock<std::mutex> ul(_alert_m);
while(!_alert_loop_should_stop) {
_alert_cv.wait(ul, [&]() {
return _alert_pending || _alert_loop_should_stop;
})
if(_alert_pending) {
_alert_pending = false;
ul.unlock();
session.pop_alerts(...);
...
ul.lock();
}
}

Delete an object after the callback is called C++

I create a new object and set a data and a callback something like this:
class DownloadData
{
std::function<void(int, bool)> m_callback;
int m_data;
public:
void sendHttpRequest()
{
// send request with data
}
private:
void getHttpResponse(int responseCode)
{
if (responseCode == 0)
{
// save data
m_callback(responseCode, true);
delete this;
return;
}
// some processing here
if (responseCode == 1 && some other condition here)
{
m_callback(responseCode, false);
delete this;
return;
}
}
}
Now the usage - I create a new object:
if (isNeededToDownloadTheFile)
{
DownloadData* p = new DownloadData(15, [](){});
p->sendHttpRequest();
}
But as you can see https://isocpp.org/wiki/faq/freestore-mgmt#delete-this it is highly not desirable to make a suicide. Is there a good design pattern or an approach for this?
You could put them in a vector or list, have getHttpResponse() set a flag instead of delete this when it's completed, and then have another part of the code occasionally traverse the list looking for completed requests.
That would also allow you to implement a timeout. If the request hasn't returned in a day, it's probably not going to and you should delete that object.
If you want to put the delete out of that function, the only way is to store the object somehow. However, this raises the ownership questions: who is the owner of the asynchronous http request that's supposed to call a callback?
In this scenario, doing the GCs job actually makes the code pretty clear. However, if you wanted to make it more adaptable to C++, I'd probably settle on a promise-like interface, similar to std::async. That way the synchronous code path makes it way easier to store the promise objects.
You asked for a code example, so there goes:
Typical approach would look like this:
{
DownloadData* p = new DownloadData(15, [](auto data){
print(data)
});
p->sendHttpRequest();
}
Once the data is available, it can be printed. However, you can look at the problem "from the other end":
{
Future<MyData> f = DownloadData(15).getFuture();
// now you can either
// a) synchronously wait for the future
// b) return it for further processing
return f;
}
f will hold the actual value once the request actually processes. That way you can push it as if it was a regular value all the way up to the place where that value is actually needed, and wait for it there. Of course, if you consume it asynchronously, you might as well spawn another asynchronous action for that.
The implementation of the Future is something that's outside of the scope of this answer, I think, but then again numerous resources are available online. The concept of Promises and Futures isn't something specific to C++.
If the caller keeps a reference to the downloading object then it can erase it when the download signals it has ended:
class DownloadData
{
// true until download stops (atomic to prevent race)
std::atomic_bool m_downloading;
int m_data;
std::function<void(int, bool)> m_callback;
public:
DownloadData(int data, std::function<void(int, bool)> callback)
: m_downloading(true), m_data(data), m_callback(callback) {}
void sendHttpRequest()
{
// send request with data
}
// called asynchronously to detect dead downloads
bool ended() const { return !m_downloading; }
private:
void getHttpResponse(int responseCode)
{
if (responseCode == 0)
{
// save data
m_callback(responseCode, true);
m_downloading = false; // signal end
return;
}
// some processing here
if(responseCode == 1)
{
m_callback(responseCode, false);
m_downloading = false; // signal end
return;
}
}
};
Then from the caller's side:
std::vector<std::unique_ptr<DownloadData>> downloads;
// ... other code ...
if (isNeededToDownloadTheFile)
{
// clean current downloads by deleting all those
// whose download is ended
downloads.erase(std::remove_if(downloads.begin(), downloads.end(),
[](std::unique_ptr<DownloadData> const& d)
{
return d->ended();
}), downloads.end());
// store this away to keep it alive until its download ends
downloads.push_back(std::make_unique<DownloadData>(15, [](int, bool){}));
downloads.back()->sendHttpRequest();
}
// ... etc ...