I'm not sure what's going on here, probably something C++ weirdness with the way it disposes of stack objects or so.
I have a class (MyAwesomeClient) which instantiates a Thread and an EventQueue in its constructor. Then I want to use the queue from my main thread. This hard faults when you press the button:
MyAwesomeClient client;
int main() {
EventQueue queue = *(client.eventQueue());
btn.fall(queue.event(&fall);
}
But this works:
MyAwesomeClient client;
int main() {
EventQueue* queue = client.eventQueue();
btn.fall(queue->event(&fall);
}
(In both cases main() ends, if you keep main() alive with a while loop it works, but who likes that).
@geky
@janjongboom In the first snippet, you make a copy of the event queue and the copy operation is not well handled by the EventQueue class. Using a reference might solve the issue: EventQueue& queue = *(client.eventQueue());.
@geky equeue is copied like a POD, this doesn't seems right. Does it makes sense to copy an event queue or do you think copy construction and copy assignment should be disabled ?
(In both cases main() ends, if you keep main() alive with a while loop it works, but who likes that).
The C and C++ standard likes that. What happens after leaving main is equivalent to calling exit which should clean up the environment and return control to the host. In this case it should destroy the client object and exit the process killing the other threads in the same time. Our runtime doesn't exactly act that way and running threads will continue to run but it is not a reason to promote behavior not expected by the C and C++ standards.
do you think copy construction and copy assignment should be disabled ?
Yep, definitely. We should probably be disabling copying in a lot of classes. I don't think it's reasonable for classes to rely on POD copy unless they are actually structs.
In this case it should destroy the client object and exit the process killing the other threads in the same time.
This is the case with c++11/pthread (actually I think it's undefined behaviour?), but in java/python, exiting main does not terminate threads unless all other threads are daemonized. Since the concept of "terminating" is a bit hazy in embedded systems, we went with allowing main to exit and its resources to be reclaimed.
This was an interesting but, and @pan- hit the nail on the head. Unfortunately the introduction of more first-class classes confuses when to pass by value/pass by pointer. We should probably disable copy constructors much more aggresively.
@geky @pan- I don't know who told me, but I was advised to let main terminate this way, rather than busy-loop at the end of main, so main wouldn't take any resources from other threads.
If the busy loop is not efficient it could waste runtime/power. I think that's the biggest concern. Exiting from main lets us take care of that for you.
@janjongboom Busy loop will consume CPU cycle, adding Thread::wait in the loop is enough to avoid unnecessary CPU cycle consumption. In the mean time the RAM occupied by the main thread stack won't be reused because it is statically allocated (see here).
To avoid useless resources consumption it might be a good thing to think about software composition. It should be possible to use a single event queue instance with different software components and users should have the choice to spawn or not spawn a thread. If it was possible to inject the event queue into the client then it would have been possible to create it in the main thread, inject it into the client and process it in the main thread. Reusing this event queue for other purpose is an added benefits of this solution.
int main() {
EventQueue event_queue;
MyAwesomeClient client(event_queue);
MyAwesomeModule module(event_queue);
btn.fall(event_queue.event(&fall);
event_queue.dispatch();
}
It should be possible to use a single event queue instance with different software components and users should have the choice to spawn or not spawn a thread.
@pan- It is, that's how I designed it. But I want it frictionless for users. So if you don't create an eventqueue yourself it'll just spin up a new one.
See https://developer.mbed.org/teams/sandbox/code/simple-mbed-client/file/816251388f55/simple-mbed-client.h line 38.
Also, is there a Thread::wait(indefinite) ?
There is Thread::wait(osWaitForever)
GitHib issue review: Closed due to inactivity. Please re-file if critical issues found.