• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
383Do not declare empty infinite loops, which are undefined behavior. Instead, call
384:cpp:func:`pw::InfiniteLoop`.
385
386.. admonition:: **Yes**:
387   :class: checkmark
388
389   .. code-block:: cpp
390
391      pw::InfiniteLoop();
392
393.. admonition:: **No**:
394   :class: error
395
396   .. code-block:: cpp
397
398      while (true) {
399        // The compiler may optimize out this loop!
400      }
401
402Prefer early exit with ``return`` and ``continue``
403--------------------------------------------------
404Prefer to exit early from functions and loops to simplify code. This is the
405same same conventions as `LLVM
406<https://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code>`_.
407We find this approach is superior to the "one return per function" style for a
408multitude of reasons:
409
410* **Visually**, the code is easier to follow, and takes less horizontal screen
411  space.
412* It makes it clear what part of the code is the **"main business" versus "edge
413  case handling"**.
414* For **functions**, parameter checking is in its own section at the top of the
415  function, rather than scattered around in the fuction body.
416* For **loops**, element checking is in its own section at the top of the loop,
417  rather than scattered around in the loop body.
418* Commit **deltas are simpler to follow** in code reviews; since adding a new
419  parameter check or loop element condition doesn't cause an indentation change
420  in the rest of the function.
421
422The guidance applies in two cases:
423
424* **Function early exit** - Early exits are for function parameter checking
425  and edge case checking at the top. The main functionality follows.
426* **Loop early exit** - Early exits in loops are for skipping an iteration
427  due to some edge case with an item getting iterated over. Loops may also
428  contain function exits, which should be structured the same way (see example
429  below).
430
431.. admonition:: **Yes**: Exit early from functions; keeping the main handling
432   at the bottom and de-dentend.
433   :class: checkmark
434
435   .. code-block:: cpp
436
437      Status DoSomething(Parameter parameter) {
438        // Parameter validation first; detecting incoming use errors.
439        PW_CHECK_INT_EQ(parameter.property(), 3, "Programmer error: frobnitz");
440
441        // Error case: Not in correct state.
442        if (parameter.other() == MyEnum::kBrokenState) {
443          LOG_ERROR("Device in strange state: %s", parametr.state_str());
444          return Status::InvalidPrecondition();
445        }
446
447        // Error case: Not in low power mode; shouldn't do anything.
448        if (parameter.power() != MyEnum::kLowPower) {
449          LOG_ERROR("Not in low power mode");
450          return Status::InvalidPrecondition();
451        }
452
453        // Main business for the function here.
454        MainBody();
455        MoreMainBodyStuff();
456      }
457
458.. admonition:: **No**: Main body of function is buried and right creeping.
459   Even though this is shorter than the version preferred by Pigweed due to
460   factoring the return statement, the logical structure is less obvious. A
461   function in Pigweed containing **nested conditionals indicates that
462   something complicated is happening with the flow**; otherwise it would have
463   the early bail structure; so pay close attention.
464   :class: error
465
466   .. code-block:: cpp
467
468      Status DoSomething(Parameter parameter) {
469        // Parameter validation first; detecting incoming use errors.
470        PW_CHECK_INT_EQ(parameter.property(), 3, "Programmer error: frobnitz");
471
472        // Error case: Not in correct state.
473        if (parameter.other() != MyEnum::kBrokenState) {
474          // Error case: Not in low power mode; shouldn't do anything.
475          if (parameter.power() == MyEnum::kLowPower) {
476            // Main business for the function here.
477            MainBody();
478            MoreMainBodyStuff();
479          } else {
480            LOG_ERROR("Not in low power mode");
481          }
482        } else {
483          LOG_ERROR("Device in strange state: %s", parametr.state_str());
484        }
485        return Status::InvalidPrecondition();
486      }
487
488.. admonition:: **Yes**: Bail early from loops; keeping the main handling at
489   the bottom and de-dentend.
490   :class: checkmark
491
492   .. code-block:: cpp
493
494      for (int i = 0; i < LoopSize(); ++i) {
495        // Early skip of item based on edge condition.
496        if (!CommonCase()) {
497          continue;
498        }
499        // Early exit of function based on error case.
500        int my_measurement = GetSomeMeasurement();
501        if (my_measurement < 10) {
502          LOG_ERROR("Found something strange; bailing");
503          return Status::Unknown();
504        }
505
506        // Main body of the loop.
507        ProcessItem(my_items[i], my_measurement);
508        ProcessItemMore(my_items[i], my_measurement, other_details);
509        ...
510      }
511
512.. admonition:: **No**: Right-creeping code with the main body buried inside
513   some nested conditional. This makes it harder to understand what is the
514   main purpose of the loop versus what is edge case handling.
515   :class: error
516
517   .. code-block:: cpp
518
519      for (int i = 0; i < LoopSize(); ++i) {
520        if (CommonCase()) {
521          int my_measurement = GetSomeMeasurement();
522          if (my_measurement >= 10) {
523            // Main body of the loop.
524            ProcessItem(my_items[i], my_measurement);
525            ProcessItemMore(my_items[i], my_measurement, other_details);
526            ...
527          } else {
528            LOG_ERROR("Found something strange; bailing");
529            return Status::Unknown();
530          }
531        }
532      }
533
534There are cases where this structure doesn't work, and in those cases, it is
535fine to structure the code differently.
536
537No ``else`` after ``return`` or ``continue``
538--------------------------------------------
539Do not put unnecessary ``} else {`` blocks after blocks that terminate with a
540return, since this causes unnecessary rightward indentation creep. This
541guidance pairs with the preference for early exits to reduce code duplication
542and standardize loop/function structure.
543
544.. admonition:: **Yes**: No else after return or continue
545   :class: checkmark
546
547   .. code-block:: cpp
548
549      // Note lack of else block due to return.
550      if (Failure()) {
551        DoTheThing();
552        return Status::ResourceExausted();
553      }
554
555      // Note lack of else block due to continue.
556      while (MyCondition()) {
557        if (SomeEarlyBail()) {
558          continue;
559        }
560        // Main handling of item
561        ...
562      }
563
564      DoOtherThing();
565      return OkStatus();
566
567.. admonition:: **No**: Else after return needlessly creeps right
568   :class: error
569
570   .. code-block:: cpp
571
572      if (Failure()) {
573        DoTheThing();
574        return Status::ResourceExausted();
575      } else {
576        while (MyCondition()) {
577          if (SomeEarlyBail()) {
578            continue;
579          } else {
580            // Main handling of item
581            ...
582          }
583        }
584        DoOtherThing();
585        return OkStatus();
586      }
587
588Error handling
589==============
590Historically, exceptions have been avoided in embedded C++ as well as in general
591C++ code written at Google. Instead, assertions and error codes are used to
592communicate errors with less overhead.
593
594Signal and propagate non-fatal errors with ``pw::Status`` and ``pw::Result``,
595and assert/check for fatal errors.
596
597Add log statements to help with error tracking. See
598:ref:`guidance below <docs-pw-style-cpp-logging>` on how to craft high-value,
599low-noise logs.
600
601.. note:
602
603Like Google's C++ style guide, Pigweed does not use exceptions. The case for
604avoiding exceptions on embedded is primarily due to reducing code size.
605
606Recoverable errors
607------------------
608Use the following to report non-fatal failures from subroutines:
609
610- :cpp:type:`pw::Status`: Zero-overhead type that wraps a
611  :ref:`status code <module-pw_status-quickref>`.
612- :ref:`pw::Result <module-pw_result>`: Union of a status code and a value.
613- :ref:`pw::StatusWithSize <module-pw_status-guide-status-with-size>`: A status
614  combined with a size. Especially useful for operations which may partially
615  succeed, such as a write that sent some bytes before failing.
616
617Fatal errors
618------------
619Use :c:macro:`PW_ASSERT` and the :c:macro:`PW_CHECK` family of macros to halt
620execution on a fatal error.
621
622- These are appropriate when the security of the device is compromised.
623
624  - Example: memory corruption is detected.
625
626.. admonition:: **Yes**
627   :class: checkmark
628
629   .. code-block:: cpp
630
631      PW_CHECK_NOTNULL(item->next);
632      PW_CHECK_PTR_EQ(item, item->next->prev);
633
634- These may be appropriate for instances of unambiguous programmer error.
635
636  - Example: a caller passed a null pointer to a routine that explicitly
637    requires non-null pointers.
638
639.. warning::
640
641   Be very careful about introducing new assertions into existing code, or in
642   code paths that are not exhaustively tested, or any other scenario that may
643   result in crashes in fielded devices.
644
645.. admonition:: **No**: May cause a runtime crash.
646   :class: error
647
648   .. code-block:: cpp
649
650      StatusWithSize sws = kvs.Get("some-key", &out);
651      PW_CHECK_OK(sws.status());
652
653   The key may be missing from the :ref:`KVS <module-pw_kvs>` for a number of
654   reasons. It is likely better to surface this error to a higher level that can
655   decide how to handle a missing value.
656
657Include guards
658==============
659The first non-comment line of every header file must be ``#pragma once``. Do
660not use traditional macro include guards. The ``#pragma once`` should come
661directly after the Pigweed copyright block, with no blank line, followed by a
662blank, like this:
663
664.. code-block:: cpp
665
666   // Copyright 2021 The Pigweed Authors
667   //
668   // Licensed under the Apache License, Version 2.0 (the "License"); you may not
669   // use this file except in compliance with the License. You may obtain a copy of
670   // the License at
671   //
672   //     https://www.apache.org/licenses/LICENSE-2.0
673   //
674   // Unless required by applicable law or agreed to in writing, software
675   // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
676   // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
677   // License for the specific language governing permissions and limitations under
678   // the License.
679   #pragma once
680
681   // Header file-level comment goes here...
682
683.. _docs-pw-style-cpp-logging:
684
685Logging
686=======
687Good logging can be incredibly useful in detecting and debugging errors. Log
688quality is determined by the amount of useful information relative to overall
689amount of logs.
690
691Log in the right spot
692---------------------
693Limiting logs to only the most relevant sections of code can guide developers to
694areas that require debugging.
695
696- **Log errors as soon as they can be umabiguously determined to be errors.** An
697  unambiguous error is one that will be reported to the caller of the module or
698  component. Avoid logging errors that are handled internally by the module or
699  component.
700
701  - Example: A task manager would not log a failure to schedule a specific
702    worker from a pool, but may log the failure to find *any* worker in the
703    pool.
704
705    .. admonition:: **No**: May log errors even if the call eventually succeeds.
706       :class: error
707
708       .. code-block:: cpp
709
710          Status TaskManager::AssignToWorker(Task& task) {
711            for (auto& worker : pool_) {
712              if (worker.AssignTask(task).ok()) {
713                return OkStatus();
714              }
715            }
716            return Status::ResourceExhausted();
717          }
718
719          Status Worker::Assign(Task& task) {
720            if (busy_) {
721              PW_LOG_DEBUG("failed to assign task to worker %zu", id_);
722              return Status::FailedPrecondition();
723            }
724            // ...
725          }
726
727    .. admonition:: **Yes**: Only logs when an actual failure has occurred.
728       :class: checkmark
729
730       .. code-block:: cpp
731
732          Status TaskManager::AssignToWorker(Task& task) {
733            for (auto& worker : pool_) {
734              if (worker.AssignTask(task).ok()) {
735                return OkStatus();
736              }
737            }
738            PW_LOG_DEBUG("failed to find a worker to handle the task");
739            return Status::ResourceExhausted();
740          }
741
742          Status Worker::Assign(Task& task) {
743            if (busy_) {
744              return Status::FailedPrecondition();
745            }
746            // ...
747          }
748
749
750- **Log failures of an overall workflow at the level that it was initiated** to
751  provide context in which an error occurred.
752
753  - Example: A widget may log that it could not perform a user-scheduled task
754    because the task manager returned an error.
755
756- **Limit the use of informational logs of non-failure conditions.** These
757  "heartbeat" logs can quickly accrue and become noise. If needed, keep the
758  frequency of these logs low, e.g. not more than once per second.
759  :c:macro:`PW_LOG_EVERY_N` and :c:macro:`PW_LOG_EVERY_N_DURATION` can be used
760  to rate-limit such logs.
761
762  .. admonition:: **No**: May spew a large number of logs.
763     :class: error
764
765     .. code-block:: cpp
766
767        void OnChunk(const Chunk& chunk) {
768          ++count_;
769          total_ += chunk.size();
770          PW_LOG_DEBUG("Processed %zu chunks totaling %zu bytes", count_, total_);
771          // ...
772        }
773
774  .. admonition:: **Yes**: Only logs once every 10 seconds.
775     :class: checkmark
776
777     .. code-block:: cpp
778
779        void OnChunk(const Packet& packet) {
780          static constexpr auto kLogInterval =
781            chrono::SystemClock::for_at_least(std::chrono::seconds(10));
782          ++count_;
783          total_ += packet.size();
784          PW_LOG_EVERY_N_DURATION(PW_LOG_LEVEL_DEBUG,
785                                  kLogInterval,
786                                  "Processed %zu chunks totaling %zu bytes",
787                                  count_,
788                                  total_);
789        }
790
791Log at the correct level
792------------------------
793:ref:`Log levels <module-pw_log-levels>` indicate the seriousness of a message
794and provide a simple mechanism for conditional logging and for log filtering.
795
796- **Downstream projects should use less filtered log levels**, as
797  project-specific errors more likely indicate an actionable failure.
798
799  - Use :c:macro:`PW_LOG_CRITICAL` for failures that compromise the entire
800    device and will imminently halt or crash the device.
801  - Use :c:macro:`PW_LOG_ERROR` for failures that are more serious or harder to
802    recover from.
803  - Use :c:macro:`PW_LOG_WARN` for failures that are less serious or easier to
804    recover from.
805  - Use :c:macro:`PW_LOG_INFO` for informational logs of non-failure conditions.
806
807- **Libraries and upstream code should allow configurable logging.** Downstream
808  projects may want to disable library and module logging to save on code size,
809  or enable it to aid in debugging.
810
811  - Use :c:macro:`PW_LOG_DEBUG` to log specific errors that the caller is
812    expected to handle.
813
814    .. admonition:: **Yes**
815       :class: checkmark
816
817       .. code-block:: cpp
818
819          if (stream.IsClosed()) {
820            PW_LOG_DEBUG("Stream closed unexpectedly");
821            return Status::OutOfRange();
822          }
823
824  - Use :c:macro:`PW_LOG_INFO` and :c:macro:`PW_LOG_WARN` to communicate error
825    conditions that may not have a caller that can handle them.
826
827    .. admonition:: **Yes**
828       :class: checkmark
829
830       .. code-block:: cpp
831
832          while(!task_queue_.empty()) {
833            Task task = std::move(task_queue_.back());
834            task_queue_.pop_back();
835            if (task.HasExpired()) {
836              PW_LOG_INFO("Task %zu expired before being scheduled", task.id());
837              continue;
838            }
839            Schedule(std::move(task));
840            // ...
841          }
842
843  - Set a :c:macro:`PW_LOG_LEVEL`. If logging in a module with a
844    :ref:`module configuration <module-structure-compile-time-configuration>`,
845    include a logging option and set :c:macro:`PW_LOG_LEVEL` to it.
846
847    .. admonition:: **Yes**
848       :class: checkmark
849
850       .. code-block:: cpp
851
852          // In my_module's config.h. Can be overridden at compile time.
853          #ifndef MY_MODULE_LOG_LEVEL
854          #define MY_MODULE_LOG_LEVEL PW_LOG_LEVEL_WARN
855          #endif MY_MODULE_LOG_LEVEL
856
857          // In my_module's source files.
858          #include "my_module/config.h"
859          #define PW_LOG_LEVEL MY_MODULE_LOG_LEVEL
860
861Log the right information
862-------------------------
863Logging the most useful information requires considering what may be relevant to
864an error and cannot be obtained another way.
865
866- **Include relevant context**, such as function parameters.
867- **Capitalize your log message, but do not end with puncuation.** Log backends
868  typically combine your log message with additional information and format
869  them.
870
871.. admonition:: **No**
872   :class: error
873
874   .. code-block:: cpp
875
876      PW_LOG_DEBUG("the operation did not complete normally.");
877
878.. admonition:: **Yes**
879   :class: checkmark
880
881   .. code-block:: cpp
882
883      PW_LOG_DEBUG("The operation completed normally");
884
885- **Set** :c:macro:`PW_LOG_MODULE_NAME` to include a
886  module name that you can filter on.
887
888.. admonition:: **Yes**
889   :class: checkmark
890
891   .. code-block:: cpp
892
893      #define PW_LOG_MODULE_NAME "my_module"
894
895- **Do not include source location details.** The log backend can be configured
896  to add various :ref:`module-pw_log-logging_attributes` automatically.
897
898.. admonition:: **No**
899   :class: error
900
901   .. code-block:: cpp
902
903      PW_LOG_DEBUG("%s:%d: %s called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
904
905- **Do not log** :cpp:type:`pw::Status` **details.** If you are logging and
906  returning an error as a result of a subroutine that returned an error, it is
907  likely that a log statement can be added closer to where that error was
908  detected.
909
910.. admonition:: **No**
911   :class: error
912
913   .. code-block:: cpp
914
915      Result<Message> ReadAndDecode(Stream& stream) {
916        Result<EncodedMessage> result = ReadEncodedMessage(stream);
917        if (!result.ok()) {
918          Status status = result.status();
919          PW_LOG_DEBUG("Failed to read message: %s",
920                       pw_StatusString(status.code));
921          return status;
922        }
923        // ...
924      }
925
926Memory allocation
927=================
928Dynamic memory allocation can be problematic. Heap allocations and deallocations
929occupy valuable CPU cycles. Memory usage becomes nondeterministic, which can
930result in a system crashing without a clear culprit.
931
932To keep Pigweed portable, core Pigweed code is not permitted to dynamically
933(heap) allocate memory, such as with ``malloc`` or ``new``. All memory should be
934allocated with automatic (stack) or static (global) storage duration. Pigweed
935must not use C++ libraries that use dynamic allocation.
936
937Projects that use Pigweed are free to use dynamic allocation, provided they
938have selected a target that enables the heap.
939
940Naming
941======
942Entities shall be named according to the `Google style guide
943<https://google.github.io/styleguide/cppguide.html>`_, with the following
944additional requirements.
945
946C++ code
947--------
948* All Pigweed C++ code must be in the ``pw`` namespace. Namespaces for modules
949  should be nested under ``pw``. For example, ``pw::string::Format()``.
950* Whenever possible, private code should be in a source (.cc) file and placed in
951  anonymous namespace nested under ``pw``. Unit tests must be declared in an
952  anonymous namespace to avoid potential linking issues when building multiple
953  tests in one binary.
954* If private code must be exposed in a header file, it must be in a namespace
955  nested under ``pw``. The namespace may be named for its subsystem or use a
956  name that designates it as private, such as ``internal``.
957* Template arguments for non-type names (e.g. ``template <int kFooBar>``) should
958  follow the constexpr and const variable Google naming convention, which means
959  k prefixed camel case (e.g.  ``kCamelCase``). This matches the Google C++
960  style for variable naming, however the wording in the official style guide
961  isn't explicit for template arguments and could be interpreted to use
962  ``foo_bar`` style naming.  For consistency with other variables whose value is
963  always fixed for the duration of the program, the naming convention is
964  ``kCamelCase``, and so that is the style we use in Pigweed.
965* Trivial membor accessors should be named with ``snake_case()``. The Google
966  C++ style allows either ``snake_case()`` or ``CapsCase()``, but Pigweed
967  always uses ``snake_case()``.
968* Abstract base classes should be named generically, with derived types named
969  specifically. For example, ``Stream`` is an abstract base, and
970  ``SocketStream`` and ``StdioStream`` are an implementations of that
971  interface.  Any prefix or postfix indicating whether something is abstract or
972  concrete is not permitted; for example, ``IStream`` or ``SocketStreamImpl``
973  are both not permitted. These pre-/post-fixes add additional visual noise and
974  are irrelevant to consumers of these interfaces.
975
976C code
977------
978In general, C symbols should be prefixed with the module name. If the symbol is
979not associated with a module, use just ``pw`` as the module name. Facade
980backends may chose to prefix symbols with the facade's name to help reduce the
981length of the prefix.
982
983* Public names used by C code must be prefixed with the module name (e.g.
984  ``pw_tokenizer_*``).
985* If private code must be exposed in a header, private names used by C code must
986  be prefixed with an underscore followed by the module name (e.g.
987  ``_pw_assert_*``).
988* Avoid writing C source (.c) files in Pigweed. Prefer to write C++ code with C
989  linkage using ``extern "C"``. Within C source, private C functions and
990  variables must be named with the ``_pw_my_module_*`` prefix and should be
991  declared ``static`` whenever possible; for example,
992  ``_pw_my_module_MyPrivateFunction``.
993* The C prefix rules apply to
994
995  * C functions (``int pw_foo_FunctionName(void);``),
996  * variables used by C code (``int pw_foo_variable_name;``),
997  * constant variables used by C code (``const int pw_foo_kConstantName;``),
998  * structs used by C code (``typedef struct {} pw_foo_StructName;``), and
999  * all of the above for ``extern "C"`` names in C++ code.
1000
1001  The prefix does not apply to struct members, which use normal Google style.
1002
1003Preprocessor macros
1004-------------------
1005* Public Pigweed macros must be prefixed with the module name (e.g.
1006  ``PW_MY_MODULE_*``).
1007* Private Pigweed macros must be prefixed with an underscore followed by the
1008  module name (e.g. ``_PW_MY_MODULE_*``). (This style may change, see
1009  `b/234886184 <https://issuetracker.google.com/issues/234886184>`_).
1010
1011**Example**
1012
1013.. code-block:: cpp
1014
1015   namespace pw::my_module {
1016   namespace nested_namespace {
1017
1018   // C++ names (types, variables, functions) must be in the pw namespace.
1019   // They are named according to the Google style guide.
1020   constexpr int kGlobalConstant = 123;
1021
1022   // Prefer using functions over extern global variables.
1023   extern int global_variable;
1024
1025   class Class {};
1026
1027   void Function();
1028
1029   extern "C" {
1030
1031   // Public Pigweed code used from C must be prefixed with pw_.
1032   extern const int pw_my_module_kGlobalConstant;
1033
1034   extern int pw_my_module_global_variable;
1035
1036   void pw_my_module_Function(void);
1037
1038   typedef struct {
1039     int member_variable;
1040   } pw_my_module_Struct;
1041
1042   // Private Pigweed code used from C must be prefixed with _pw_.
1043   extern const int _pw_my_module_kPrivateGlobalConstant;
1044
1045   extern int _pw_my_module_private_global_variable;
1046
1047   void _pw_my_module_PrivateFunction(void);
1048
1049   typedef struct {
1050     int member_variable;
1051   } _pw_my_module_PrivateStruct;
1052
1053   }  // extern "C"
1054
1055   // Public macros must be prefixed with PW_.
1056   #define PW_MY_MODULE_PUBLIC_MACRO(arg) arg
1057
1058   // Private macros must be prefixed with _PW_.
1059   #define _PW_MY_MODULE_PRIVATE_MACRO(arg) arg
1060
1061   }  // namespace nested_namespace
1062   }  // namespace pw::my_module
1063
1064See :ref:`docs-pw-style-macros` for details about macro usage.
1065
1066Namespace scope formatting
1067==========================
1068All non-indented blocks (namespaces, ``extern "C"`` blocks, and preprocessor
1069conditionals) must have a comment on their closing line with the
1070contents of the starting line.
1071
1072All nested namespaces should be declared together with no blank lines between
1073them.
1074
1075.. code-block:: cpp
1076
1077   #include "some/header.h"
1078
1079   namespace pw::nested {
1080   namespace {
1081
1082   constexpr int kAnonConstantGoesHere = 0;
1083
1084   }  // namespace
1085
1086   namespace other {
1087
1088   const char* SomeClass::yes = "no";
1089
1090   bool ThisIsAFunction() {
1091   #if PW_CONFIG_IS_SET
1092     return true;
1093   #else
1094     return false;
1095   #endif  // PW_CONFIG_IS_SET
1096   }
1097
1098   extern "C" {
1099
1100   const int pw_kSomeConstant = 10;
1101   int pw_some_global_variable = 600;
1102
1103   void pw_CFunction() { ... }
1104
1105   }  // extern "C"
1106
1107   }  // namespace
1108   }  // namespace pw::nested
1109
1110Using directives for literals
1111=============================
1112`Using-directives
1113<https://en.cppreference.com/w/cpp/language/namespace#Using-directives>`_ (e.g.
1114``using namespace ...``) are permitted in implementation files only for the
1115purposes of importing literals such as ``std::chrono_literals`` or
1116``pw::bytes::unit_literals``. Namespaces that contain any symbols other than
1117literals are not permitted in a using-directive. This guidance also has no
1118impact on `using-declarations
1119<https://en.cppreference.com/w/cpp/language/namespace#Using-declarations>`_
1120(e.g. ``using foo::Bar;``).
1121
1122Rationale: Literals improve code readability, making units clearer at the point
1123of definition.
1124
1125.. code-block:: cpp
1126
1127   using namespace std::chrono;                    // Not allowed
1128   using namespace std::literals::chrono_literals; // Allowed
1129
1130   constexpr std::chrono::duration delay = 250ms;
1131
1132Pointers and references
1133=======================
1134For pointer and reference types, place the asterisk or ampersand next to the
1135type.
1136
1137.. code-block:: cpp
1138
1139   int* const number = &that_thing;
1140   constexpr const char* kString = "theory!"
1141
1142   bool FindTheOneRing(const Region& where_to_look) { ... }
1143
1144Prefer storing references over storing pointers. Pointers are required when the
1145pointer can change its target or may be ``nullptr``. Otherwise, a reference or
1146const reference should be used.
1147
1148.. _docs-pw-style-macros:
1149
1150Preprocessor macros
1151===================
1152Macros should only be used when they significantly improve upon the C++ code
1153they replace. Macros should make code more readable, robust, and safe, or
1154provide features not possible with standard C++, such as stringification, line
1155number capturing, or conditional compilation. When possible, use C++ constructs
1156like constexpr variables in place of macros. Never use macros as constants,
1157except when a string literal is needed or the value must be used by C code.
1158
1159When macros are needed, the macros should be accompanied with extensive tests
1160to ensure the macros are hard to use wrong.
1161
1162Stand-alone statement macros
1163----------------------------
1164Macros that are standalone statements must require the caller to terminate the
1165macro invocation with a semicolon (see `Swalling the Semicolon
1166<https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html>`_). For
1167example, the following does *not* conform to Pigweed's macro style:
1168
1169.. code-block:: cpp
1170
1171   // BAD! Definition has built-in semicolon.
1172   #define PW_LOG_IF_BAD(mj) \
1173     CallSomeFunction(mj);
1174
1175   // BAD! Compiles without error; semicolon is missing.
1176   PW_LOG_IF_BAD("foo")
1177
1178Here's how to do this instead:
1179
1180.. code-block:: cpp
1181
1182   // GOOD; requires semicolon to compile.
1183   #define PW_LOG_IF_BAD(mj) \
1184     CallSomeFunction(mj)
1185
1186   // GOOD; fails to compile due to lacking semicolon.
1187   PW_LOG_IF_BAD("foo")
1188
1189For macros in function scope that do not already require a semicolon, the
1190contents can be placed in a ``do { ... } while (0)`` loop.
1191
1192.. code-block:: cpp
1193
1194   #define PW_LOG_IF_BAD(mj)  \
1195     do {                     \
1196       if (mj.Bad()) {        \
1197         Log(#mj " is bad")   \
1198       }                      \
1199     } while (0)
1200
1201Standalone macros at global scope that do not already require a semicolon can
1202add a ``static_assert`` declaration statement as their last line.
1203
1204.. code-block:: cpp
1205
1206   #define PW_NEAT_THING(thing)             \
1207     bool IsNeat_##thing() { return true; } \
1208     static_assert(true, "Macros must be terminated with a semicolon")
1209
1210Private macros in public headers
1211--------------------------------
1212Private macros in public headers must be prefixed with ``_PW_``, even if they
1213are undefined after use; this prevents collisions with downstream users. For
1214example:
1215
1216.. code-block:: cpp
1217
1218   #define _PW_MY_SPECIAL_MACRO(op) ...
1219   ...
1220   // Code that uses _PW_MY_SPECIAL_MACRO()
1221   ...
1222   #undef _PW_MY_SPECIAL_MACRO
1223
1224Macros in private implementation files (.cc)
1225--------------------------------------------
1226Macros within .cc files that should only be used within one file should be
1227undefined after their last use; for example:
1228
1229.. code-block:: cpp
1230
1231   #define DEFINE_OPERATOR(op) \
1232     T operator ## op(T x, T y) { return x op y; } \
1233     static_assert(true, "Macros must be terminated with a semicolon") \
1234
1235   DEFINE_OPERATOR(+);
1236   DEFINE_OPERATOR(-);
1237   DEFINE_OPERATOR(/);
1238   DEFINE_OPERATOR(*);
1239
1240   #undef DEFINE_OPERATOR
1241
1242Preprocessor conditional statements
1243===================================
1244When using macros for conditional compilation, prefer to use ``#if`` over
1245``#ifdef``. This checks the value of the macro rather than whether it exists.
1246
1247* ``#if`` handles undefined macros equivalently to ``#ifdef``. Undefined
1248  macros expand to 0 in preprocessor conditional statements.
1249* ``#if`` evaluates false for macros defined as 0, while ``#ifdef`` evaluates
1250  true.
1251* Macros defined using compiler flags have a default value of 1 in GCC and
1252  Clang, so they work equivalently for ``#if`` and ``#ifdef``.
1253* Macros defined to an empty statement cause compile-time errors in ``#if``
1254  statements, which avoids ambiguity about how the macro should be used.
1255
1256All ``#endif`` statements should be commented with the expression from their
1257corresponding ``#if``. Do not indent within preprocessor conditional statements.
1258
1259.. code-block:: cpp
1260
1261   #if USE_64_BIT_WORD
1262   using Word = uint64_t;
1263   #else
1264   using Word = uint32_t;
1265   #endif  // USE_64_BIT_WORD
1266
1267Unsigned integers
1268=================
1269Unsigned integers are permitted in Pigweed. Aim for consistency with existing
1270code and the C++ Standard Library. Be very careful mixing signed and unsigned
1271integers.
1272
1273Features not in the C++ standard
1274================================
1275Avoid features not available in standard C++. This includes compiler extensions
1276and features from other standards like POSIX.
1277
1278For example, use ``ptrdiff_t`` instead of POSIX's ``ssize_t``, unless
1279interacting with a POSIX API in intentionally non-portable code. Never use
1280POSIX functions with suitable standard or Pigweed alternatives, such as
1281``strnlen`` (use ``pw::string::NullTerminatedLength`` instead).
1282