Using try and catch for cooperative multitasking

Im working on a very big complex project and to reduce complexity ive implemented a scheduler that calls functions at a given rate dynamically. Ive been wanting to implement a delay function into the scheduler so a task can suspend itself for a given time and give the time to other tasks ans at the end continue from that suspend function call. For this ill need context switching and ive been contemplating if I should use setjmp and longjmp to save the context when switching tasks if the suspend is called by the task itsself, but a lot of people dont recommend it because if i say create a class in the task that allocates data using new then the destructor calling delete will not be called (e.g. String class). As far as i understand this is solved with using try, throw and catch, but i dont know if its even possible to use them to continue where the function was called.

Is this possible and if i really do continue the suspend function so that the task is guaranteed to return normally then i could still use setjmp and longjmp and wont have problems with leaks?

Hello
I guess we are talking about non-preemptive scheduling. In this way you can use a simple taskDelay() function.

Which chip or board?
Most AVRs have an unfortunately large ratio of “context that should be saved” to “total RAM” (which applies no matter how you go about saving the context.)

Sorry if there was a missunderstanding but im not use freertos or similar, i dont have a taskDelay() function. I developed the scheduler myself and want to implement something like taskDelay() into my scheduler. My question was if its possible to use something like setjmp and longjmp to implement context switching safely.

Im using a teensy 4.0. I think it would have enough RAM for this.
Im hoping to support other boards like stm32f4 or esp32. Something 8bit like the uno dont have enough processing for this project anyway.

Why would anyone want to use something like that on an ESP32 when it’s already running FreeRTOS? Adding a home-brew scheduler on top of a well-established, multi-tasking OS makes no sense to me.

Because the framework im building is supposed to support any board fast enough (e.g. teensy boards or stm32). They dont have RTOS and so im building a simple scheduler so you dont have to redesign everything, just simply upload to another board after changing pin definitions. Also this scheduler is object oriented, meaning simply create a class and inheret from the scheduler class and it will automatically take care of adding it to the scheduler on construction. This is way simpler than Freertos and it can run on any board.

Quick & dirty multitasking that runs on anything.

Create a class (idler) that inherits from link list. (Maybe create linked list too) To this class add the method …

virtual void idle(void);

Now, create a class that manages this linked list with a global function…

void idle(void);

That whenever its called, just runs down the linked list calling each item’s idle(); method. Call this function in your loop() function.

Now, anything built on the idler class gets a little time to do something each time you go through your loop.

It works! I know it works because I use it every day. You can find it in LC_baseTools. Installable from your handy dandy library manager of the Arduino IDE.

-jim lee

Thanks for the info. Thats basically what my scheduler already does. As said i want to add a function that will delay the current task and give other tasks its time.
Maybe take a look at my library: GitHub - ChSt98/Simple-Schedule: This makes use of my Interval-Control and Chain-Buffer libraries to implement a class that can run many tasks similar to multithreading at given rates and priorities.

Well in mine I have a sleep() function that halts the loop() just like delay(). But in spends it time calling idle() keeping all the other threads running.

-jim lee

I believe “conventional wisdom” is that you can’t do a full context switch in pure C or C++.

I think you should bite the bullet and write or find the assembly language suspend() (save context and run the scheduler, called from tasks) and resume() (called from scheduler, restores a task context and run it) functions - they’re probably only about a dozen lines each if you’re not worried about multiple stack pointers and such.
(RTOSes tend to combine the two functions into a “switch task” Handler, but that shouldn’t stop you from using, say, the CMSIS-RTOS code as an example. ( CMSIS/HAL_CM0.s at master · ARM-software/CMSIS · GitHub )

Sounds like you want at least coroutines and multiple stacks.

I have tried that but that creates timing problems if multiple tasks call sleep. For example if a task wants to delay for 5ms and during this delay (while running other tasks) another calls delay for 10ms then the first one will delay for 15ms because you either have to return from the second one earlier so either the second delay is cut short or have the first delay run longer. We need context switching to return to the first delay without returning the second delay

Thanks for an actual good piece of information. I guess that might be the only way, although ill keep looking for another solution.
As far as i understand assembly is specific for an instruction set and therefore specific for a processor (or family). This creates problems as i want this framework to be mostly compatible with all boards.
Im only trying to switch between tasks (switching to another function when suspend is called) not cutting them off, so im hoping with this constraint ill find a solutionand hope its possible with setjmp and longjmp.

Nope, you can’t do task switching on one stack. longjmp only moves back on the current stack.

As I understand it longjmp is not compatible with C++ anyway as it doesn’t handle destructors for locally declared objects.

A coroutine system needs a context-switching piece of assembler, and code to manage
multiple stacks. For real time tasks you also need a way to switch stacks from an ISR,
and some scheduling code.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.