Home | History | Annotate | Download | only in include
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef C2_H_
     18 #define C2_H_
     19 
     20 #include <errno.h>
     21 
     22 #include <string>
     23 
     24 /** nanoseconds with arbitrary origin. */
     25 typedef int64_t c2_nsecs_t;
     26 
     27 /** \mainpage Codec2
     28  *
     29  * Codec2 is a generic frame-based data processing API.
     30  *
     31  * The media subsystem accesses components via the \ref API.
     32  */
     33 
     34 /** \ingroup API
     35  *
     36  * The Codec2 API defines the operation of data processing components and their interaction with
     37  * the rest of the system.
     38  *
     39  * Coding Conventions
     40  *
     41  * Mitigating Binary Compatibility.
     42  *
     43  * While full binary compatibility is not a goal of the API (due to our use of STL), we try to
     44  * mitigate binary breaks by adhering to the following conventions:
     45  *
     46  * - at most one vtable with placeholder virtual methods
     47  * - all optional/placeholder virtual methods returning a c2_status_t, with C2_OMITTED not requiring
     48  *   any update to input/output arguments.
     49  * - limiting symbol export of inline methods
     50  * - use of pimpl (or shared-pimpl)
     51  *
     52  * Naming
     53  *
     54  * - all classes and types prefix with C2
     55  * - classes for internal use prefix with _C2
     56  * - enum values in global namespace prefix with C2_ all caps
     57  * - enum values inside classes have no C2_ prefix as class already has it
     58  * - supporting two kinds of enum naming: all-caps and kCamelCase
     59  * \todo revisit kCamelCase for param-type
     60  *
     61  * Aspects
     62  *
     63  * Aspects define certain common behavior across a group of objects.
     64  * - classes whose name matches _C2.*Aspect
     65  * - only protected constructors
     66  * - no desctructor and copiable
     67  * - all methods are inline or static (this is opposite of the interface paradigm where all methods
     68  *   are virtual, which would not work due to the at most one vtable rule.)
     69  * - only private variables (this prevents subclasses interfering with the aspects.)
     70  */
     71 
     72 /// \defgroup types Common Types
     73 /// @{
     74 
     75 /**
     76  * C2String: basic string implementation
     77  */
     78 typedef std::string C2String;
     79 
     80 /**
     81  * C2StringLiteral: basic string literal implementation.
     82  * \note these are never owned by any object, and can only refer to C string literals.
     83  */
     84 typedef const char *C2StringLiteral;
     85 
     86 /**
     87  * c2_status_t: status codes used.
     88  */
     89 enum c2_status_t : int32_t {
     90 /*
     91  * Use POSIX errno constants.
     92  */
     93     C2_OK        = 0,            ///< operation completed successfully
     94 
     95     // bad input
     96     C2_BAD_VALUE = EINVAL,       ///< argument has invalid value (user error)
     97     C2_BAD_INDEX = ENXIO,        ///< argument uses invalid index (user error)
     98     C2_CANNOT_DO = ENOTSUP,      ///< argument/index is valid but not possible
     99 
    100     // bad sequencing of events
    101     C2_DUPLICATE = EEXIST,       ///< object already exists
    102     C2_NOT_FOUND = ENOENT,       ///< object not found
    103     C2_BAD_STATE = EPERM,        ///< operation is not permitted in the current state
    104     C2_BLOCKING  = EWOULDBLOCK,  ///< operation would block but blocking is not permitted
    105     C2_CANCELED  = EINTR,        ///< operation interrupted/canceled
    106 
    107     // bad environment
    108     C2_NO_MEMORY = ENOMEM,       ///< not enough memory to complete operation
    109     C2_REFUSED   = EACCES,       ///< missing permission to complete operation
    110 
    111     C2_TIMED_OUT = ETIMEDOUT,    ///< operation did not complete within timeout
    112 
    113     // bad versioning
    114     C2_OMITTED   = ENOSYS,       ///< operation is not implemented/supported (optional only)
    115 
    116     // unknown fatal
    117     C2_CORRUPTED = EFAULT,       ///< some unexpected error prevented the operation
    118     C2_NO_INIT   = ENODEV,       ///< status has not been initialized
    119 };
    120 
    121 /**
    122  * Type that describes the desired blocking behavior for variable blocking calls. Blocking in this
    123  * API is used in a somewhat modified meaning such that operations that merely update variables
    124  * protected by mutexes are still considered "non-blocking" (always used in quotes).
    125  */
    126 enum c2_blocking_t : int32_t {
    127     /**
    128      * The operation SHALL be "non-blocking". This means that it shall not perform any file
    129      * operations, or call/wait on other processes. It may use a protected region as long as the
    130      * mutex is never used to protect code that is otherwise "may block".
    131      */
    132     C2_DONT_BLOCK = false,
    133     /**
    134      * The operation MAY be temporarily blocking.
    135      */
    136     C2_MAY_BLOCK = true,
    137 };
    138 
    139 /// @}
    140 
    141 /// \defgroup utils Utilities
    142 /// @{
    143 
    144 #define C2_DO_NOT_COPY(type) \
    145     type& operator=(const type &) = delete; \
    146     type(const type &) = delete; \
    147 
    148 #define C2_DEFAULT_MOVE(type) \
    149     type& operator=(type &&) = default; \
    150     type(type &&) = default; \
    151 
    152 #define C2_ALLOW_OVERFLOW __attribute__((no_sanitize("integer")))
    153 #define C2_CONST    __attribute__((const))
    154 #define C2_HIDE     __attribute__((visibility("hidden")))
    155 #define C2_INLINE   inline C2_HIDE
    156 #define C2_INTERNAL __attribute__((internal_linkage))
    157 #define C2_PACK     __attribute__((aligned(4)))
    158 #define C2_PURE     __attribute__((pure))
    159 
    160 #define DEFINE_OTHER_COMPARISON_OPERATORS(type) \
    161     inline bool operator!=(const type &other) const { return !(*this == other); } \
    162     inline bool operator<=(const type &other) const { return (*this == other) || (*this < other); } \
    163     inline bool operator>=(const type &other) const { return !(*this < other); } \
    164     inline bool operator>(const type &other) const { return !(*this < other) && !(*this == other); }
    165 
    166 #define DEFINE_FIELD_BASED_COMPARISON_OPERATORS(type, field) \
    167     inline bool operator<(const type &other) const { return field < other.field; } \
    168     inline bool operator==(const type &other) const { return field == other.field; } \
    169     DEFINE_OTHER_COMPARISON_OPERATORS(type)
    170 
    171 #define DEFINE_FIELD_AND_MASK_BASED_COMPARISON_OPERATORS(type, field, mask) \
    172     inline bool operator<(const type &other) const { \
    173         return (field & mask) < (other.field & (mask)); \
    174     } \
    175     inline bool operator==(const type &other) const { \
    176         return (field & mask) == (other.field & (mask)); \
    177     } \
    178     DEFINE_OTHER_COMPARISON_OPERATORS(type)
    179 
    180 #define DEFINE_ENUM_OPERATORS(etype) \
    181     inline constexpr etype operator|(etype a, etype b) { return (etype)(std::underlying_type<etype>::type(a) | std::underlying_type<etype>::type(b)); } \
    182     inline constexpr etype &operator|=(etype &a, etype b) { a = (etype)(std::underlying_type<etype>::type(a) | std::underlying_type<etype>::type(b)); return a; } \
    183     inline constexpr etype operator&(etype a, etype b) { return (etype)(std::underlying_type<etype>::type(a) & std::underlying_type<etype>::type(b)); } \
    184     inline constexpr etype &operator&=(etype &a, etype b) { a = (etype)(std::underlying_type<etype>::type(a) & std::underlying_type<etype>::type(b)); return a; } \
    185     inline constexpr etype operator^(etype a, etype b) { return (etype)(std::underlying_type<etype>::type(a) ^ std::underlying_type<etype>::type(b)); } \
    186     inline constexpr etype &operator^=(etype &a, etype b) { a = (etype)(std::underlying_type<etype>::type(a) ^ std::underlying_type<etype>::type(b)); return a; } \
    187     inline constexpr etype operator~(etype a) { return (etype)(~std::underlying_type<etype>::type(a)); }
    188 
    189 template<typename T, typename B>
    190 class C2_HIDE c2_cntr_t;
    191 
    192 /// \cond INTERNAL
    193 
    194 /// \defgroup utils_internal
    195 /// @{
    196 
    197 template<typename T>
    198 struct C2_HIDE _c2_cntr_compat_helper {
    199     template<typename U, typename E=typename std::enable_if<std::is_integral<U>::value>::type>
    200     C2_ALLOW_OVERFLOW
    201     inline static constexpr T get(const U &value) {
    202         return T(value);
    203     }
    204 
    205     template<typename U, typename E=typename std::enable_if<(sizeof(U) >= sizeof(T))>::type>
    206     C2_ALLOW_OVERFLOW
    207     inline static constexpr T get(const c2_cntr_t<U, void> &value) {
    208         return T(value.mValue);
    209     }
    210 };
    211 
    212 /// @}
    213 
    214 /// \endcond
    215 
    216 /**
    217  * Integral counter type.
    218  *
    219  * This is basically an unsigned integral type that is NEVER checked for overflow/underflow - and
    220  * comparison operators are redefined.
    221  *
    222  * \note Comparison of counter types is not fully transitive, e.g.
    223  * it could be that a > b > c but a !> c.
    224  * std::less<>, greater<>, less_equal<> and greater_equal<> specializations yield total ordering,
    225  * but may not match semantic ordering of the values.
    226  *
    227  * Technically: counter types represent integer values: A * 2^N + value, where A can be arbitrary.
    228  * This makes addition, subtraction, multiplication (as well as bitwise operations) well defined.
    229  * However, division is in general not well defined, as the result may depend on A. This is also
    230  * true for logical operators and boolean conversion.
    231  *
    232  * Even though well defined, bitwise operators are not implemented for counter types as they are not
    233  * meaningful.
    234  */
    235 template<typename T, typename B=typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type>
    236 class C2_HIDE c2_cntr_t {
    237     using compat = _c2_cntr_compat_helper<T>;
    238 
    239     T mValue;
    240     constexpr static T HALF_RANGE = T(~0) ^ (T(~0) >> 1);
    241 
    242     template<typename U>
    243     friend struct _c2_cntr_compat_helper;
    244 public:
    245 
    246     /**
    247      * Default constructor. Initialized counter to 0.
    248      */
    249     inline constexpr c2_cntr_t() : mValue(T(0)) {}
    250 
    251     /**
    252      * Construct from a compatible type.
    253      */
    254     template<typename U>
    255     inline constexpr c2_cntr_t(const U &value) : mValue(compat::get(value)) {}
    256 
    257     /**
    258      * Peek as underlying signed type.
    259      */
    260     C2_ALLOW_OVERFLOW
    261     inline constexpr typename std::make_signed<T>::type peek() const {
    262         return static_cast<typename std::make_signed<T>::type>(mValue);
    263     }
    264 
    265     /**
    266      * Peek as underlying unsigned type.
    267      */
    268     inline constexpr T peeku() const {
    269         return mValue;
    270     }
    271 
    272     /**
    273      * Peek as long long - e.g. for printing.
    274      */
    275     C2_ALLOW_OVERFLOW
    276     inline constexpr long long peekll() const {
    277         return (long long)mValue;
    278     }
    279 
    280     /**
    281      * Peek as unsigned long long - e.g. for printing.
    282      */
    283     C2_ALLOW_OVERFLOW
    284     inline constexpr unsigned long long peekull() const {
    285         return (unsigned long long)mValue;
    286     }
    287 
    288     /**
    289      * Convert to a smaller counter type. This is always safe.
    290      */
    291     template<typename U, typename E=typename std::enable_if<(sizeof(U) < sizeof(T))>::type>
    292     inline operator c2_cntr_t<U>() {
    293         return c2_cntr_t<U>(mValue);
    294     }
    295 
    296     /**
    297      * Arithmetic operators
    298      */
    299 
    300 #define DEFINE_C2_CNTR_BINARY_OP(attrib, op, op_assign) \
    301     template<typename U> \
    302     attrib inline c2_cntr_t<T>& operator op_assign(const U &value) { \
    303         mValue op_assign compat::get(value); \
    304         return *this; \
    305     } \
    306     \
    307     template<typename U, typename E=decltype(compat::get(U(0)))> \
    308     attrib inline constexpr c2_cntr_t<T> operator op(const U &value) const { \
    309         return c2_cntr_t<T>(mValue op compat::get(value)); \
    310     } \
    311     \
    312     template<typename U, typename E=typename std::enable_if<(sizeof(U) < sizeof(T))>::type> \
    313     attrib inline constexpr c2_cntr_t<U> operator op(const c2_cntr_t<U> &value) const { \
    314         return c2_cntr_t<U>(U(mValue) op value.peeku()); \
    315     }
    316 
    317 #define DEFINE_C2_CNTR_UNARY_OP(attrib, op) \
    318     attrib inline constexpr c2_cntr_t<T> operator op() const { \
    319         return c2_cntr_t<T>(op mValue); \
    320     }
    321 
    322 #define DEFINE_C2_CNTR_CREMENT_OP(attrib, op) \
    323     attrib inline c2_cntr_t<T> &operator op() { \
    324         op mValue; \
    325         return *this; \
    326     } \
    327     attrib inline c2_cntr_t<T> operator op(int) { \
    328         return c2_cntr_t<T, void>(mValue op); \
    329     }
    330 
    331     DEFINE_C2_CNTR_BINARY_OP(C2_ALLOW_OVERFLOW, +, +=)
    332     DEFINE_C2_CNTR_BINARY_OP(C2_ALLOW_OVERFLOW, -, -=)
    333     DEFINE_C2_CNTR_BINARY_OP(C2_ALLOW_OVERFLOW, *, *=)
    334 
    335     DEFINE_C2_CNTR_UNARY_OP(C2_ALLOW_OVERFLOW, -)
    336     DEFINE_C2_CNTR_UNARY_OP(C2_ALLOW_OVERFLOW, +)
    337 
    338     DEFINE_C2_CNTR_CREMENT_OP(C2_ALLOW_OVERFLOW, ++)
    339     DEFINE_C2_CNTR_CREMENT_OP(C2_ALLOW_OVERFLOW, --)
    340 
    341     template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type>
    342     C2_ALLOW_OVERFLOW
    343     inline constexpr c2_cntr_t<T> operator<<(const U &value) const {
    344         return c2_cntr_t<T>(mValue << value);
    345     }
    346 
    347     template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type>
    348     C2_ALLOW_OVERFLOW
    349     inline c2_cntr_t<T> &operator<<=(const U &value) {
    350         mValue <<= value;
    351         return *this;
    352     }
    353 
    354     /**
    355      * Comparison operators
    356      */
    357     C2_ALLOW_OVERFLOW
    358     inline constexpr bool operator<=(const c2_cntr_t<T> &other) const {
    359         return T(other.mValue - mValue) < HALF_RANGE;
    360     }
    361 
    362     C2_ALLOW_OVERFLOW
    363     inline constexpr bool operator>=(const c2_cntr_t<T> &other) const {
    364         return T(mValue - other.mValue) < HALF_RANGE;
    365     }
    366 
    367     inline constexpr bool operator==(const c2_cntr_t<T> &other) const {
    368         return mValue == other.mValue;
    369     }
    370 
    371     inline constexpr bool operator!=(const c2_cntr_t<T> &other) const {
    372         return !(*this == other);
    373     }
    374 
    375     inline constexpr bool operator<(const c2_cntr_t<T> &other) const {
    376         return *this <= other && *this != other;
    377     }
    378 
    379     inline constexpr bool operator>(const c2_cntr_t<T> &other) const {
    380         return *this >= other && *this != other;
    381     }
    382 };
    383 
    384 template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type>
    385 inline constexpr c2_cntr_t<T> operator+(const U &a, const c2_cntr_t<T> &b) {
    386     return b + a;
    387 }
    388 
    389 template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type>
    390 inline constexpr c2_cntr_t<T> operator-(const U &a, const c2_cntr_t<T> &b) {
    391     return c2_cntr_t<T>(a) - b;
    392 }
    393 
    394 template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type>
    395 inline constexpr c2_cntr_t<T> operator*(const U &a, const c2_cntr_t<T> &b) {
    396     return b * a;
    397 }
    398 
    399 typedef c2_cntr_t<uint32_t> c2_cntr32_t; /** 32-bit counter type */
    400 typedef c2_cntr_t<uint64_t> c2_cntr64_t; /** 64-bit counter type */
    401 
    402 /// \cond INTERNAL
    403 
    404 /// \defgroup utils_internal
    405 /// @{
    406 
    407 template<typename... T> struct c2_types;
    408 
    409 /** specialization for a single type */
    410 template<typename T>
    411 struct c2_types<T> {
    412     typedef typename std::decay<T>::type wide_type;
    413     typedef wide_type narrow_type;
    414     typedef wide_type min_type; // type for min(T...)
    415 };
    416 
    417 /** specialization for two types */
    418 template<typename T, typename U>
    419 struct c2_types<T, U> {
    420     static_assert(std::is_floating_point<T>::value == std::is_floating_point<U>::value,
    421                   "mixing floating point and non-floating point types is disallowed");
    422     static_assert(std::is_signed<T>::value == std::is_signed<U>::value,
    423                   "mixing signed and unsigned types is disallowed");
    424 
    425     typedef typename std::decay<
    426             decltype(true ? std::declval<T>() : std::declval<U>())>::type wide_type;
    427     typedef typename std::decay<
    428             typename std::conditional<sizeof(T) < sizeof(U), T, U>::type>::type narrow_type;
    429     typedef typename std::conditional<
    430             std::is_signed<T>::value, wide_type, narrow_type>::type min_type;
    431 };
    432 
    433 /// @}
    434 
    435 /// \endcond
    436 
    437 /**
    438  * Type support utility class. Only supports similar classes, such as:
    439  * - all floating point
    440  * - all unsigned/all signed
    441  * - all pointer
    442  */
    443 template<typename T, typename U, typename... V>
    444 struct c2_types<T, U, V...> {
    445     /** Common type that accommodates all template parameter types. */
    446     typedef typename c2_types<typename c2_types<T, U>::wide_type, V...>::wide_type wide_type;
    447     /** Narrowest type of the template parameter types. */
    448     typedef typename c2_types<typename c2_types<T, U>::narrow_type, V...>::narrow_type narrow_type;
    449     /** Type that accommodates the minimum value for any input for the template parameter types. */
    450     typedef typename c2_types<typename c2_types<T, U>::min_type, V...>::min_type min_type;
    451 };
    452 
    453 /**
    454  *  \ingroup utils_internal
    455  * specialization for two values */
    456 template<typename T, typename U>
    457 inline constexpr typename c2_types<T, U>::wide_type c2_max(const T a, const U b) {
    458     typedef typename c2_types<T, U>::wide_type wide_type;
    459     return ({ wide_type a_(a), b_(b); a_ > b_ ? a_ : b_; });
    460 }
    461 
    462 /**
    463  * Finds the maximum value of a list of "similarly typed" values.
    464  *
    465  * This is an extension to std::max where the types do not have to be identical, and the smallest
    466  * resulting type is used that accommodates the argument types.
    467  *
    468  * \note Value types must be similar, e.g. all floating point, all pointers, all signed, or all
    469  * unsigned.
    470  *
    471  * @return the largest of the input arguments.
    472  */
    473 template<typename T, typename U, typename... V>
    474 constexpr typename c2_types<T, U, V...>::wide_type c2_max(const T a, const U b, const V ... c) {
    475     typedef typename c2_types<T, U, V...>::wide_type wide_type;
    476     return ({ wide_type a_(a), b_(c2_max(b, c...)); a_ > b_ ? a_ : b_; });
    477 }
    478 
    479 /**
    480  *  \ingroup utils_internal
    481  * specialization for two values */
    482 template<typename T, typename U>
    483 inline constexpr typename c2_types<T, U>::min_type c2_min(const T a, const U b) {
    484     typedef typename c2_types<T, U>::wide_type wide_type;
    485     return ({
    486         wide_type a_(a), b_(b);
    487         static_cast<typename c2_types<T, U>::min_type>(a_ < b_ ? a_ : b_);
    488     });
    489 }
    490 
    491 /**
    492  * Finds the minimum value of a list of "similarly typed" values.
    493  *
    494  * This is an extension to std::min where the types do not have to be identical, and the smallest
    495  * resulting type is used that accommodates the argument types.
    496  *
    497  * \note Value types must be similar, e.g. all floating point, all pointers, all signed, or all
    498  * unsigned.
    499  *
    500  * @return the smallest of the input arguments.
    501  */
    502 template<typename T, typename U, typename... V>
    503 constexpr typename c2_types<T, U, V...>::min_type c2_min(const T a, const U b, const V ... c) {
    504     typedef typename c2_types<U, V...>::min_type rest_type;
    505     typedef typename c2_types<T, rest_type>::wide_type wide_type;
    506     return ({
    507         wide_type a_(a), b_(c2_min(b, c...));
    508         static_cast<typename c2_types<T, rest_type>::min_type>(a_ < b_ ? a_ : b_);
    509     });
    510 }
    511 
    512 /**
    513  *  \ingroup utils_internal
    514  */
    515 template<typename T, typename U, typename V>
    516 inline constexpr typename c2_types<T, V>::wide_type c2_clamp(const T a, const U b, const V c) {
    517     typedef typename c2_types<T, U, V>::wide_type wide_type;
    518     return ({
    519         wide_type a_(a), b_(b), c_(c);
    520         static_cast<typename c2_types<T, V>::wide_type>(b_ < a_ ? a_ : b_ > c_ ? c_ : b_);
    521     });
    522 }
    523 
    524 /// @}
    525 
    526 #include <functional>
    527 template<typename T>
    528 struct std::less<::c2_cntr_t<T>> {
    529     constexpr bool operator()(const ::c2_cntr_t<T> &lh, const ::c2_cntr_t<T> &rh) const {
    530         return lh.peeku() < rh.peeku();
    531     }
    532 };
    533 template<typename T>
    534 struct std::less_equal<::c2_cntr_t<T>> {
    535     constexpr bool operator()(const ::c2_cntr_t<T> &lh, const ::c2_cntr_t<T> &rh) const {
    536         return lh.peeku() <= rh.peeku();
    537     }
    538 };
    539 template<typename T>
    540 struct std::greater<::c2_cntr_t<T>> {
    541     constexpr bool operator()(const ::c2_cntr_t<T> &lh, const ::c2_cntr_t<T> &rh) const {
    542         return lh.peeku() > rh.peeku();
    543     }
    544 };
    545 template<typename T>
    546 struct std::greater_equal<::c2_cntr_t<T>> {
    547     constexpr bool operator()(const ::c2_cntr_t<T> &lh, const ::c2_cntr_t<T> &rh) const {
    548         return lh.peeku() >= rh.peeku();
    549     }
    550 };
    551 
    552 #endif  // C2_H_
    553