| libfit |
| |
| Source: https://fuchsia.googlesource.com/fuchsia/+/main/sdk/lib/fit/ |
| Version: 36303cd2d1611cb1b670235692d01a92e83ecd21 |
| License: |
| |
| Copyright 2019 The Fuchsia Authors. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are |
| met: |
| |
| * Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| * Redistributions in binary form must reproduce the above |
| copyright notice, this list of conditions and the following disclaimer |
| in the documentation and/or other materials provided with the |
| distribution. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| ====== |
| |
| FIT is a lean library of portable C++ abstractions for control flow and |
| memory management beyond what is offered by the C++ 17 standard library. |
| |
| FIT only depends on the C++ language and standard library, including some C++17 |
| library features. It offers essential enhancements to the C++ standard library |
| rather than attempting to replace it or become a framework for writing |
| applications. FIT can be thought of as an "annex" that expresses a few ideas |
| we wish the C++ standard library might itself implement someday. |
| |
| FIT is lean. |
| |
| ## What Belongs in FIT |
| |
| Several Fuchsia SDK libraries, such as *libfidl*, depend on FIT and on the C++ |
| standard library. As these libraries are broadly used, we must take care in |
| deciding what features to include in FIT to avoid burdening developers with |
| unnecessary code or dependencies. |
| |
| In general, the goal is to identify specific abstractions that make sense to |
| generalize across the entire ecosystem of Fuchsia C++ applications. These will |
| necessarily be somewhat low-level but high impact. We don't want to add code to |
| FIT simply because we think it's cool. We need evidence that it is a common |
| idiom and that a broad audience of developers will significantly benefit from |
| its promotion. |
| |
| Here are a few criteria to consider: |
| |
| - Is the feature lightweight, general-purpose, and platform-independent? |
| - Is the feature not well served by other means, particularly by the C++ |
| standard library? |
| - Is the feature needed by a Fuchsia SDK library? |
| - Does the feature embody a beneficial idiom that clients of the Fuchsia SDK |
| commonly use? |
| - Has the feature been re-implemented many times already leading to code |
| fragmentation that we would like to eliminate? |
| |
| If in doubt, leave it out. See [Justifications] below. |
| |
| ## What Doesn't Belong in FIT |
| |
| FIT is not intended to become a catch-all class library. |
| |
| Specifically prohibited features: |
| |
| - Features that introduce dependencies on libraries other than the C and C++ |
| standard library. |
| - Features that only work on certain operating systems. |
| - Collection classes where the C++ 17 standard library already offers an |
| adequate (if not perfect) alternative. |
| - Classes that impose an implementation burden on clients such as event loops, |
| dispatchers, frameworks, and other glue code. |
| |
| ## Implementation Considerations |
| |
| FIT is not exception safe (but could be made to be in the future). |
| |
| ## Style Conventions |
| |
| The API style was modified to fit current android::base library conventions. |
| |
| In brief: |
| |
| - Class identifiers are CamelCase |
| - Class methods and variable identifiers use "camelCase", class fields use |
| "mCamelCase". |
| - Template parameters are `CamelCase`. |
| - Preprocessor macros are `UPPER_SNAKE_CASE`. |
| |
| ## Justifications |
| |
| These sections explain why certain features are in FIT. |
| |
| ### fit::Function |
| |
| - *libfidl*'s API needs a callable function wrapper with move semantics but |
| C++ 14's `std::function` only supports copyable function objects which forces |
| FIDL to allocate callback state on the heap making programs less efficient |
| and harder to write. |
| - Lots of other C++ code uses callbacks extensively and would benefit from move |
| semantics for similar reasons. |
| - So we should create a move-only function wrapper to use everywhere. |
| |
| ### fit::Defer |
| |
| - When writing asynchronous event-driven programs, it can become challenging |
| to ensure that resources remain in scope for the duration of an operation |
| in progress and are subsequently released. |
| - The C++ 14 standard library offers several classes with RAII semantics, such |
| as `std::unique_ptr`, which are helpful in these situations. Unfortunately the |
| C++ 14 standard library does not offer affordances for easily invoking a |
| function when a block or object goes out of scope short of implementing a |
| new class from scratch. |
| - We have observed several re-implementations of the same idea throughout the |
| system. |
| - So we should create a simple way to invoke a function on scope exit. |
| |
| ### fit::Nullable |
| |
| - Case study: fit::defer has a need to store a closure that may be nullable. |
| We were able to replace its hand-rolled lifetime management code with |
| fit::nullable thereby vastly simplifying its implementation. |
| - Case study: fit::future has a need to track its own validity along with |
| a continuation that may or not be present. |
| - Case study: We have previously observed bugs where developers were |
| surprised when assigning a null closure to wrappers such as fit::function |
| fit::defer, or fit::future left these objects in a supposedly "valid" |
| but uninvocable state. These objects therefore take care to detect |
| null closures and enter an "invalid" state. Using fit::is_null and |
| fit::nullable makes it easier to eliminate this redundant state and |
| simplifies the API for clients of these wrappers. |
| - std::optional can be effective here but it doesn't directly handle nullity |
| so it takes more care to coalesce the null and "not present" states. |
| std::optional also increases the size of the object to carry an extra |
| bool and passing, whereas fit::nullable eliminates this overhead by |
| taking advantage of the underlying value's null state (if there is one). |
| - So we introduce fit::nullable to handle both cases systematically while |
| still hewing close to the semantics of std::optional. |