i’m writing a custom library in c++ for push back and it heavily relies on multitasking. part of it includes a PID, of which’s output is stored internally, so I would be using multitasking/multithreading to do this. I at one point considered using vex::thread but the documentation is so bad that I doubt I’ll be able to handle bugs if they show up. my main gripe with pros::task is that the syntax is so ugly and unintuitive like what is void* param and what is up with the code to pass params into a task, and I also don’t know how it works in general. meanwhile I understand std::thread pretty well, but i’ve heard that pros being rtos makes it already optimized for vex. also I would be using pros::delay() even if I use thread which I don’t know what will happen if I use them together (I can’t test because I don’t have access to a brain right now since my school’s robotics room is closed for the school year already)
pros::Task is probably better because it’s specifically for PROS. Home » Tutorials » Topical Tutorials » Multitasking | PROS for V5 looks like an ok explanation, though it doesn’t have any examples. I’m pretty sure the void* parameters are just so it can take any type; it doesn’t really matter that much, just use a (void*) cast on your parameters. To make a task just do pros::Task nameOfTaskVariable(nameOfTaskCallback, (void*) parameter); I guess for multiple parameters you could use an array, but for a PID task global variables are fine (that’s what I did last year and it worked well). I have never used std::thread though, so I don’t know if it is better, but I would recommend pros::Task.
My PID class in this case is ran by a function called pidobj.bindTarget(targetVariable, true) so I guess its not the same? Im trying to use a lambda like this:
pros::Task PIDTask(this{this->pidobj.bindTarget(this->targetVariable, true);}
(im binding it to a variable i have support for this in pid)
So back to the question, the C-style syntax is basically that in the function I use void* param and I pass an array of the params into the task function? How do I use the parameters in the original function then?
Sorry, I don’t completely understand your question. When you say true, do you mean there is a variable that default to true? Or that you are calling it with the value true? Also, it looks like you put this in brackets (because it’s a lambda), but it formatted it to a link with no body, so escape the [ and ]'s (with \'s) next time. Anyway, you probably shouldn’t be calling it with a function, and if the second value is a boolean then there might be a way to rework it with a member variable of whatever class pidobj is. Lastly, a tuple (or pair in this case) could work as an alternative if you don’t want to have to change the boolean member variable every time you run the function.
Sorry if that was unclear, I meant that you shouldn’t use a lambda as the parameter for the task callback. You can use a std::pair to hold your two parameters (targetVariable and true), so they can be passed as one parameter (of type std::pair<targetVariableType, bool>). You could alternatively try to refactor your code to turn whatever parameter you are passing true to into a member variable of the pidobj class, but it’s probably neater just to use std::pair. I don’t know why pros tasks don’t just use variadic syntax so you can have multiple parameters, but luckily there are workarounds.
I saw that there was also stuff going on with void* param, do I need to have it somewhere in my bindTarget function? Im assuming the code would be something like pros::Task newtask(pidobj.bindTarget, std::make_pair(&target, true), “working”);?
I thought I couldn’t pass in member functions directly though or smth?
Also would what if I’m storing the tasks in a map,
like:
std::unordered_map<std::string, pros::Task> tasks;
tasks.emplace(“LeftPID”, pros::Task([this] {same stuff as b4});
id ensure its not immediately run because i also added a line in the lambda that waits for a notification, but how would I do this without lambdas providing params
The map thing would work, but you could probably wait for a notification inside the task callback itself if that is the only time it is called. If it isn’t, I don’t know what you would do, sorry. You maybe could wrap the task construction in a lambda itself then run the lambda in the map, but I’m not 100% sure if that would work. You do have to cast the pair to a void parameter though. And you also have to make the parameter in pidobj.bindTarget a void*. Basically it might look like this:
std::unordered_map<std::string>, [sorry I don't know how you would put a lambda type here but you have to do that]> tasks;
tasks.emplace("LeftPID", [this] { return pros::Task(pidobj.bindTarget, (void*) std::make_pair(&target, true), "working"); });
Then the type signature for pidobj.bindTarget would look like this:
i swear this is so convoluted and overengineered at this point. if the lambda thing works i will use it directly because i also want PID to be used normally, outside of the taskmanager, if I so choose to.
also im pretty sure the lambda type is just std::functionpros::Task() with that sample code (i think)
if the way I’m using with that map thing works I’ll just keep it like that because it seems that this way provides better modularity (i also have ramsete and odom and other classes that I haven’t finished yet that have member functions put to a task, and sometimes I might decide to suddenly change a function from being the one sent to a task to be run in another function that does gets sent instead)
it doesn’t ill spend some time rewriting these functions I guess.