• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
get_c2_cntr_compat_helper201     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
get_c2_cntr_compat_helper207     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      */
c2_cntr_t()249     inline constexpr c2_cntr_t() : mValue(T(0)) {}
250 
251     /**
252      * Construct from a compatible type.
253      */
254     template<typename U>
c2_cntr_t(const U & value)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
peek()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      */
peeku()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
peekll()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
peekull()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 constexpr 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