I originally posted this as a question, but seeing as there are many different opinions on the matter, I'm re-posting it as a discussion. Here was the original question:
I'm working on a multithreaded project using the mbed-rtos library, and I'm wondering whether it's preferable to keep the variables specific to each thread within the thread function itself, or make them "static". By "static", I mean put each thread in a separate file and declare its variables in an anonymous namespace so they're external to the thread function itself, but still somewhat concealed from the rest of the application.
As an example, one of the threads in my project, USB_Thread, communicates with a PC using the USBHID class in the USBDevice library. In addition to the USBHID object, it also uses a 1KB buffer to send and receive chunks of data. Which method of handling these variables is preferred?
Method A: "static" variables (default stack size)
namespace {
USBHID hid(64, 64);
char buffer[1024];
}
void USB_Thread(void const *args) {
while (true) {
//Do USB stuff!!!
}
}
Method B: local variables (larger stack size)
void USB_Thread(void const *args) {
USBHID hid(64, 64);
char buffer[1024];
while (true) {
//Do USB stuff!!!
}
}
It seems to me that keeping a thread's variables internal would make estimating your memory consumption easier, while also providing better encapsulation.
And here is the discussion that commenced in the comments:
With internal, do you mean local? For a project of my own I went for exactly the opposite (at least for the buffers/larger stuff), for the same reason: It is a bit high on memory, and that way the compiler tells me how much RAM memory I am using with my buffers.
Yes, local as in method B. Interesting... I would have thought estimating your memory usage would be easier with local variables since you can see what each thread will use simply by looking at the stack size you gave it when you created it... My other thought is that method B would make your threads more "portable", as in you could create additional instances without having to copy and paste static variables.
From the code it might indeed be easier, then again estimating thread sizes is irritating imo :). It is true for portability it is better if your thread contains evertyhing.
@Neil, what if you create a method C, allocate those objects within a thread on a heap?
@Erik: Isn't it though? I hate estimating a stack size for threads! It would be nice if compilers were smart enough to analyze a thread's maximum stack depth based on every possible code path at compile time. Wishful thinking I know...
@Martin: Thanks, but I try to avoid using the heap on microcontrollers unless I absolutely have to. Besides, last I checked heap/stack collision detection was broken in the regular SDK let alone when the RTOS was used.
So my question is, what's everybody's opinion on this matter? Is there a hard and fast rule about where to put your thread's variables when using an RTOS? I'm currently of the opinion that any thread-specific variables that aren't shared with the rest of the program should be local automatic variables within the thread function, regardless of size. But I'm new at this, so I might be wrong.
I originally posted this as a question, but seeing as there are many different opinions on the matter, I'm re-posting it as a discussion. Here was the original question:
I'm working on a multithreaded project using the mbed-rtos library, and I'm wondering whether it's preferable to keep the variables specific to each thread within the thread function itself, or make them "static". By "static", I mean put each thread in a separate file and declare its variables in an anonymous namespace so they're external to the thread function itself, but still somewhat concealed from the rest of the application.
As an example, one of the threads in my project, USB_Thread, communicates with a PC using the USBHID class in the USBDevice library. In addition to the USBHID object, it also uses a 1KB buffer to send and receive chunks of data. Which method of handling these variables is preferred?
Method A: "static" variables (default stack size)
Method B: local variables (larger stack size)
It seems to me that keeping a thread's variables internal would make estimating your memory consumption easier, while also providing better encapsulation.
And here is the discussion that commenced in the comments:
With internal, do you mean local? For a project of my own I went for exactly the opposite (at least for the buffers/larger stuff), for the same reason: It is a bit high on memory, and that way the compiler tells me how much RAM memory I am using with my buffers.
Yes, local as in method B. Interesting... I would have thought estimating your memory usage would be easier with local variables since you can see what each thread will use simply by looking at the stack size you gave it when you created it... My other thought is that method B would make your threads more "portable", as in you could create additional instances without having to copy and paste static variables.
From the code it might indeed be easier, then again estimating thread sizes is irritating imo :). It is true for portability it is better if your thread contains evertyhing.
@Neil, what if you create a method C, allocate those objects within a thread on a heap?
@Erik: Isn't it though? I hate estimating a stack size for threads! It would be nice if compilers were smart enough to analyze a thread's maximum stack depth based on every possible code path at compile time. Wishful thinking I know...
@Martin: Thanks, but I try to avoid using the heap on microcontrollers unless I absolutely have to. Besides, last I checked heap/stack collision detection was broken in the regular SDK let alone when the RTOS was used.
So my question is, what's everybody's opinion on this matter? Is there a hard and fast rule about where to put your thread's variables when using an RTOS? I'm currently of the opinion that any thread-specific variables that aren't shared with the rest of the program should be local automatic variables within the thread function, regardless of size. But I'm new at this, so I might be wrong.