151 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
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.
 |