1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-02-21 13:46:52 +00:00

Suggested modernization steps for each *.CC module (#1801)

* Suggested modernization steps
This commit is contained in:
Dmytro Lytovchenko 2021-10-07 19:18:44 +02:00 committed by GitHub
parent 435f17641a
commit 2312965285
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,15 +1,95 @@
# Notes on the C-to-C++ Conversion # Notes on the C-to-C++ Conversion
- libtransmission was written in C for fifteen years, so eliminating all - libtransmission was written in C for fifteen years, so eliminating all Cisms is nearly impossible. **Modernization
Cisms is nearly impossible. **Modernization patches are welcomed** but patches are welcomed** but it won't all happen overnight. `tr_strdup()` and `constexpr` wil exist side-by-side in the
it won't all happen overnight. `tr_strdup()` and `constexpr` wil exist codebase for the forseeable future.
side-by-side in the codebase for the forseeable future.
- It's so tempting to refactor all the things! Please keep modernization - It's so tempting to refactor all the things! Please keep modernization patches reasonably focused so that they will be
patches reasonably focused so that they will be easy to review. easy to review.
- Prefer `std::` tools over bespoke ones. For example, use `std::vector` - Prefer `std::` tools over bespoke ones. For example, use `std::vector`
instead of tr_ptrArray. Redundant bespoke code should be removed. instead of tr_ptrArray. Redundant bespoke code should be removed.
- Consider ripple effects before adding C++ into public headers. Will it - Consider ripple effects before adding C++ into public headers. Will it break C code that #includes that header? If you think it might, [consult with downstream projects](https://github.com/transmission/transmission/issues/1826) to see if this is a problem for them.
break C code that #includes that header?
## Checklist for modernization of a module
> **_NOTE:_**
> The version in `libtransmission/CMakeLists.txt` is C++17.
> See https://github.com/AnthonyCalandra/modern-cpp-features
This can be done in multiple smaller passes:
1. Satisfy clang-tidy. `libtransmission/.clang-tidy`'s list of rules should eventually be expanded to a list similar to the one in `qt/.clang-tidy`.
2. Group member functions and their parent structs
- Use `namespace libtransmission`
- Split large modules into smaller groups of files in a `libtransmission/<name>` subdirectories, with own
sub-namespace.
3. Enums replaced with new `enum class` syntax. Numeric `#define` constants replaced with C++ `const`/`constexpr`.
4. Memory - promote init and free functions to C++ ctors and dtors, and ensure it is only managed with new/delete
5. Owned memory - promote simple pointer fields owning their data to smart pointers (unique_ptr, shared_ptr, vector,
string)
### Detailed Steps
1. Satisfy clang-tidy warnings
- Change C includes to C++ wraps, example: <string.h> becomes <cstring> and update calls to standard library to
use `std::` namespace prefix. This clearly delineates the border between std library and transmission. Headers
must be sorted alphabetically.
- Headers which are used conditionally based on some `#ifdef` in the code, should also have same `#ifdef` in the
include section.
- Revisit type warnings, `int` vs `unsigned int`. Sizes and counts should use `size_t` type where this does not
break external API declarations. Ideally change that too.
2. Move and group code together.
- Move member functions into structs. To minimize code churn, create function forward declarations inside structs,
and give `struct_name::` prefixes to the functions.
```c++
typedef struct {
int field;
} foo;
int foo_blep(struct foo *f) {
return f->field;
}
```
becomes:
```c++
struct foo {
int field;
void blep();
};
int foo::blep() {
return this->field;
}
```
- For functions taking `const` pointer, add `const` after the function prototype: `int blep() const` like so.
- For structs used by other modules, struct definitions should relocate to internal `*-common.h` header files.
- Split large files into sub-modules sharing own separate sub-namespace and sitting in a subdirectory
under `libtransmission/`.
- Some externally invoked functions must either not move OR have `extern "C"` adapter functions.
3. Enums promoted to `enum class` and given a type:
```c++
enum { A, B, C };
```
becomes
```c++
enum: int { A, B, C }; // unscoped, use A, B, C
enum MyEnum: int { A, B, C }; // unscoped, use A, B, C
// OR wrap into a scope -
enum struct MyEnum: int { A, B, C }; // scoped, use MyEnum::A
enum class MyEnum: int { A, B, C }; // scoped, use MyEnum::A
```
this will make all values of enum to have that numeric type.
4. Numeric/bool `#define` constants should be replaced with C++ `const`/`constexpr`.
6. Memory management:
- Prefer constructors and destructors vs manual construction and destruction. But when doing so must ensure that the
struct is never constructed using C `malloc`/`free`, but must use C++ `new`/`delete`.
- Avoid using std::memset on a new struct. It is allowed in C, and C++ struct but will destroy virtual table on a
C++ class. Use field initializers in C++.
7. Owned memory:
- If destructor deletes something, it means it was owned. Promote that field to owning type (vector, unique_ptr,
shared_ptr or string).