Skip to content

Commit 26519d9

Browse files
committed
#4 - Added more info to README.md
1 parent 9592096 commit 26519d9

File tree

1 file changed

+62
-2
lines changed

1 file changed

+62
-2
lines changed

README.md

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ MyFirstThread::OnLoop() - Thread 3 - On CPU 0, Counter = 2
229229
MyFirstThread::OnLoop() - Thread 2 - On CPU 1, Counter = 2
230230
```
231231

232-
The explicit maximum number of *ESPresio* `Thread`s supported by the library is 256, however the *practical limit* depends entirely on the specifications of your microcontroller. It's almost certainly going to be considerably lower than 256!
232+
The explicit maximum number of *ESPressio* `Thread`s supported by the library is 256, however the *practical limit* depends entirely on the specifications of your microcontroller. It's almost certainly going to be considerably lower than 256!
233233

234234
### The Thread Manager
235235
In the previous example, you'll see that we manually called `Initialize()` on each instance of `MyFirstThread`.
@@ -254,4 +254,64 @@ void setup() {
254254
Manager::Initialize();
255255
}
256256
```
257-
Now, all three of our `MyFirstThread` instances will start exactly as they did before, but we didn't have to explicitly `Initialize()` each of them separately.
257+
Now, all three of our `MyFirstThread` instances will start exactly as they did before, but we didn't have to explicitly `Initialize()` each of them separately.
258+
259+
### Automated Garbage Collection
260+
It is quite common to have `Thread`s with non-permanent lifetimes, such as *Worker Threads* (less common with microcontrollers, but not unheard of).
261+
262+
*ESPressio* Threads provides a means of leveraging fully-automatic *Garbage Collection* for your `Thread`s once they've `Terminated`.
263+
264+
Let's modify our previous example to take advantage of it, and let's add some *finality* to `MyFirstThread` so that it will automatically `Terminate` when it has done its "work":
265+
```cpp
266+
class MyFirstThread : public Thread {
267+
private:
268+
int _counter = 0;
269+
protected:
270+
void OnInitialization() override {
271+
// Anything we need to do here prior to the Thread's Loop sstarting
272+
}
273+
274+
void OnLoop() override {
275+
_counter++; // Increment the counter
276+
277+
// Let's display some information about our Thread...
278+
Serial.printf("MyFirstThread::OnLoop() - Thread #%d - On CPU %d, Counter = %d", GetThreadID(), xPortGetCoreID(), _counter);
279+
280+
if (_counter == 10) {
281+
Termiante(); // This will Terminate the Thread
282+
}
283+
284+
delay(1000); // Let's let this Thread wait for 1 second before it loops around again
285+
}
286+
public:
287+
MyFirstThread(bool freeOnTerminate) : Thread(freeOnTerminate) {}
288+
};
289+
```
290+
Okay, so our `MyFirstThread` class has been updated so that it will automatically `Terminate` when the `_counter` reaches `10`.
291+
292+
I've also added a public *Constructor* to expose the overloaded constructor on `Thread`, which provides the optional `freeOnTerminate` parameter we shall be using in a moment.
293+
294+
Let's modify the way we define the *Instances* of `MyFirstThread` so that we can leverage Automatic Garbage Collection:
295+
```cpp
296+
MyFirstThread* thread1, thread2, thread3;
297+
298+
void setup() {
299+
Serial.begin(115200);
300+
301+
// Create our Threads (passing `true` to the constructor for "FreeOnTerminate")
302+
thread1 = new MyFirstThread(true);
303+
thread2 = new MyFirstThread(true);
304+
thread3 = new MyFirstThread(true);
305+
306+
delay(500); // Small delay just so that the thread doesn't start before the Serial Monitor is ready
307+
308+
Manager::Initialize();
309+
}
310+
```
311+
Now, when you run this program, each of the three instances of `MyFirstThread` will loop precisely 10 times, output their entries to the Serial console, then each of them will automatically `Terminate()`.
312+
313+
At that moment, the *Automatic Garbage Collector* will be awoken, and will take responsibility for purging the unwanted instances from our device's active memory.
314+
315+
>It is important to understand when it's appropriate to take advantage of Automatic Garbage Collection, and when you should manually manage the memory of your `Thread`s.
316+
317+
It's also good to know that the *Automatic Garbage Collector* is a "good citizen" and doesn't take up undue memory or clock cycles when it doesn't have any garbage to collect.

0 commit comments

Comments
 (0)