Vala yield not returning - asynchronous

I'm having trouble writing an async function in Vala.
I understand that the function's callback has to get registered somewhere in order for execution to continue after the yield statements, so I add it to the GLib mainloop to be called periodically using Idle.add. Here is my dummy code:
async void loop_func()
{
var id = Idle.add(loop_func.callback);
message("Added idle %u",id);
yield;
message("yielded successfully 1");
yield;
message("yielded successfully 2");
for (var i = 0; i < 20; i++)
{
message("%d",i);
yield;
}
message("finished");
}
int main()
{
var loop = new GLib.MainLoop();
loop_func.begin(() => {loop.quit();});
loop.run();
return 0;
}
Despite this, the code after the 2nd yield statement never gets executed.
This can be seen from the output:
$ ./async
** Message: 20:07:24.932: async.vala:4: Added idle 1
** Message: 20:07:24.932: async.vala:7: yielded successfully 1
And then it hangs.
What am I missing here?

Although GLib calls an idle function repeatedly until it tells it to stop (by returning false), the async function's .callback seems to quit repeating immediately after being called.
This can be overcome by adding the callback again every time before the yield statement:
async void loop_func()
{
for (var i = 0; i < 20; i++)
{
Idle.add(loop_func.callback);
yield;
}
}
An alternative (and possibly more effective) way to do this would be to ignore the value that the async function's callback returns:
async void loop_func()
{
var id = Idle.add(() => {loop_func.callback(); return Source.CONTINUE;});
for (var i = 0; i < 20; i++)
{
yield;
}
Source.remove(id);
}

Related

Dart waiting for an async function to complete without await

I've narrowed my problem down to the below code. I'm new to Dart, and I can't seem to figure out why the code won't move on to printing "done" before print the numbers 1-10.
import 'dart:async';
Future<bool> wait() async {
for(int i = 0; i < 10; i++){
print('$i');
}
return true;
}
Future testAsync() async {
print('starting');
wait();
print('done');
}
main(List<String> arguments){
testAsync();
}
Since there is no await keyword in front of wait(); shouldn't the program execute print('done'); and then print out the numbers? For some reason, it is waiting for wait(); to finish anyway.
This is expected behavior since Dart 2.0.0:
(Breaking) Functions marked async now run synchronously until the first await statement. Previously, they would return to the event loop once at the top of the function body before any code runs (issue 30345).
https://github.com/dart-lang/sdk/blob/stable/CHANGELOG.md
Since you async method does not actually wait on anything, the entire method is therefore executed synchronously.
You can change you code into something like this to get the behavior your want:
import 'dart:async';
Future<bool> wait() async {
await Future.microtask(() {
for (int i = 0; i < 10; i++) {
print('$i');
}
});
return true;
}
Future testAsync() async {
print('starting');
wait();
print('done');
}
main(List<String> arguments) {
testAsync();
}

What is an async scope for a delegate in Vala?

I am trying the async examples from the GNOME project site. I get the follwoing warning which I don't under stand on how to fix.
async.vala:8.2-8.17: warning: delegates with scope="async" must be owned
Code
async double do_calc_in_bg(double val) throws ThreadError {
SourceFunc callback = do_calc_in_bg.callback;
double[] output = new double[1];
// Hold reference to closure to keep it from being freed whilst
// thread is active.
// WARNING HERE
ThreadFunc<bool> run = () => {
// Perform a dummy slow calculation.
// (Insert real-life time-consuming algorithm here.)
double result = 0;
for (int a = 0; a<100000000; a++)
result += val * a;
output[0] = result;
Idle.add((owned) callback);
return true;
};
new Thread<bool>("thread-example", run);
yield;
return output[0];
}
void main(string[] args) {
var loop = new MainLoop();
do_calc_in_bg.begin(0.001, (obj, res) => {
try {
double result = do_calc_in_bg.end(res);
stderr.printf(#"Result: $result\n");
} catch (ThreadError e) {
string msg = e.message;
stderr.printf(#"Thread error: $msg\n");
}
loop.quit();
});
loop.run();
}
The warning is pointing at the run variable inside the async function. Who or what needs to be owned? The reference to the closure?
The delegate needs to have a well defined owner all the time. The error message is a bit misleading.
To fix it you have to explicitly transfer the ownership from the delegate to the thread constructor:
new Thread<bool>("thread-example", (owned) run);
Instead of
new Thread<bool>("thread-example", run);
See also: https://wiki.gnome.org/Projects/Vala/Tutorial#Ownership
PS: The generated C code is fine in both cases. (at least with valac 0.46.6)

How do I operate List async by using Dart?

I have a collection, and now I need to iterate through the data in it, and then modify one of the fields, but this modification process is time consuming and requires asynchronous, I do not know how to write this code correctly.
Here are my fake code:
Stream<int> asynchronousNaturalsTo(int n) async* {
yield calculate(n).asStream();
}
Future<int> calculate(int i) async {
// async calculate result. maybe there is some long-running operate.
return Future.value(i + 10);
}
main() async {
// 1. I have a List that contains data needs be calculated by async.
for (int i = 0; i < 3; i++) {
// 2. calculate
var list = await asynchronousNaturalsTo(i);
// 3. finally, use the final result.
print(list);
}
}
How do I write the code?
thx...

Network timeout using node.js client at about 5 seconds

Note, this question was previously very different. This is now the real issue. Which is...
When making a call to executeStoredProcedure() using the node.js client I get a 408 code, RequestTimeout and I get no data back from the sproc's "body". This seems to occur at about 5 seconds, but when I time bound things from inside the sproc itself, any value over say 700 milliseconds causes me to get a network timeout (although I don't see it until about 5 seconds have passed).
Note, I can have longer running sprocs with read operations. This only seems to occur when I have a lot of createDocument() operations, so I don't think it's on the client side. I think something is happening on the server side.
It's still possible that my original thought is true and I'm not getting a false back from a createDocument() call which causes my sproc to keep running past its timeout and that's what's causing the 408.
Here is the time limited version of my create documents sproc
generateData = function(memo) {
var collection, collectionLink, nowTime, row, startTime, timeout;
if ((memo != null ? memo.remaining : void 0) == null) {
throw new Error('generateData must be called with an object containing a `remaining` field.');
}
if (memo.totalCount == null) {
memo.totalCount = 0;
}
memo.countForThisRun = 0;
timeout = memo.timeout || 600; // Works at 600. Fails at 800.
startTime = new Date();
memo.stillTime = true;
collection = getContext().getCollection();
collectionLink = collection.getSelfLink();
memo.stillQueueing = true;
while (memo.remaining > 0 && memo.stillQueueing && memo.stillTime) {
row = {
a: 1,
b: 2
};
getContext().getResponse().setBody(memo);
memo.stillQueueing = collection.createDocument(collectionLink, row);
if (memo.stillQueueing) {
memo.remaining--;
memo.countForThisRun++;
memo.totalCount++;
}
nowTime = new Date();
memo.nowTime = nowTime;
memo.startTime = startTime;
memo.stillTime = (nowTime - startTime) < timeout;
if (memo.stillTime) {
memo.continuation = null;
} else {
memo.continuation = 'Value does not matter';
}
}
getContext().getResponse().setBody(memo);
return memo;
};
The stored procedure above queues document creates in a while loop until the API returns false.
Keep in mind that createDocument() is an asynchronous method. The boolean returned represents whether it is time to wrap up execution right there and then. The return value isn't "smart" enough to estimate and account for how much time the async call will take; so it can't be used for queueing a bunch of calls in a while() loop.
As a result, the stored procedure above doesn't terminate gracefully when the boolean returns false because it has a bunch of createDocument() calls that are still running. The end result is a timeout (which eventually leads to blacklisting on repeated attempts).
In short, avoid this pattern:
while (stillQueueing) {
stillQueueing = collection.createDocument(collectionLink, row);
}
Instead, you should use the callback for control flow. Here is the refactored code:
function(memo) {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
var row = {
a: 1,
b: 2
};
if ((memo != null ? memo.remaining : void 0) == null) {
throw new Error('generateData must be called with an object containing a `remaining` field.');
}
if (memo.totalCount == null) {
memo.totalCount = 0;
}
memo.countForThisRun = 0;
createMemo();
function createMemo() {
var isAccepted = collection.createDocument(collectionLink, row, function(err, createdDoc) {
if (err) throw err;
memo.remaining--;
memo.countForThisRun++;
memo.totalCount++;
if (memo.remaining > 0) {
createMemo();
} else {
getContext().getResponse().setBody(memo);
}
});
if (!isAccepted) {
getContext().getResponse().setBody(memo);
}
}
};

how to handle this type of things. using asp.net mvc

I have
public jsonresult update(studentinfo s)
{
for(i=0;i>0;i++)
{
var x = // i am getting some x so i am checking again
if( x != null)
{
var updateuser = student.update(s.student,"","");
**return json(updateuser.ToString());** // if i keep it here i am getting exceptoin saying not all code paths return value bec this return i can not keep it out for loop bec each and evary updateuser i need to return json..
}
}
}
How to overcome this type of things?
What language are you using to write your code? What you've posted doesn't look like any of the valid languages I know for .NET. Here's how the controller action might look in C# (assuming this is the language you are using):
public ActionResult Update(StudentInfo s)
{
// create some collection that will contain all updated users
var updatedUsers = new List<StudentInfo>();
// Revise the loop as it is absolutely not clear from your code
// what you are trying to do. The way you wrote the loop it will
// never execute - for(int i=0; i>0; i++)
for (int i = 0; i < 5; i++)
{
var updatedUser = student.Update(s.student, "", "");
updatedUsers.Add(updatedUser);
}
// return the list of updated users outside the loop so that the compiler
// doesn't complain about paths of the method not returning a value
return Json(updatedUsers);
}
If I understand correctly, you want to return a collection of users. The 'return' keyword does not work like that. You need to return the entire collection at once.

Resources