Thoughts about Handling of Complexity

Status
Not open for further replies.
Here is the definition of yield() in Arduino (hooks.c) and the only use I can find, in wiring.c function delay().
what about
yield.cpp
in
\arduino-1.8.19\hardware\teensy\avr\cores\teensy4

that reads (external definitions omitted)

Code:
void yield(void) __attribute__ ((weak));
void yield(void)
{
	static uint8_t running=0;
	if (!yield_active_check_flags) return;	// nothing to do
	if (running) return; // TODO: does this need to be atomic?
	running = 1;


	// USB Serial - Add hack to minimize impact...
	if (yield_active_check_flags & YIELD_CHECK_USB_SERIAL) {
		if (Serial.available()) serialEvent();
		if (_serialEvent_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIAL;
	}

#if defined(USB_DUAL_SERIAL) || defined(USB_TRIPLE_SERIAL)
	if (yield_active_check_flags & YIELD_CHECK_USB_SERIALUSB1) {
		if (SerialUSB1.available()) serialEventUSB1();
		if (_serialEventUSB1_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIALUSB1;
	}
#endif
#ifdef USB_TRIPLE_SERIAL
	if (yield_active_check_flags & YIELD_CHECK_USB_SERIALUSB2) {
		if (SerialUSB2.available()) serialEventUSB2();
		if (_serialEventUSB2_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIALUSB2;
	}
#endif

	// Current workaround until integrate with EventResponder.
	if (yield_active_check_flags & YIELD_CHECK_HARDWARE_SERIAL) HardwareSerial::processSerialEventsList();

	running = 0;
	if (yield_active_check_flags & YIELD_CHECK_EVENT_RESPONDER) EventResponder::runFromYield();
	
};
 
here is a Teensy forum and Arduino implementations are for me no metric

Teensy is Arduino-compatible. The point I was trying to make is that yield() was included in Arduino with a purpose, according to those comments. Teensy implements its own yield() that supersedes the Arduino yield() and implements EventResponder logic. Teensy's yield() is declared "weak", so when yield() is defined in a cooperative RTOS, it can supersede the Teensy yield(). I have been thinking of EventResponder as an alternative to an RTOS, but Paul has made the point that EventResponder and an RTOS could coexist. That's what we are discussing.
 
I have been thinking of EventResponder as an alternative to an RTOS, but Paul has made the point that EventResponder and an RTOS could coexist.

The word "coexist" leaves a lot of opportunity for misunderstanding!

Just in case there's any confusion, in a hypothetical RTOS scenario, the non-RTOS EventResponder implementation we have today would be deleted (or not compiled by #ifdef or other config) and replaced by a compatibility layer which uses the RTOS's mailboxes or similar features to allow libraries using EventResponder to work as expected by making use of the RTOS's intended way.

This hypothetical scenario, if it happens, is probably a long way off. But even though it may be years away, I am still curious to hear well reasoned opinion about why EventResponder current API might be an obstacle to someday being implemented with RTOS mailbox/queue/notification/semaphore. If there is some aspect of EventResponder which can't work well when (hypothetically) removed and replaced with a thin compatibility wrapper around RTOS features, I am willing to consider paring back some EventResponder features.
 
Many of the messages on this thread are about missed optimization, rather than discussing the originally intended topic of how to manage complexity (of concurrent tasks) or about how EventResponder, RTOS, or other software may or may not support that goal.

Just in case there may be any misunderstanding, I consider working but less than fully optimized code to be a low priority, especially when the performance is reasonably good enough for most applications. I have been burned many times by attempted optimizations done quickly because they seemed simple or obvious, but then ended up having unintended effects or subtle changes to behavior. I have saved links to several messages about specific optimization issues on my low priority list. At this time, many other issues are considered high priority, such as the newer MacOS crashing with teensy_serialmon, and unfinished work on full MTP support. I know some people feel very strongly about these low-level optimizations. Those sorts of improvements will happen, but I'm not going to risk doing them "quickly" while so many other far more important issues and features are in need of attention.
 
Just in case there's any confusion, in a hypothetical RTOS scenario, the non-RTOS EventResponder implementation we have today would be deleted (or not compiled by #ifdef or other config) and replaced by a compatibility layer which uses the RTOS's mailboxes or similar features to allow libraries using EventResponder to work as expected by making use of the RTOS's intended way.

I will spend some time to understand EventResponder better and give you my thoughts. For now, I plan to continue testing with a cooperative executive with yield() that simply supersedes Teensy's yield(). I'm not sure if that disables EventResponder entirely, but it does disable whatever event processing is done in Teensy's yield(), right?
 
For now, I plan to continue testing with a cooperative executive with yield() that simply supersedes Teensy's yield(). I'm not sure if that disables EventResponder entirely, but it does disable whatever event processing is done in Teensy's yield(), right?

Yes, if you override yield(), EventResponder will no longer respond to events. But if you want that behavior, just copy the last line from Teensy's yield() into your own.
 
Additive - @luni64 seems to have a library:
https://github.com/luni64/TeensyHelpers
that has the ability to override yield and use EventResponder together:
Code:
#include "attachYieldFunc.h"
#include "EventResponder.h"

void attachYieldFunc(yieldFunc_t _yieldFunc) // pass a pointer to the function you want to be called from yield
{
  static yieldFunc_t yieldFunc = _yieldFunc; // store the passed in function pointer
  static EventResponder er;                  // define a new EventResponder which will handle the calls.

  er.attach([](EventResponderRef r) {        // we can not directly attach our function to the responder since we need to retrigger the repsonder
    yieldFunc();                             // instead we attach an inline defined relay function as lambda expression
    r.triggerEvent();                        // the relay calls our function and afterwards triggers the responder to schedule the next call.
  });

  er.triggerEvent();                         // to start the call chain we need to trigger the responder once
}

I have used it without issue...
Thoughts?
 
Status
Not open for further replies.
Back
Top