IS4Code / PawnPlus

A SA-MP plugin enhancing the capabilities of the Pawn programming language
MIT License
102 stars 17 forks source link

List of tasks as a parameter in `task_all` #50

Closed duydang2311 closed 2 years ago

duydang2311 commented 2 years ago

Hi @IllidanS4,

The current task_all implementation uses rest parameter for passing a number of tasks.

I would love to request a feature that you can pass a list (or any other dynamic containers) of tasks to task_all as a parameter, not a rest one.

This is super useful when we work with loops, for example:

new Task:tasks[100];
for(new i = 0; i != sizeof tasks; ++i) {
    tasks[i] = task_new();
    task_set_result_ms(tasks[i], 1, 1000);
}
await task_all(tasks);
for(new i = 0; i != sizeof tasks; ++i) {
    task_delete(tasks[i]);
}
new List:listOfTasks = list_new();
for(new i = 0; i != 100; ++i) {
    new Task:t = task_new();
    task_set_result_ms(t, 1, 1000);
    list_add(listOfTasks, t);
}
await task_all(listOfTasks);
list_clear_deep(listOfTasks);
IS4Code commented 2 years ago

Hello, would using pawn_call_native be sufficient?

await Task:pawn_call_native(pawn_nameof(task_all), "l", listOfTasks);
dinhkhoi2298 commented 2 years ago

hay @duydang2311

duydang2311 commented 2 years ago

Hello, would using pawn_call_native be sufficient?

await Task:pawn_call_native(pawn_nameof(task_all), "l", listOfTasks);

Thanks for the fast response!

There are few runtime errors in pp_on_error when I run a test with pawn_call_native.

hook OnGameModeInit() {
    new List:listOfTasks = list_new();
    for(new i = 0; i != 100; ++i) {
        new Task:t = task_new();
        task_set_result_ms(t, 1, 1000);
        list_add(listOfTasks, t);
    }
    await Task:pawn_call_native(pawn_nameof(task_all), "l", listOfTasks);
    return 1;
}
SOURCE: pawn_call_native
MESSAGE: native function 'task_all' has raised an AMX error 5: Invalid memory access

SOURCE: task_wait
MESSAGE: task reference is invalid (value 0x0)

SOURCE: task_get_result
MESSAGE: task reference is invalid (value 0x0)
IS4Code commented 2 years ago

Sorry, my bad, I forgot that l actually copies the contents to the function as values, not references (which are needed in this case). A quick fix would be to store the task as array in the list, i.e.:

new List:listOfTasks = list_new();
new Task:t[1];
for(new i = 0; i != 100; ++i) {
    t[0] = task_new();
    task_set_result_ms(t[0], 1, 1000);
    list_add_arr(listOfTasks, t);
}
await Task:pawn_call_native(pawn_nameof(task_all), "l", listOfTasks);

Would you be fine with this solution?

duydang2311 commented 2 years ago

I see, it's a bit unclean. It solves my issue though.

Yes, I'm fine with this. Thank you.

IS4Code commented 2 years ago

I agree that a better-looking solution would be nice. I will think about it. By the way, list_get still works the same if you have array elements in a list, so if you intend to use that list for other things, you don't have to change much of the code.