1.. _docs-pw-style-cpp: 2 3========= 4C++ style 5========= 6The Pigweed C++ style guide is closely based on Google's external C++ Style 7Guide, which is found on the web at 8https://google.github.io/styleguide/cppguide.html. The Google C++ Style Guide 9applies to Pigweed except as described in this document. 10 11The Pigweed style guide only applies to Pigweed itself. It does not apply to 12projects that use Pigweed or to the third-party code included with Pigweed. 13Non-Pigweed code is free to use features restricted by Pigweed, such as dynamic 14memory allocation and the entirety of the C++ Standard Library. 15 16Recommendations in the :ref:`docs-embedded-cpp` are considered part of the 17Pigweed style guide, but are separated out since it covers more general 18embedded development beyond just C++ style. 19 20C++ standard 21============ 22All Pigweed C++ code must compile with ``-std=c++17`` in Clang and GCC. C++20 23features may be used as long as the code still compiles unmodified with C++17. 24See ``pw_polyfill/language_feature_macros.h`` for macros that provide C++20 25features when supported. 26 27Compiler extensions should not be used unless wrapped in a macro or properly 28guarded in the preprocessor. See ``pw_processor/compiler.h`` for macros that 29wrap compiler-specific features. 30 31Automatic formatting 32==================== 33Pigweed uses `clang-format <https://clang.llvm.org/docs/ClangFormat.html>`_ to 34automatically format Pigweed source code. A ``.clang-format`` configuration is 35provided with the Pigweed repository. Within an upstream Pigweed environment, the 36`pw format` tool can be used to automatically format code. 37 38Automatic formatting is essential to facilitate large-scale, automated changes 39in Pigweed. Therefore, all code in Pigweed is expected to be formatted with 40``clang-format`` prior to submission. Existing code may be reformatted at any 41time. 42 43If ``clang-format`` formats code in an undesirable or incorrect way, it can be 44disabled for the affected lines by adding ``// clang-format off``. 45``clang-format`` must then be re-enabled with a ``// clang-format on`` comment. 46 47.. code-block:: cpp 48 49 // clang-format off 50 constexpr int kMyMatrix[] = { 51 100, 23, 0, 52 0, 542, 38, 53 1, 2, 201, 54 }; 55 // clang-format on 56 57C Standard Library 58================== 59In C++ headers, always use the C++ versions of C Standard Library headers (e.g. 60``<cstdlib>`` instead of ``<stdlib.h>``). If the header is used by both C and 61C++ code, only the C header should be used. 62 63In C++ code, it is preferred to use C functions from the ``std`` namespace. For 64example, use ``std::memcpy`` instead of ``memcpy``. The C++ standard does not 65require the global namespace versions of the functions to be provided. Using 66``std::`` is more consistent with the C++ Standard Library and makes it easier 67to distinguish Pigweed functions from library functions. 68 69Within core Pigweed, do not use C standard library functions that allocate 70memory, such as ``std::malloc``. There are exceptions to this for when dynamic 71allocation is enabled for a system; Pigweed modules are allowed to add extra 72functionality when a heap is present; but this must be optional. 73 74C++ Standard Library 75==================== 76Much of the C++ Standard Library is not a good fit for embedded software. Many 77of the classes and functions were not designed with the RAM, flash, and 78performance constraints of a microcontroller in mind. For example, simply 79adding the line ``#include <iostream>`` can increase the binary size by 150 KB! 80This is larger than many microcontrollers' entire internal storage. 81 82However, with appropriate caution, a limited set of standard C++ libraries can 83be used to great effect. Developers can leverage familiar, well-tested 84abstractions instead of writing their own. C++ library algorithms and classes 85can give equivalent or better performance than hand-written C code. 86 87A limited subset of the C++ Standard Library is permitted in Pigweed. To keep 88Pigweed small, flexible, and portable, functions that allocate dynamic memory 89must be avoided. Care must be exercised when using multiple instantiations of a 90template function, which can lead to code bloat. 91 92Permitted Headers 93----------------- 94.. admonition:: The following C++ Standard Library headers are always permitted: 95 :class: checkmark 96 97 * ``<array>`` 98 * ``<complex>`` 99 * ``<initializer_list>`` 100 * ``<iterator>`` 101 * ``<limits>`` 102 * ``<optional>`` 103 * ``<random>`` 104 * ``<ratio>`` 105 * ``<string_view>`` 106 * ``<tuple>`` 107 * ``<type_traits>`` 108 * ``<utility>`` 109 * ``<variant>`` 110 * C Standard Library headers (``<c*>``) 111 112.. admonition:: With caution, parts of the following headers can be used: 113 :class: warning 114 115 * ``<algorithm>`` -- be wary of potential memory allocation 116 * ``<atomic>`` -- not all MCUs natively support atomic operations 117 * ``<bitset>`` -- conversions to or from strings are disallowed 118 * ``<functional>`` -- do **not** use ``std::function``; use 119 :ref:`module-pw_function` 120 * ``<mutex>`` -- can use ``std::lock_guard``, use :ref:`module-pw_sync` for 121 mutexes 122 * ``<new>`` -- for placement new 123 * ``<numeric>`` -- be wary of code size with multiple template instantiations 124 125.. admonition:: Never use any of these headers: 126 :class: error 127 128 * Dynamic containers (``<list>``, ``<map>``, ``<set>``, ``<vector>``, etc.) 129 * Streams (``<iostream>``, ``<ostream>``, ``<fstream>``, ``<sstream>`` etc.) 130 -- in some cases :ref:`module-pw_stream` can work instead 131 * ``<span>`` -- use :ref:`module-pw_span` instead. Downstream projects may 132 want to directly use ``std::span`` if it is available, but upstream must 133 use the ``pw::span`` version for compatability 134 * ``<string>`` -- can use :ref:`module-pw_string` 135 * ``<thread>`` -- can use :ref:`module-pw_thread` 136 * ``<future>`` -- eventually :ref:`module-pw_async` will offer this 137 * ``<exception>``, ``<stdexcept>`` -- no exceptions 138 * ``<memory>``, ``<scoped_allocator>`` -- no allocations 139 * ``<regex>`` 140 * ``<valarray>`` 141 142Headers not listed here should be carefully evaluated before they are used. 143 144These restrictions do not apply to third party code or to projects that use 145Pigweed. 146 147Combining C and C++ 148=================== 149Prefer to write C++ code over C code, using ``extern "C"`` for symbols that must 150have C linkage. ``extern "C"`` functions should be defined within C++ 151namespaces to simplify referring to other code. 152 153C++ functions with no parameters do not include ``void`` in the parameter list. 154C functions with no parameters must include ``void``. 155 156.. code-block:: cpp 157 158 namespace pw { 159 160 bool ThisIsACppFunction() { return true; } 161 162 extern "C" int pw_ThisIsACFunction(void) { return -1; } 163 164 extern "C" { 165 166 int pw_ThisIsAlsoACFunction(void) { 167 return ThisIsACppFunction() ? 100 : 0; 168 } 169 170 } // extern "C" 171 172 } // namespace pw 173 174Comments 175======== 176Prefer C++-style (``//``) comments over C-style comments (``/* */``). C-style 177comments should only be used for inline comments. 178 179.. code-block:: cpp 180 181 // Use C++-style comments, except where C-style comments are necessary. 182 // This returns a random number using an algorithm I found on the internet. 183 #define RANDOM_NUMBER() [] { \ 184 return 4; /* chosen by fair dice roll */ \ 185 }() 186 187Indent code in comments with two additional spaces, making a total of three 188spaces after the ``//``. All code blocks must begin and end with an empty 189comment line, even if the blank comment line is the last line in the block. 190 191.. code-block:: cpp 192 193 // Here is an example of code in comments. 194 // 195 // int indentation_spaces = 2; 196 // int total_spaces = 3; 197 // 198 // engine_1.thrust = RANDOM_NUMBER() * indentation_spaces + total_spaces; 199 // 200 bool SomeFunction(); 201 202Passing move-only or expensive-to-copy arguments 203================================================ 204C++ offers a number of ways to pass arguments arguments to functions. 205When taking move-only or expensive-to-copy arguments, use the following table 206to determine which argument type to use: 207 208.. list-table:: C++ argument type choices 209 :widths: 30 20 10 210 :header-rows: 1 211 212 * - Use-case 213 - Name 214 - Syntax 215 * - If read-only 216 - By const reference 217 - ``const T&`` 218 * - If mutating 219 - By reference 220 - ``T&`` 221 * - If consuming 222 - By rvalue reference 223 - ``T&&`` 224 * - If conditionally consuming 225 - By value 226 - ``T`` 227 228Why rvalue references 229--------------------- 230When a function consumes or moves such an argument, it should accept an rvalue 231reference (``T&&``) rather than taking the argument by-value (``T``). An rvalue 232reference forces the caller to ``std::move`` when passing a preexisting 233variable, which makes the transfer of ownership explicit. 234 235Compared with accepting arguments by-value, rvalue references prevent 236unnecessary object instances and extra calls to move constructors. This has been 237shown to significantly impact code size and stack usage for Pigweed users. 238 239This is especially important when using ``pw::Function``. For more information 240about accepting ``pw::Function`` arguments, see 241:ref:`module-pw_function-move-semantics`. 242 243.. admonition:: **Yes**: Accept move-only or expensive-to-copy values by rvalue: 244 :class: checkmark 245 246 .. code-block:: cpp 247 248 void FrobulateVector(pw::Vector<T>&& vector) { 249 Frobulate(std::move(vector)); 250 } 251 252.. admonition:: **No**: Accepts move-only or expensive-to-copy values by value: 253 :class: error 254 255 .. code-block:: cpp 256 257 void FrobulateVector(pw::Vector<T> vector) { 258 Frobulate(std::move(vector)); 259 } 260 261This guidance overrides the standard `Google style guidance on rvalues 262<https://google.github.io/styleguide/cppguide.html#Rvalue_references>`_. 263 264Conditionally moving values 265--------------------------- 266An exception to the rule above is when a move-only or expensive-to-copy value 267is only conditionally consumed by the body of the function, for example: 268 269.. admonition:: **No**: Conditionally consumes ``vector``: 270 :class: error 271 272 .. code-block:: cpp 273 274 void PossiblyFrobulate(bool should_frob, pw::Vector<T>&& vector) { 275 if (should_frob) { 276 Frobulate(std::move(vector)); 277 } 278 } 279 280Because ``PossiblyFrobulate`` above will only consume ``vector`` in some code 281paths, the original ``vector`` passed by the user will outlive the call to 282``PossiblyFrobulate``: 283 284.. code-block:: cpp 285 286 pw::Vector<T> my_vec = ...; 287 288 // ``my_vec`` looks to be moved here, but the resulting ``rvalue`` is never 289 // consumed by ``PossiblyFrobulate``. 290 PossiblyFrobulate(false, std::move(my_vec)); 291 292 ... // some other long-running work 293 294 // ``my_vec`` is still alive here, possibly causing excess memory usage, 295 // deadlocks, or even undefined behavior! 296 297When conditionally consuming an argument, prefer instead to either accept 298the argument by-value or ensure that it is consumed by all control paths: 299 300.. admonition:: **Yes**: Conditionally consumes by-value ``vector``: 301 :class: checkmark 302 303 .. code-block:: cpp 304 305 void PossiblyFrobulate(bool should_frob, pw::Vector<T> vector) { 306 if (should_frob) { 307 Frobulate(std::move(vector)); 308 } 309 } 310 311.. admonition:: **Yes**: Consumes ``vector`` on all control paths: 312 :class: checkmark 313 314 .. code-block:: cpp 315 316 void PossiblyFrobulate(bool should_frob, pw::Vector<T>&& vector) { 317 if (should_frob) { 318 Frobulate(std::move(vector)); 319 } else { 320 [[maybe_unused]] auto to_discard = std::move(vector); 321 } 322 } 323 324Control statements 325================== 326 327Loops and conditionals 328---------------------- 329All loops and conditional statements must use braces, and be on their own line. 330 331.. admonition:: **Yes**: Always use braces for line conditionals and loops: 332 :class: checkmark 333 334 .. code-block:: cpp 335 336 while (SomeCondition()) { 337 x += 2; 338 } 339 if (OtherCondition()) { 340 DoTheThing(); 341 } 342 343 344.. admonition:: **No**: Missing braces 345 :class: error 346 347 .. code-block:: cpp 348 349 while (SomeCondition()) 350 x += 2; 351 if (OtherCondition()) 352 DoTheThing(); 353 354.. admonition:: **No**: Statement on same line as condition 355 :class: error 356 357 .. code-block:: cpp 358 359 while (SomeCondition()) { x += 2; } 360 if (OtherCondition()) { DoTheThing(); } 361 362 363The syntax ``while (true)`` is preferred over ``for (;;)`` for infinite loops. 364 365.. admonition:: **Yes**: 366 :class: checkmark 367 368 .. code-block:: cpp 369 370 while (true) { 371 DoSomethingForever(); 372 } 373 374.. admonition:: **No**: 375 :class: error 376 377 .. code-block:: cpp 378 379 for (;;) { 380 DoSomethingForever(); 381 } 382 383 384Prefer early exit with ``return`` and ``continue`` 385-------------------------------------------------- 386Prefer to exit early from functions and loops to simplify code. This is the 387same same conventions as `LLVM 388<https://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code>`_. 389We find this approach is superior to the "one return per function" style for a 390multitude of reasons: 391 392* **Visually**, the code is easier to follow, and takes less horizontal screen 393 space. 394* It makes it clear what part of the code is the **"main business" versus "edge 395 case handling"**. 396* For **functions**, parameter checking is in its own section at the top of the 397 function, rather than scattered around in the fuction body. 398* For **loops**, element checking is in its own section at the top of the loop, 399 rather than scattered around in the loop body. 400* Commit **deltas are simpler to follow** in code reviews; since adding a new 401 parameter check or loop element condition doesn't cause an indentation change 402 in the rest of the function. 403 404The guidance applies in two cases: 405 406* **Function early exit** - Early exits are for function parameter checking 407 and edge case checking at the top. The main functionality follows. 408* **Loop early exit** - Early exits in loops are for skipping an iteration 409 due to some edge case with an item getting iterated over. Loops may also 410 contain function exits, which should be structured the same way (see example 411 below). 412 413.. admonition:: **Yes**: Exit early from functions; keeping the main handling 414 at the bottom and de-dentend. 415 :class: checkmark 416 417 .. code-block:: cpp 418 419 Status DoSomething(Parameter parameter) { 420 // Parameter validation first; detecting incoming use errors. 421 PW_CHECK_INT_EQ(parameter.property(), 3, "Programmer error: frobnitz"); 422 423 // Error case: Not in correct state. 424 if (parameter.other() == MyEnum::kBrokenState) { 425 LOG_ERROR("Device in strange state: %s", parametr.state_str()); 426 return Status::InvalidPrecondition(); 427 } 428 429 // Error case: Not in low power mode; shouldn't do anything. 430 if (parameter.power() != MyEnum::kLowPower) { 431 LOG_ERROR("Not in low power mode"); 432 return Status::InvalidPrecondition(); 433 } 434 435 // Main business for the function here. 436 MainBody(); 437 MoreMainBodyStuff(); 438 } 439 440.. admonition:: **No**: Main body of function is buried and right creeping. 441 Even though this is shorter than the version preferred by Pigweed due to 442 factoring the return statement, the logical structure is less obvious. A 443 function in Pigweed containing **nested conditionals indicates that 444 something complicated is happening with the flow**; otherwise it would have 445 the early bail structure; so pay close attention. 446 :class: error 447 448 .. code-block:: cpp 449 450 Status DoSomething(Parameter parameter) { 451 // Parameter validation first; detecting incoming use errors. 452 PW_CHECK_INT_EQ(parameter.property(), 3, "Programmer error: frobnitz"); 453 454 // Error case: Not in correct state. 455 if (parameter.other() != MyEnum::kBrokenState) { 456 // Error case: Not in low power mode; shouldn't do anything. 457 if (parameter.power() == MyEnum::kLowPower) { 458 // Main business for the function here. 459 MainBody(); 460 MoreMainBodyStuff(); 461 } else { 462 LOG_ERROR("Not in low power mode"); 463 } 464 } else { 465 LOG_ERROR("Device in strange state: %s", parametr.state_str()); 466 } 467 return Status::InvalidPrecondition(); 468 } 469 470.. admonition:: **Yes**: Bail early from loops; keeping the main handling at 471 the bottom and de-dentend. 472 :class: checkmark 473 474 .. code-block:: cpp 475 476 for (int i = 0; i < LoopSize(); ++i) { 477 // Early skip of item based on edge condition. 478 if (!CommonCase()) { 479 continue; 480 } 481 // Early exit of function based on error case. 482 int my_measurement = GetSomeMeasurement(); 483 if (my_measurement < 10) { 484 LOG_ERROR("Found something strange; bailing"); 485 return Status::Unknown(); 486 } 487 488 // Main body of the loop. 489 ProcessItem(my_items[i], my_measurement); 490 ProcessItemMore(my_items[i], my_measurement, other_details); 491 ... 492 } 493 494.. admonition:: **No**: Right-creeping code with the main body buried inside 495 some nested conditional. This makes it harder to understand what is the 496 main purpose of the loop versus what is edge case handling. 497 :class: error 498 499 .. code-block:: cpp 500 501 for (int i = 0; i < LoopSize(); ++i) { 502 if (CommonCase()) { 503 int my_measurement = GetSomeMeasurement(); 504 if (my_measurement >= 10) { 505 // Main body of the loop. 506 ProcessItem(my_items[i], my_measurement); 507 ProcessItemMore(my_items[i], my_measurement, other_details); 508 ... 509 } else { 510 LOG_ERROR("Found something strange; bailing"); 511 return Status::Unknown(); 512 } 513 } 514 } 515 516There are cases where this structure doesn't work, and in those cases, it is 517fine to structure the code differently. 518 519No ``else`` after ``return`` or ``continue`` 520-------------------------------------------- 521Do not put unnecessary ``} else {`` blocks after blocks that terminate with a 522return, since this causes unnecessary rightward indentation creep. This 523guidance pairs with the preference for early exits to reduce code duplication 524and standardize loop/function structure. 525 526.. admonition:: **Yes**: No else after return or continue 527 :class: checkmark 528 529 .. code-block:: cpp 530 531 // Note lack of else block due to return. 532 if (Failure()) { 533 DoTheThing(); 534 return Status::ResourceExausted(); 535 } 536 537 // Note lack of else block due to continue. 538 while (MyCondition()) { 539 if (SomeEarlyBail()) { 540 continue; 541 } 542 // Main handling of item 543 ... 544 } 545 546 DoOtherThing(); 547 return OkStatus(); 548 549.. admonition:: **No**: Else after return needlessly creeps right 550 :class: error 551 552 .. code-block:: cpp 553 554 if (Failure()) { 555 DoTheThing(); 556 return Status::ResourceExausted(); 557 } else { 558 while (MyCondition()) { 559 if (SomeEarlyBail()) { 560 continue; 561 } else { 562 // Main handling of item 563 ... 564 } 565 } 566 DoOtherThing(); 567 return OkStatus(); 568 } 569 570Error handling 571============== 572Historically, exceptions have been avoided in embedded C++ as well as in general 573C++ code written at Google. Instead, assertions and error codes are used to 574communicate errors with less overhead. 575 576Signal and propagate non-fatal errors with ``pw::Status`` and ``pw::Result``, 577and assert/check for fatal errors. 578 579Add log statements to help with error tracking. See 580:ref:`guidance below <docs-pw-style-cpp-logging>` on how to craft high-value, 581low-noise logs. 582 583.. note: 584 585Like Google's C++ style guide, Pigweed does not use exceptions. The case for 586avoiding exceptions on embedded is primarily due to reducing code size. 587 588Recoverable errors 589------------------ 590Use the following to report non-fatal failures from subroutines: 591 592- :cpp:type:`pw::Status`: Zero-overhead type that wraps a 593 :ref:`status code <module-pw_status-quickref>`. 594- :ref:`pw::Result <module-pw_result>`: Union of a status code and a value. 595- :ref:`pw::StatusWithSize <module-pw_status-guide-status-with-size>`: A status 596 combined with a size. Especially useful for operations which may partially 597 succeed, such as a write that sent some bytes before failing. 598 599Fatal errors 600------------ 601Use :c:macro:`PW_ASSERT` and the :c:macro:`PW_CHECK` family of macros to halt 602execution on a fatal error. 603 604- These are appropriate when the security of the device is compromised. 605 606 - Example: memory corruption is detected. 607 608.. admonition:: **Yes** 609 :class: checkmark 610 611 .. code-block:: cpp 612 613 PW_CHECK_NOTNULL(item->next); 614 PW_CHECK_PTR_EQ(item, item->next->prev); 615 616- These may be appropriate for instances of unambiguous programmer error. 617 618 - Example: a caller passed a null pointer to a routine that explicitly 619 requires non-null pointers. 620 621.. warning:: 622 623 Be very careful about introducing new assertions into existing code, or in 624 code paths that are not exhaustively tested, or any other scenario that may 625 result in crashes in fielded devices. 626 627.. admonition:: **No**: May cause a runtime crash. 628 :class: error 629 630 .. code-block:: cpp 631 632 StatusWithSize sws = kvs.Get("some-key", &out); 633 PW_CHECK_OK(sws.status()); 634 635 The key may be missing from the :ref:`KVS <module-pw_kvs>` for a number of 636 reasons. It is likely better to surface this error to a higher level that can 637 decide how to handle a missing value. 638 639Include guards 640============== 641The first non-comment line of every header file must be ``#pragma once``. Do 642not use traditional macro include guards. The ``#pragma once`` should come 643directly after the Pigweed copyright block, with no blank line, followed by a 644blank, like this: 645 646.. code-block:: cpp 647 648 // Copyright 2021 The Pigweed Authors 649 // 650 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 651 // use this file except in compliance with the License. You may obtain a copy of 652 // the License at 653 // 654 // https://www.apache.org/licenses/LICENSE-2.0 655 // 656 // Unless required by applicable law or agreed to in writing, software 657 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 658 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 659 // License for the specific language governing permissions and limitations under 660 // the License. 661 #pragma once 662 663 // Header file-level comment goes here... 664 665.. _docs-pw-style-cpp-logging: 666 667Logging 668======= 669Good logging can be incredibly useful in detecting and debugging errors. Log 670quality is determined by the amount of useful information relative to overall 671amount of logs. 672 673Log in the right spot 674--------------------- 675Limiting logs to only the most relevant sections of code can guide developers to 676areas that require debugging. 677 678- **Log errors as soon as they can be umabiguously determined to be errors.** An 679 unambiguous error is one that will be reported to the caller of the module or 680 component. Avoid logging errors that are handled internally by the module or 681 component. 682 683 - Example: A task manager would not log a failure to schedule a specific 684 worker from a pool, but may log the failure to find *any* worker in the 685 pool. 686 687 .. admonition:: **No**: May log errors even if the call eventually succeeds. 688 :class: error 689 690 .. code-block:: cpp 691 692 Status TaskManager::AssignToWorker(Task& task) { 693 for (auto& worker : pool_) { 694 if (worker.AssignTask(task).ok()) { 695 return OkStatus(); 696 } 697 } 698 return Status::ResourceExhausted(); 699 } 700 701 Status Worker::Assign(Task& task) { 702 if (busy_) { 703 PW_LOG_DEBUG("failed to assign task to worker %zu", id_); 704 return Status::FailedPrecondition(); 705 } 706 // ... 707 } 708 709 .. admonition:: **Yes**: Only logs when an actual failure has occurred. 710 :class: checkmark 711 712 .. code-block:: cpp 713 714 Status TaskManager::AssignToWorker(Task& task) { 715 for (auto& worker : pool_) { 716 if (worker.AssignTask(task).ok()) { 717 return OkStatus(); 718 } 719 } 720 PW_LOG_DEBUG("failed to find a worker to handle the task"); 721 return Status::ResourceExhausted(); 722 } 723 724 Status Worker::Assign(Task& task) { 725 if (busy_) { 726 return Status::FailedPrecondition(); 727 } 728 // ... 729 } 730 731 732- **Log failures of an overall workflow at the level that it was initiated** to 733 provide context in which an error occurred. 734 735 - Example: A widget may log that it could not perform a user-scheduled task 736 because the task manager returned an error. 737 738- **Limit the use of informational logs of non-failure conditions.** These 739 "heartbeat" logs can quickly accrue and become noise. If needed, keep the 740 frequency of these logs low, e.g. not more than once per second. 741 :c:macro:`PW_LOG_EVERY_N` and :c:macro:`PW_LOG_EVERY_N_DURATION` can be used 742 to rate-limit such logs. 743 744 .. admonition:: **No**: May spew a large number of logs. 745 :class: error 746 747 .. code-block:: cpp 748 749 void OnChunk(const Chunk& chunk) { 750 ++count_; 751 total_ += chunk.size(); 752 PW_LOG_DEBUG("Processed %zu chunks totaling %zu bytes", count_, total_); 753 // ... 754 } 755 756 .. admonition:: **Yes**: Only logs once every 10 seconds. 757 :class: checkmark 758 759 .. code-block:: cpp 760 761 void OnChunk(const Packet& packet) { 762 static constexpr auto kLogInterval = 763 chrono::SystemClock::for_at_least(std::chrono::seconds(10)); 764 ++count_; 765 total_ += packet.size(); 766 PW_LOG_EVERY_N_DURATION(PW_LOG_LEVEL_DEBUG, 767 kLogInterval, 768 "Processed %zu chunks totaling %zu bytes", 769 count_, 770 total_); 771 } 772 773Log at the correct level 774------------------------ 775:ref:`Log levels <module-pw_log-levels>` indicate the seriousness of a message 776and provide a simple mechanism for conditional logging and for log filtering. 777 778- **Downstream projects should use less filtered log levels**, as 779 project-specific errors more likely indicate an actionable failure. 780 781 - Use :c:macro:`PW_LOG_CRITICAL` for failures that compromise the entire 782 device and will imminently halt or crash the device. 783 - Use :c:macro:`PW_LOG_ERROR` for failures that are more serious or harder to 784 recover from. 785 - Use :c:macro:`PW_LOG_WARN` for failures that are less serious or easier to 786 recover from. 787 - Use :c:macro:`PW_LOG_INFO` for informational logs of non-failure conditions. 788 789- **Libraries and upstream code should allow configurable logging.** Downstream 790 projects may want to disable library and module logging to save on code size, 791 or enable it to aid in debugging. 792 793 - Use :c:macro:`PW_LOG_DEBUG` to log specific errors that the caller is 794 expected to handle. 795 796 .. admonition:: **Yes** 797 :class: checkmark 798 799 .. code-block:: cpp 800 801 if (stream.IsClosed()) { 802 PW_LOG_DEBUG("Stream closed unexpectedly"); 803 return Status::OutOfRange(); 804 } 805 806 - Use :c:macro:`PW_LOG_INFO` and :c:macro:`PW_LOG_WARN` to communicate error 807 conditions that may not have a caller that can handle them. 808 809 .. admonition:: **Yes** 810 :class: checkmark 811 812 .. code-block:: cpp 813 814 while(!task_queue_.empty()) { 815 Task task = std::move(task_queue_.back()); 816 task_queue_.pop_back(); 817 if (task.HasExpired()) { 818 PW_LOG_INFO("Task %zu expired before being scheduled", task.id()); 819 continue; 820 } 821 Schedule(std::move(task)); 822 // ... 823 } 824 825 - Set a :c:macro:`PW_LOG_LEVEL`. If logging in a module with a 826 :ref:`module configuration <module-structure-compile-time-configuration>`, 827 include a logging option and set :c:macro:`PW_LOG_LEVEL` to it. 828 829 .. admonition:: **Yes** 830 :class: checkmark 831 832 .. code-block:: cpp 833 834 // In my_module's config.h. Can be overridden at compile time. 835 #ifndef MY_MODULE_LOG_LEVEL 836 #define MY_MODULE_LOG_LEVEL PW_LOG_LEVEL_WARN 837 #endif MY_MODULE_LOG_LEVEL 838 839 // In my_module's source files. 840 #include "my_module/config.h" 841 #define PW_LOG_LEVEL MY_MODULE_LOG_LEVEL 842 843Log the right information 844------------------------- 845Logging the most useful information requires considering what may be relevant to 846an error and cannot be obtained another way. 847 848- **Include relevant context**, such as function parameters. 849- **Capitalize your log message, but do not end with puncuation.** Log backends 850 typically combine your log message with additional information and format 851 them. 852 853.. admonition:: **No** 854 :class: error 855 856 .. code-block:: cpp 857 858 PW_LOG_DEBUG("the operation did not complete normally."); 859 860.. admonition:: **Yes** 861 :class: checkmark 862 863 .. code-block:: cpp 864 865 PW_LOG_DEBUG("The operation completed normally"); 866 867- **Set** :c:macro:`PW_LOG_MODULE_NAME` to include a 868 module name that you can filter on. 869 870.. admonition:: **Yes** 871 :class: checkmark 872 873 .. code-block:: cpp 874 875 #define PW_LOG_MODULE_NAME "my_module" 876 877- **Do not include source location details.** The log backend can be configured 878 to add various :ref:`module-pw_log-logging_attributes` automatically. 879 880.. admonition:: **No** 881 :class: error 882 883 .. code-block:: cpp 884 885 PW_LOG_DEBUG("%s:%d: %s called", __FILE__, __LINE__, __PRETTY_FUNCTION__); 886 887- **Do not log** :cpp:type:`pw::Status` **details.** If you are logging and 888 returning an error as a result of a subroutine that returned an error, it is 889 likely that a log statement can be added closer to where that error was 890 detected. 891 892.. admonition:: **No** 893 :class: error 894 895 .. code-block:: cpp 896 897 Result<Message> ReadAndDecode(Stream& stream) { 898 Result<EncodedMessage> result = ReadEncodedMessage(stream); 899 if (!result.ok()) { 900 Status status = result.status(); 901 PW_LOG_DEBUG("Failed to read message: %s", 902 pw_StatusString(status.code)); 903 return status; 904 } 905 // ... 906 } 907 908Memory allocation 909================= 910Dynamic memory allocation can be problematic. Heap allocations and deallocations 911occupy valuable CPU cycles. Memory usage becomes nondeterministic, which can 912result in a system crashing without a clear culprit. 913 914To keep Pigweed portable, core Pigweed code is not permitted to dynamically 915(heap) allocate memory, such as with ``malloc`` or ``new``. All memory should be 916allocated with automatic (stack) or static (global) storage duration. Pigweed 917must not use C++ libraries that use dynamic allocation. 918 919Projects that use Pigweed are free to use dynamic allocation, provided they 920have selected a target that enables the heap. 921 922Naming 923====== 924Entities shall be named according to the `Google style guide 925<https://google.github.io/styleguide/cppguide.html>`_, with the following 926additional requirements. 927 928C++ code 929-------- 930* All Pigweed C++ code must be in the ``pw`` namespace. Namespaces for modules 931 should be nested under ``pw``. For example, ``pw::string::Format()``. 932* Whenever possible, private code should be in a source (.cc) file and placed in 933 anonymous namespace nested under ``pw``. Unit tests must be declared in an 934 anonymous namespace to avoid potential linking issues when building multiple 935 tests in one binary. 936* If private code must be exposed in a header file, it must be in a namespace 937 nested under ``pw``. The namespace may be named for its subsystem or use a 938 name that designates it as private, such as ``internal``. 939* Template arguments for non-type names (e.g. ``template <int kFooBar>``) should 940 follow the constexpr and const variable Google naming convention, which means 941 k prefixed camel case (e.g. ``kCamelCase``). This matches the Google C++ 942 style for variable naming, however the wording in the official style guide 943 isn't explicit for template arguments and could be interpreted to use 944 ``foo_bar`` style naming. For consistency with other variables whose value is 945 always fixed for the duration of the program, the naming convention is 946 ``kCamelCase``, and so that is the style we use in Pigweed. 947* Trivial membor accessors should be named with ``snake_case()``. The Google 948 C++ style allows either ``snake_case()`` or ``CapsCase()``, but Pigweed 949 always uses ``snake_case()``. 950* Abstract base classes should be named generically, with derived types named 951 specifically. For example, ``Stream`` is an abstract base, and 952 ``SocketStream`` and ``StdioStream`` are an implementations of that 953 interface. Any prefix or postfix indicating whether something is abstract or 954 concrete is not permitted; for example, ``IStream`` or ``SocketStreamImpl`` 955 are both not permitted. These pre-/post-fixes add additional visual noise and 956 are irrelevant to consumers of these interfaces. 957 958C code 959------ 960In general, C symbols should be prefixed with the module name. If the symbol is 961not associated with a module, use just ``pw`` as the module name. Facade 962backends may chose to prefix symbols with the facade's name to help reduce the 963length of the prefix. 964 965* Public names used by C code must be prefixed with the module name (e.g. 966 ``pw_tokenizer_*``). 967* If private code must be exposed in a header, private names used by C code must 968 be prefixed with an underscore followed by the module name (e.g. 969 ``_pw_assert_*``). 970* Avoid writing C source (.c) files in Pigweed. Prefer to write C++ code with C 971 linkage using ``extern "C"``. Within C source, private C functions and 972 variables must be named with the ``_pw_my_module_*`` prefix and should be 973 declared ``static`` whenever possible; for example, 974 ``_pw_my_module_MyPrivateFunction``. 975* The C prefix rules apply to 976 977 * C functions (``int pw_foo_FunctionName(void);``), 978 * variables used by C code (``int pw_foo_variable_name;``), 979 * constant variables used by C code (``const int pw_foo_kConstantName;``), 980 * structs used by C code (``typedef struct {} pw_foo_StructName;``), and 981 * all of the above for ``extern "C"`` names in C++ code. 982 983 The prefix does not apply to struct members, which use normal Google style. 984 985Preprocessor macros 986------------------- 987* Public Pigweed macros must be prefixed with the module name (e.g. 988 ``PW_MY_MODULE_*``). 989* Private Pigweed macros must be prefixed with an underscore followed by the 990 module name (e.g. ``_PW_MY_MODULE_*``). (This style may change, see 991 `b/234886184 <https://issuetracker.google.com/issues/234886184>`_). 992 993**Example** 994 995.. code-block:: cpp 996 997 namespace pw::my_module { 998 namespace nested_namespace { 999 1000 // C++ names (types, variables, functions) must be in the pw namespace. 1001 // They are named according to the Google style guide. 1002 constexpr int kGlobalConstant = 123; 1003 1004 // Prefer using functions over extern global variables. 1005 extern int global_variable; 1006 1007 class Class {}; 1008 1009 void Function(); 1010 1011 extern "C" { 1012 1013 // Public Pigweed code used from C must be prefixed with pw_. 1014 extern const int pw_my_module_kGlobalConstant; 1015 1016 extern int pw_my_module_global_variable; 1017 1018 void pw_my_module_Function(void); 1019 1020 typedef struct { 1021 int member_variable; 1022 } pw_my_module_Struct; 1023 1024 // Private Pigweed code used from C must be prefixed with _pw_. 1025 extern const int _pw_my_module_kPrivateGlobalConstant; 1026 1027 extern int _pw_my_module_private_global_variable; 1028 1029 void _pw_my_module_PrivateFunction(void); 1030 1031 typedef struct { 1032 int member_variable; 1033 } _pw_my_module_PrivateStruct; 1034 1035 } // extern "C" 1036 1037 // Public macros must be prefixed with PW_. 1038 #define PW_MY_MODULE_PUBLIC_MACRO(arg) arg 1039 1040 // Private macros must be prefixed with _PW_. 1041 #define _PW_MY_MODULE_PRIVATE_MACRO(arg) arg 1042 1043 } // namespace nested_namespace 1044 } // namespace pw::my_module 1045 1046See :ref:`docs-pw-style-macros` for details about macro usage. 1047 1048Namespace scope formatting 1049========================== 1050All non-indented blocks (namespaces, ``extern "C"`` blocks, and preprocessor 1051conditionals) must have a comment on their closing line with the 1052contents of the starting line. 1053 1054All nested namespaces should be declared together with no blank lines between 1055them. 1056 1057.. code-block:: cpp 1058 1059 #include "some/header.h" 1060 1061 namespace pw::nested { 1062 namespace { 1063 1064 constexpr int kAnonConstantGoesHere = 0; 1065 1066 } // namespace 1067 1068 namespace other { 1069 1070 const char* SomeClass::yes = "no"; 1071 1072 bool ThisIsAFunction() { 1073 #if PW_CONFIG_IS_SET 1074 return true; 1075 #else 1076 return false; 1077 #endif // PW_CONFIG_IS_SET 1078 } 1079 1080 extern "C" { 1081 1082 const int pw_kSomeConstant = 10; 1083 int pw_some_global_variable = 600; 1084 1085 void pw_CFunction() { ... } 1086 1087 } // extern "C" 1088 1089 } // namespace 1090 } // namespace pw::nested 1091 1092Using directives for literals 1093============================= 1094`Using-directives 1095<https://en.cppreference.com/w/cpp/language/namespace#Using-directives>`_ (e.g. 1096``using namespace ...``) are permitted in implementation files only for the 1097purposes of importing literals such as ``std::chrono_literals`` or 1098``pw::bytes::unit_literals``. Namespaces that contain any symbols other than 1099literals are not permitted in a using-directive. This guidance also has no 1100impact on `using-declarations 1101<https://en.cppreference.com/w/cpp/language/namespace#Using-declarations>`_ 1102(e.g. ``using foo::Bar;``). 1103 1104Rationale: Literals improve code readability, making units clearer at the point 1105of definition. 1106 1107.. code-block:: cpp 1108 1109 using namespace std::chrono; // Not allowed 1110 using namespace std::literals::chrono_literals; // Allowed 1111 1112 constexpr std::chrono::duration delay = 250ms; 1113 1114Pointers and references 1115======================= 1116For pointer and reference types, place the asterisk or ampersand next to the 1117type. 1118 1119.. code-block:: cpp 1120 1121 int* const number = &that_thing; 1122 constexpr const char* kString = "theory!" 1123 1124 bool FindTheOneRing(const Region& where_to_look) { ... } 1125 1126Prefer storing references over storing pointers. Pointers are required when the 1127pointer can change its target or may be ``nullptr``. Otherwise, a reference or 1128const reference should be used. 1129 1130.. _docs-pw-style-macros: 1131 1132Preprocessor macros 1133=================== 1134Macros should only be used when they significantly improve upon the C++ code 1135they replace. Macros should make code more readable, robust, and safe, or 1136provide features not possible with standard C++, such as stringification, line 1137number capturing, or conditional compilation. When possible, use C++ constructs 1138like constexpr variables in place of macros. Never use macros as constants, 1139except when a string literal is needed or the value must be used by C code. 1140 1141When macros are needed, the macros should be accompanied with extensive tests 1142to ensure the macros are hard to use wrong. 1143 1144Stand-alone statement macros 1145---------------------------- 1146Macros that are standalone statements must require the caller to terminate the 1147macro invocation with a semicolon (see `Swalling the Semicolon 1148<https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html>`_). For 1149example, the following does *not* conform to Pigweed's macro style: 1150 1151.. code-block:: cpp 1152 1153 // BAD! Definition has built-in semicolon. 1154 #define PW_LOG_IF_BAD(mj) \ 1155 CallSomeFunction(mj); 1156 1157 // BAD! Compiles without error; semicolon is missing. 1158 PW_LOG_IF_BAD("foo") 1159 1160Here's how to do this instead: 1161 1162.. code-block:: cpp 1163 1164 // GOOD; requires semicolon to compile. 1165 #define PW_LOG_IF_BAD(mj) \ 1166 CallSomeFunction(mj) 1167 1168 // GOOD; fails to compile due to lacking semicolon. 1169 PW_LOG_IF_BAD("foo") 1170 1171For macros in function scope that do not already require a semicolon, the 1172contents can be placed in a ``do { ... } while (0)`` loop. 1173 1174.. code-block:: cpp 1175 1176 #define PW_LOG_IF_BAD(mj) \ 1177 do { \ 1178 if (mj.Bad()) { \ 1179 Log(#mj " is bad") \ 1180 } \ 1181 } while (0) 1182 1183Standalone macros at global scope that do not already require a semicolon can 1184add a ``static_assert`` declaration statement as their last line. 1185 1186.. code-block:: cpp 1187 1188 #define PW_NEAT_THING(thing) \ 1189 bool IsNeat_##thing() { return true; } \ 1190 static_assert(true, "Macros must be terminated with a semicolon") 1191 1192Private macros in public headers 1193-------------------------------- 1194Private macros in public headers must be prefixed with ``_PW_``, even if they 1195are undefined after use; this prevents collisions with downstream users. For 1196example: 1197 1198.. code-block:: cpp 1199 1200 #define _PW_MY_SPECIAL_MACRO(op) ... 1201 ... 1202 // Code that uses _PW_MY_SPECIAL_MACRO() 1203 ... 1204 #undef _PW_MY_SPECIAL_MACRO 1205 1206Macros in private implementation files (.cc) 1207-------------------------------------------- 1208Macros within .cc files that should only be used within one file should be 1209undefined after their last use; for example: 1210 1211.. code-block:: cpp 1212 1213 #define DEFINE_OPERATOR(op) \ 1214 T operator ## op(T x, T y) { return x op y; } \ 1215 static_assert(true, "Macros must be terminated with a semicolon") \ 1216 1217 DEFINE_OPERATOR(+); 1218 DEFINE_OPERATOR(-); 1219 DEFINE_OPERATOR(/); 1220 DEFINE_OPERATOR(*); 1221 1222 #undef DEFINE_OPERATOR 1223 1224Preprocessor conditional statements 1225=================================== 1226When using macros for conditional compilation, prefer to use ``#if`` over 1227``#ifdef``. This checks the value of the macro rather than whether it exists. 1228 1229* ``#if`` handles undefined macros equivalently to ``#ifdef``. Undefined 1230 macros expand to 0 in preprocessor conditional statements. 1231* ``#if`` evaluates false for macros defined as 0, while ``#ifdef`` evaluates 1232 true. 1233* Macros defined using compiler flags have a default value of 1 in GCC and 1234 Clang, so they work equivalently for ``#if`` and ``#ifdef``. 1235* Macros defined to an empty statement cause compile-time errors in ``#if`` 1236 statements, which avoids ambiguity about how the macro should be used. 1237 1238All ``#endif`` statements should be commented with the expression from their 1239corresponding ``#if``. Do not indent within preprocessor conditional statements. 1240 1241.. code-block:: cpp 1242 1243 #if USE_64_BIT_WORD 1244 using Word = uint64_t; 1245 #else 1246 using Word = uint32_t; 1247 #endif // USE_64_BIT_WORD 1248 1249Unsigned integers 1250================= 1251Unsigned integers are permitted in Pigweed. Aim for consistency with existing 1252code and the C++ Standard Library. Be very careful mixing signed and unsigned 1253integers. 1254 1255Features not in the C++ standard 1256================================ 1257Avoid features not available in standard C++. This includes compiler extensions 1258and features from other standards like POSIX. 1259 1260For example, use ``ptrdiff_t`` instead of POSIX's ``ssize_t``, unless 1261interacting with a POSIX API in intentionally non-portable code. Never use 1262POSIX functions with suitable standard or Pigweed alternatives, such as 1263``strnlen`` (use ``pw::string::NullTerminatedLength`` instead). 1264