Skip to content

Commit 7c80bea

Browse files
authored
Update README.md
1 parent d6d97a7 commit 7c80bea

File tree

1 file changed

+8
-226
lines changed

1 file changed

+8
-226
lines changed

README.md

Lines changed: 8 additions & 226 deletions
Original file line numberDiff line numberDiff line change
@@ -13,51 +13,23 @@
1313

1414
[![Discord](https://img.shields.io/discord/960639692213190719?style=plastic&color=purple&logo=discord)](https://discord.gg/FBVKJTaY)
1515

16-
The SystemCore provides a lightweight and highly structured foundation for C++ applications, combining a minimalistic design with a powerful debugging and monitoring system.
16+
This C++ framework provides a lightweight and highly structured foundation for C++ applications, combining a minimalistic design with a powerful debugging and monitoring system.
1717

1818
It allows you to focus entirely on your application's logic without being restricted in your coding style. Similar to LaTeX, it separates structure from content - enabling faster, more reliable development, even for complex systems.
1919

2020
## Advantages
2121

22-
- **Reduced boilerplate code** > Just add lines of code, which are beneficial for the tasks
23-
- **Relieved memory allocations** > Lifetime of requested memory very often matches the lifetime of the task itself, which is monitored. Therefore reducing the risk of memory leaks!
24-
- **Application level debugging** > Spend less time on searching for strange bugs due to the improved overview of the system. Just focus on your tasks
25-
- **Increased productivity** > A long-term relaxed and still speedy coding experience for *everyone*
26-
- **Quality control** > Your code can be characterized and rated instead of calling it "clean" or "dirty"
27-
- **Simple and useful documentation** > The structure allows for the creation of a visual description of your project which can be understood by tech and non-tech people.
28-
- **Increased maintainability** > You get an easy-to-read code at any time. This remains true regardless of the size or complexity of the system. Use a set of simple instructions to reach the target architecture starting from the current state
29-
- **Big support range** > Starting from small to very complex systems
22+
- **Minimal boilerplate** > Focus purely on task-specific logic
23+
- **Recursive process structure** > Uniform system architecture from simple to complex
24+
- **Integrated debugging** > Visual process tree, logs and command interface over TCP
25+
- **Memory-safe design** > Aligned lifetimes of processes and data, reducing leaks
26+
- **Cross-platform** > Windows, Linux, MacOS, FreeBSD, uC (STM32, ESP32, ARM, RISC-V)
3027

3128
## Requirements
3229

3330
- C++ standard as low as C++11 can be used
3431
- On Microcontrollers: Minimum of 32k flash memory
3532

36-
## Status
37-
38-
- Mature code created in 2018
39-
- Finished: Release pending. ETA: July 2025
40-
41-
## Supported Targets
42-
43-
The code of this repository is already very mature and has been successfully used on the following systems
44-
45-
- Windows
46-
- MinGW
47-
- MSVC
48-
- Linux / Raspberry Pi
49-
- GCC
50-
- MacOS
51-
- FreeBSD
52-
- ESP32
53-
- STM32
54-
- RISC-V
55-
- ARM
56-
57-
## Learn how to use it
58-
59-
The [Tutorials](https://github.com/NoOrientationProgramming/NopTutorials) provide more information on how to delve into this wonderful (recursive) world ..
60-
6133
### How to add to your project
6234

6335
`git submodule add https://github.com/NoOrientationProgramming/SystemCore.git`
@@ -68,196 +40,6 @@ To implement a new process you can use the provided shell scripts on linux: [cpp
6840

6941
Or just create your own..
7042

71-
## Intro
72-
73-
The key element consists of a single file named Processing.cpp. This file contains an abstract C++ class, which handles the processing of tasks within larger systems. The class serves as the foundation for implementing concrete user processes.
74-
75-
<p align="center">
76-
<kbd>
77-
<img src="https://raw.githubusercontent.com/NoOrientationProgramming/NopTutorials/main/doc/system/core-dependencies.svg" style="max-width:100%"/>
78-
</kbd>
79-
</p>
80-
81-
When using the SystemCore the entire system structure is recursive. This has a big and very beneficial impact during development, runtime, documentation and communication with other team members independent of their background.
82-
83-
There is no low- or high-level code. Just **one essential looped function**: `process()` .. everywhere
84-
85-
```cpp
86-
Success Supervising::process()
87-
{
88-
++mCounter; // do something wild
89-
return Pending;
90-
}
91-
```
92-
93-
## Debugging
94-
95-
Only a few lines of code are necessary to get a powerful debugging service integrated directly into your application. In this case we use the **optional** function `initialize()`
96-
97-
```cpp
98-
Success Supervising::initialize()
99-
{
100-
SystemDebugging *pDbg;
101-
102-
pDbg = SystemDebugging::create(this);
103-
if (!pDbg)
104-
return procErrLog(-1, "could not create process");
105-
106-
start(pDbg);
107-
108-
return Positive;
109-
}
110-
```
111-
112-
After that, you can connect to three different TCP channels.
113-
114-
**Optionally**: Each process can show some useful stuff by creating a `processInfo()` function. The rest of your code is unaffected.
115-
116-
```cpp
117-
void Supervising::processInfo(char *pBuf, char *pBufEnd)
118-
{
119-
dInfo("Counter\t\t%d", mCounter);
120-
}
121-
```
122-
123-
### Channel 1 - Process Tree
124-
125-
Just one quick look is needed to see how your **entire** system is doing.
126-
127-
<p align="center">
128-
<kbd>
129-
<img src="https://raw.githubusercontent.com/NoOrientationProgramming/NopTutorials/main/doc/channel-dbg-1_tree-proc.png" style="max-width:100%"/>
130-
</kbd>
131-
</p>
132-
133-
### Channel 2 - Process Log
134-
135-
What is happening. But much more important: **Who** is doing what and when
136-
137-
<p align="center">
138-
<kbd>
139-
<img src="https://raw.githubusercontent.com/NoOrientationProgramming/NopTutorials/main/doc/channel-dbg-2_log.png"/>
140-
</kbd>
141-
</p>
142-
143-
### Channel 3 - Command interface
144-
145-
Do you want to trigger something? Just register a command **anywhere** in your application.
146-
147-
```cpp
148-
void yourCommand(char *pArgs, char *pBuf, char *pBufEnd)
149-
{
150-
dInfo("Executed with '%s'", pArgs);
151-
}
152-
153-
Success Supervising::initialize()
154-
{
155-
...
156-
157-
cmdReg("test", yourCommand);
158-
159-
return Positive;
160-
}
161-
```
162-
163-
<p align="center">
164-
<kbd>
165-
<img src="https://raw.githubusercontent.com/NoOrientationProgramming/NopTutorials/main/doc/channel-dbg-3_cmd.png" style="max-width:100%"/>
166-
</kbd>
167-
</p>
168-
169-
## Waiting for a child process and consuming its result
170-
171-
After a process has been started, it simply continues running in the background and completes its work. The parent process itself decides when to check for the completion of the activity. Although a callback can also be implemented as an alternative, we would advise against it. When callbacks are used, the parent process must deal with the 'interruption' at all times and must not be negatively affected by it. It's easier to simply ask the child process occasionally. Even if the child process has already finished the activity, the parent process is not obligated to accept the data. Thus, the child process even acts as a buffer for the achieved results. This is very practical and simplifies development.
172-
173-
Here we already see an important distinction between functions and processes. A function is an immediate mapping between its inputs and outputs. Outputs could be divided into an error code (&rarr; success) and a result. The success of a function can thus be either negative (<0) or positive (1). Negative events should preferably always be processed first to avoid nesting of program code. This way, developers read the code linearly from top to bottom, simplifying development further. Now, a process is very similar to a function. However, the mapping does not occur instantaneously but takes too much time to wait for the result. Therefore, the success of a process has an additional state: Pending (0). Only when a process has completed its activity is the success either positive or any negative value. Processes can be divided based on the type of delay into
174-
175-
1. Communication-bound processes
176-
1. Work-bound processes
177-
178-
The abstract core class solely implements the handling of success. You are free to choose the result a specific process delivers.
179-
180-
Another difference between functions and processes is that the result of functions is passed directly and immediately by the compiler. The function can then be dismantled immediately. All of this is accomplished by the compiler and with the help of the computer system's stack. However, with processes, the user decides when the data is processed. For this fundamental reason, the user must also take care of initiating the destruction procedure at least by themselves. Here too, the abstract process class helps us to properly shut down the specific user process. One last important piece of information is that processes cannot be implemented through the usual stack processing, as the lifespan of a process can be arbitrarily long. Therefore, all processes reside on the heap.
181-
182-
If the lifespan of the required data matches that of a process, then we have the advantage that the data does not need to be separately requested using malloc(). This is usually the case and reduces the risk of memory leaks, thereby making software development safer in general.
183-
184-
```cpp
185-
Success Supervising::process()
186-
{
187-
Success success;
188-
189-
// Wait
190-
success = mpChild->success();
191-
if (success == Pending)
192-
return Pending;
193-
194-
// Check error
195-
if (success != Positive)
196-
return procErrLog(-1, "my child process failed");
197-
198-
// Consume result
199-
mData = mpChild->data();
200-
201-
// Repel
202-
repel(mpChild);
203-
mpChild = NULL;
204-
205-
return Positive;
206-
}
207-
```
208-
209-
210-
## Multithreading
211-
212-
If two or more work-bound processes are concurrently operated and the CPU has multiple cores, it is useful to parallelize their execution. But isn't parallelization entirely difficult? Actually not.. Just a single bit is enough to start a process in a new thread. The waiting for the completion of a process remains the same. Only in some cases does the transfer of data from one thread to another need to be done with a synchronization mechanism of your choice (e.g., mutex). Thanks to the good overview in the system, however, this also becomes child's play.
213-
214-
```cpp
215-
Success Supervising::initialize()
216-
{
217-
mpChild = IntenseCalculating::create();
218-
if (!mpChild)
219-
return procErrLog(-1, "could not create process");
220-
221-
start(mpChild, DrivenByNewInternalDriver);
222-
223-
return Positive;
224-
}
225-
```
226-
If there are many of these work-bound processes, the use of a thread pool could also be practical. Here too, the waiting procedure remains the same. This method of starting a process can also be used on microcontrollers to drive a process in interrupts or in general to implement intelligent scheduling mechanisms.
227-
228-
```cpp
229-
Success Supervising::initialize()
230-
{
231-
mpChild = IntenseCalculating::create();
232-
if (!mpChild)
233-
return procErrLog(-1, "could not create process");
234-
235-
start(mpChild, DrivenByExternalDriver);
236-
ThreadPooling::procAdd(mpChild);
237-
238-
return Positive;
239-
}
240-
```
241-
242-
## Why is recursion so important?
243-
244-
TODO
245-
- Always the same => Realizes the KISS prinziple
246-
- Code is self-similar => Refactoring is done by just moving code around => No structural changes needed
247-
248-
<p align="center">
249-
<kbd>
250-
<img src="https://raw.githubusercontent.com/NoOrientationProgramming/NopTutorials/main/doc/system/recursion.svg" style="width:700px;max-width:100%"/>
251-
</kbd>
252-
</p>
253-
254-
## FAQ
255-
256-
Q: Isn't this some kind of operating system?
257-
A: No. There is no such thing as an operating system. Every piece of software should be structured this way.
258-
259-
Q: Aren't these micro services?
260-
A: Not exactly. These processes reside in the application itself. They are more similar to Go-/co-routines, tasklets or async-await structures.
43+
## Learn how to use it
26144

262-
Q: Isn't it ineffective to poll for the result of a child process instead of using callbacks and event driven design?
263-
A: No. Because: TODO
45+
The [Tutorials](https://github.com/NoOrientationProgramming/NopTutorials) provide more information on how to delve into this wonderful (recursive) world ..

0 commit comments

Comments
 (0)