C++ is growing incredible fast and it will continue in next future. To get more complete library, variadic templates, lambdas, string-view, smart-pointers, move semantic, concurrency, files, initializer lists, type inference…
To learn, to practice new features from C++, to have a toolset to complete C++ library, to program in C++ with less "undefined behavior"
Once upon a time…
I wrote some rules and C++ tools to help colleagues with no experience in C++ to survive with it.
But later, I discover It was pleasant to work with these tools, safe, easy to use, low dependencies… I’m also very interested in making safe programs (no crashes)
This toolset compiles with modern C++ (and it will be), but is not fully idiomatic. Some of the tools has been added to C++ standard library (regular expressions, tuples, date time…), and there are new ways to solve most of the problems. It was time to play and learn with new C++ and these concepts
Let’s enjoy and learn new C++. Let’s have toolkit working with new C++. Let’s create your basic tools to develop from scratch. It’s a great excuse!!!
I loved my CountPtr implementation, my old tuples worked fine… Now both will be replaced by std implementation. Other tools, will be rewrited with modern C++.
I know It will be necessary to update frequently some parts of the library in order to keep updated to last versions of C++. It’s part of the game.
Previously I wrote the documentation with asciidoc, muse over emacs and doxys on some projects. Now I’m going to add doxygen (I’m not a fan of these kind of tools, I prefer something like asciidoc or emacs/muse, but it’s a standard).
I’m not focused on radical performance, I prefer:
-
Safety
-
I don’t like undefined behaviour
-
I don’t like crashes due to programming mistakes. C++ could be a dangerous language. It’s easy to have crashes, I want a library protecting and helping the programmer.
-
Message driven programming
-
If we have a failure processing a message, usually is better to inform about it and continue with next one.
-
KISS and YAGNI
-
Easy to use API (the implementation could be complex)
-
I will introduce features as soon I will require
-
No thousands of options, better few options, easy to use and less verbose (try to compose, please)
-
Make difficult to produce "write only code" using this library. The code using this library…
-
has to be easy to read
-
writting simplicity is less important
-
Small
-
This is about having basic features, not incredible possibilities. There are great C++ libraries for that.
-
Portability (win/linux)
-
zero dependency
-
C++ doesn’t have a standard dependency tool. It is going to be a small library, complex dependencies will be avoided
-
Easy to compile
Performance is desired but not over safety, easy api…
Note
|
Important working on a team. |
C++ is not the safest programming language in the world. In fact, it’s easy to produce undefined behaviour working with C++.
Warning
|
undefined behavior is all arround you… |
Working in a team (generally different levels), it’s desirable to have safety in mind.
C++ is focused on performance and low level abstractions.
In C++ you can have undefined behaviour for several errors.
Most of these undefined behaviours ends with a program crash.
My aim is to reduce program crashes. I want my programs keep running even after an error.
I don’t try to transform C++ in Erlang or Elixir. And yes, I know that Rust is the tool which try to be efficient, close to metal and safe.
I enjoy learning and practicing Erlang/elixir. I learned several concepts with them. Rust looks quite interesting and promising, we will see what happens in the future, meanwhile, I’m learning and following it.
Crash and errors reasons and how to deal with them…
Crash | Managed with… |
---|---|
Non trapped exception |
message driven programming with main message loop trapping all exceptions |
Null pointer |
generate an exception is better to undefined behaviour (usually crash) |
Dangling pointers |
smart pointers and signal slot. Please RAII everywhere <br> No arithmetic pointers |
Memory leaks |
same as previous one |
Resource management |
memory is not the only resource. RAII everywhere |
Invalid iterators |
Exception is better than undefined behaviour (even for deterministic false positives, fail fast) |
Infinite loops |
reduce loops usage |
Consuming all resources |
_ |
Integer zero division |
throw an exception |
Concurrency and parallelism |
reduce or remove parallelism <br> do not share, message passing |
Float comparison |
don’t do it and request for help to the compiler |
Race conditions |
Share nothing, send messages, high level concurrency tools, or… reduce parallelism |
I have next flags activated on gcc/g++
-std={cpp}14 -O0 -g -Werror -Wall -W -Wundef -Wpointer-arith -Wfloat-equal -fexceptions -Winit-self -Wconversion -Wclobbered -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wsign-compare -Wtype-limits -Wuninitialized -Wno-unused-result -Wnon-virtual-dtor -Wreorder -Woverloaded-virtual -Wsign-promo -Winit-self -Wignored-qualifiers -Wmissing-include-dirs -Wswitch-default -Wswitch-enum -Wshadow -Wcast-qual -Wwrite-strings -Wconversion -time
jle will also provide a base exception class with stack. You will have to fill the stack manually (this is C++)
Note
|
Important working on a team. |
Concurrency is great. Why?
-
Several problems are easy to solve in a concurrent way
-
Avoid active waiting
-
Use all machine cores (better performance)
-
Avoid full program stop waiting for a task
I love concurrency and parallelism, but I love it with languages like Erlang and Elixir, designed to work great with this concept.
ADA and Rust, would be interesting candidates.
But Python, Ruby not due to GIL, GVL, to start with.
C, C++, Java, C#… aren’t good for concurrency. They lack of high level abstractions and they are not designed to avoid race conditions.
You could use different strategies to avoid concurrency problems, like resources locking ordering. All these kind of strategies, reduce the concurrency and the code continues being difficult to maintain.
You could have a great thread safe code working perfect. But some day, you could call a different function and your code, could not be thread safe anymore. This will be difficult to detect and very difficult to solve.
The majority of Chrome code is intended to be single-threaded, where this presents no problem. When in multi-threaded code, however, the right answer is usually to use a base::LazyInstance.
http://www.chromium.org/developers/coding-style/cpp-dos-and-donts
The right way to deal with concurrency is… "share nothing, message passing" (actor model and csp)
Therefore, threads are not a good idea. In Rust, could be an option because the compiler will forbid you to share things between threads.
Computer is a state machine. Threads are for people who can’t program state machines
Message passing in an ansynchronous way, also generates new problems. Many times we need a synchronous communication. Erlang/Elixir solves it.
As Alan Cox said, you can develop state machines. In fact, all non trivial process, has to deal with states.
I will create an external DSL to write declarative finite state machines.
For asynchronous task like reading a socket.
OK, do it, wait for asynchronous events on a dedicated thread.
You can even execute your code in a dedicated thread, but not simultaneously with other code of your own program.
Doing it, will be as easy as adding a line JLE_ASYNCHR
Do it with processes. You can communicate them with pipes, rabbitmq, RESTful…
This way, you can use all cores and even all available machines.
Concurrency with processes… is share nothing communicate with messages. The right way.
I will add support for RESTfull, rabbitmq, execute process and communicate with pipes.
#include <iostream>
#include "core/alarm.h"
#include "core/signal_slot.hpp"
#include "core/timer.h"
// Function to receive timer events
void test_timer(void)
{
std::cout << jle::chrono::now() << " on_timer in fucntion" << std::endl;
}
int main()
{
std::cout << jle::chrono::now() << " starting..." << std::endl;
// configure timer for function
JLE_TIMER_FUNCT(1s, test_timer);
// program stop after 10s
JLE_ONE_SHOOT_FUNCT(10s, [](){ std::cout << "CLOSING... "; jle::timer::stop_main_loop();});
jle::timer::start_main_loop();
}
void jle::alarm_msg(const jle::alarm& al)
{
std::cout << al << std::endl;
}
Folder | Description |
---|---|
src |
source code |
src/core |
Basic tools (signal-slot, strings…) |
src/net |
net source |
src/xxx |
pending |
bin |
generated bins |
doc |
generated doc |
test |
source for unit testing |
examples |
ex source |
data |
general data |
Next commands are provided
make make help make libs make doc make test make compile_test make compile_examples
I don’t plan to use it daily. I will write it simultaneously with… web applications with dart, polymer, enjoining Elixir, learning from Go and Rust, following Scala…
In any case, I plan to follow next order (more or less)…
-
(done) smart_pointer
-
(done) just a safe wrapper over stl, but safer
-
-
(done) signal_slot
-
(90%) date_time
-
(done) string tools
-
(done) exception type with stack
-
(done) double safe comparison
-
(done) safe containers
-
(done) nullable type, it is a wrapper from std::experimental::optional
-
(done) tuples ostream <<
-
(50%) Http REST support (pending routes and client)
-
(done) integer div 0 protection
-
(90%) Message driven programming oriented: synchr, timers
-
(done) parallelism control helper
-
(done) LL(n) parser
-
(done) qt gui for LL(n)
-
LL(n) parser documentation
-
(done) IDL class generation base and example
-
IDL class generation
-
stream
-
yaml
-
json
-
bson
-
less operator
-
equal operator
-
…
-
-
IDL documentation
-
.ini and .cfg parsing files
-
ashared_ptr. Destroy it ansynchronous way to avoid deleting when using it
-
IDL fsm generation
-
async signals
-
soft-realtime facilities
-
factory template
-
…