Home | History | Annotate | Download | only in foundation
      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 STAGEFRIGHT_FOUNDATION_A_DATA_H_
     18 #define STAGEFRIGHT_FOUNDATION_A_DATA_H_
     19 
     20 #include <memory> // for std::shared_ptr, weak_ptr and unique_ptr
     21 #include <type_traits> // for std::aligned_union
     22 
     23 #include <utils/StrongPointer.h> // for android::sp and wp
     24 
     25 #include <media/stagefright/foundation/TypeTraits.h>
     26 #include <media/stagefright/foundation/Flagged.h>
     27 
     28 #undef HIDE
     29 #define HIDE __attribute__((visibility("hidden")))
     30 
     31 namespace android {
     32 
     33 /**
     34  * AData is a flexible union type that supports non-POD members. It supports arbitrary types as long
     35  * as they are either moveable or copyable.
     36  *
     37  * Internally, AData is using AUnion - a structure providing the union support. AUnion should not
     38  * be used by generic code as it is very unsafe - it opens type aliasing errors where an object of
     39  * one type can be easily accessed as an object of another type. AData prevents this.
     40  *
     41  * AData allows a custom type flagger to be used for future extensions (e.g. allowing automatic
     42  * type conversion). A strict and a relaxed flagger are provided as internal types.
     43  *
     44  * Use as follows:
     45  *
     46  * AData<int, float>::Basic data; // strict type support
     47  * int i = 1;
     48  * float f = 7.0f;
     49  *
     50  * data.set(5);
     51  * EXPECT_TRUE(data.find(&i));
     52  * EXPECT_FALSE(data.find(&f));
     53  * EXPECT_EQ(i, 5);
     54  *
     55  * data.set(6.0f);
     56  * EXPECT_FALSE(data.find(&i));
     57  * EXPECT_TRUE(data.find(&f));
     58  * EXPECT_EQ(f, 6.0f);
     59  *
     60  * AData<int, sp<RefBase>>::RelaxedBasic objdata; // relaxed type support
     61  * sp<ABuffer> buf = new ABuffer(16), buf2;
     62  * sp<RefBase> obj;
     63  *
     64  * objdata.set(buf);
     65  * EXPECT_TRUE(objdata.find(&buf2));
     66  * EXPECT_EQ(buf, buf2);
     67  * EXPECT_FALSE(objdata.find(&i));
     68  * EXPECT_TRUE(objdata.find(&obj));
     69  * EXPECT_TRUE(obj == buf);
     70  *
     71  * obj = buf;
     72  * objdata.set(obj); // storing as sp<RefBase>
     73  * EXPECT_FALSE(objdata.find(&buf2));  // not stored as ABuffer(!)
     74  * EXPECT_TRUE(objdata.find(&obj));
     75  */
     76 
     77 /// \cond Internal
     78 
     79 /**
     80  * Helper class to call constructor and destructor for a specific type in AUnion.
     81  * This class is needed as member function specialization is not allowed for a
     82  * templated class.
     83  */
     84 struct HIDE _AUnion_impl {
     85     /**
     86      * Calls placement constuctor for type T with arbitrary arguments for a storage at an address.
     87      * Storage MUST be large enough to contain T.
     88      * Also clears the slack space after type T. \todo This is not technically needed, so we may
     89      * choose to do this just for debugging.
     90      *
     91      * \param totalSize size of the storage
     92      * \param addr      pointer to where object T should be constructed
     93      * \param args      arbitrary arguments for constructor
     94      */
     95     template<typename T, typename ...Args>
     96     inline static void emplace(size_t totalSize, T *addr, Args&&... args) {
     97         new(addr)T(std::forward<Args>(args)...);
     98         // clear slack space - this is not technically required
     99         constexpr size_t size = sizeof(T);
    100         memset(reinterpret_cast<uint8_t*>(addr) + size, 0, totalSize - size);
    101     }
    102 
    103     /**
    104      * Calls destuctor for an object of type T located at a specific address.
    105      *
    106      * \note we do not clear the storage in this case as the storage should not be used
    107      * until another object is placed there, at which case the storage will be cleared.
    108      *
    109      * \param addr    pointer to where object T is stored
    110      */
    111     template<typename T>
    112     inline static void del(T *addr) {
    113         addr->~T();
    114     }
    115 };
    116 
    117 /** Constructor specialization for void type */
    118 template<>
    119 HIDE inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
    120     memset(addr, 0, totalSize);
    121 }
    122 
    123 /** Destructor specialization for void type */
    124 template<>
    125 HIDE inline void _AUnion_impl::del<void>(void *) {
    126 }
    127 
    128 /// \endcond
    129 
    130 /**
    131  * A templated union class that can contain specific types of data, and provides
    132  * constructors, destructor and access methods strictly for those types.
    133  *
    134  * \note This class is VERY UNSAFE compared to a union, but it allows non-POD unions.
    135  * In particular care must be taken that methods are called in a careful order to
    136  * prevent accessing objects of one type as another type. This class provides no
    137  * facilities to help with this ordering. This is meant to be wrapped by safer
    138  * utility classes that do that.
    139  *
    140  * \param Ts types stored in this union.
    141  */
    142 template<typename ...Ts>
    143 struct AUnion {
    144 private:
    145     using _type = typename std::aligned_union<0, Ts...>::type; ///< storage type
    146     _type mValue;                                              ///< storage
    147 
    148 public:
    149     /**
    150      * Constructs an object of type T with arbitrary arguments in this union. After this call,
    151      * this union will contain this object.
    152      *
    153      * This method MUST be called only when either 1) no object or 2) a void object (equivalent to
    154      * no object) is contained in this union.
    155      *
    156      * \param T     type of object to be constructed. This must be one of the template parameters of
    157      *              the union class with the same cv-qualification, or void.
    158      * \param args  arbitrary arguments for the constructor
    159      */
    160     template<
    161             typename T, typename ...Args,
    162             typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
    163     inline void emplace(Args&&... args) {
    164         _AUnion_impl::emplace(
    165                 sizeof(_type), reinterpret_cast<T*>(&mValue), std::forward<Args>(args)...);
    166     }
    167 
    168     /**
    169      * Destructs an object of type T in this union. After this call, this union will contain no
    170      * object.
    171      *
    172      * This method MUST be called only when this union contains an object of type T.
    173      *
    174      * \param T     type of object to be destructed. This must be one of the template parameters of
    175      *              the union class with the same cv-qualification, or void.
    176      */
    177     template<
    178             typename T,
    179             typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
    180     inline void del() {
    181         _AUnion_impl::del(reinterpret_cast<T*>(&mValue));
    182     }
    183 
    184     /**
    185      * Returns a const reference to the object of type T in this union.
    186      *
    187      * This method MUST be called only when this union contains an object of type T.
    188      *
    189      * \param T     type of object to be returned. This must be one of the template parameters of
    190      *              the union class with the same cv-qualification.
    191      */
    192     template<
    193             typename T,
    194             typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
    195     inline const T &get() const {
    196         return *reinterpret_cast<const T*>(&mValue);
    197     }
    198 
    199     /**
    200      * Returns a reference to the object of type T in this union.
    201      *
    202      * This method MUST be called only when this union contains an object of type T.
    203      *
    204      * \param T     type of object to be returned. This must be one of the template parameters of
    205      *              the union class with the same cv-qualification.
    206      */
    207     template<typename T>
    208     inline T &get() {
    209         return *reinterpret_cast<T*>(&mValue);
    210     }
    211 };
    212 
    213 /**
    214  * Helper utility class that copies an object of type T to a destination.
    215  *
    216  * T must be copy assignable or copy constructible.
    217  *
    218  * It provides:
    219  *
    220  * void assign(T*, const U&) // for copiable types - this leaves the source unchanged, hence const.
    221  *
    222  * \param T type of object to assign to
    223  */
    224 template<
    225         typename T,
    226         bool=std::is_copy_assignable<T>::value>
    227 struct HIDE _AData_copier {
    228     static_assert(std::is_copy_assignable<T>::value, "T must be copy assignable here");
    229 
    230     /**
    231      * Copies src to data without modifying data.
    232      *
    233      * \param data pointer to destination
    234      * \param src source object
    235      */
    236     inline static void assign(T *data, const T &src) {
    237         *data = src;
    238     }
    239 
    240     template<typename U>
    241     using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type;
    242 
    243     /**
    244      * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<>
    245      */
    246     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
    247     inline static void assign(sp<Tp> *data, const sp<U> &src) {
    248         *data = static_cast<Tp*>(src.get());
    249     }
    250 
    251     template<typename Tp, typename U, typename=enable_if_T_is_same_as<wp<Tp>>>
    252     inline static void assign(wp<Tp> *data, const wp<U> &src) {
    253         sp<U> __tmp = src.promote();
    254         *data = static_cast<Tp*>(__tmp.get());
    255     }
    256 
    257     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
    258     inline static void assign(sp<Tp> *data, sp<U> &&src) {
    259         sp<U> __tmp = std::move(src); // move src out as get cannot
    260         *data = static_cast<Tp*>(__tmp.get());
    261     }
    262 
    263     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
    264     inline static void assign(std::shared_ptr<Tp> *data, const std::shared_ptr<U> &src) {
    265         *data = std::static_pointer_cast<Tp>(src);
    266     }
    267 
    268     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
    269     inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) {
    270         std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot
    271         *data = std::static_pointer_cast<Tp>(__tmp);
    272     }
    273 
    274     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::weak_ptr<Tp>>>
    275     inline static void assign(std::weak_ptr<Tp> *data, const std::weak_ptr<U> &src) {
    276         *data = std::static_pointer_cast<Tp>(src.lock());
    277     }
    278 
    279     // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the
    280     // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that
    281     // they are stored as shared_ptrs.
    282     /**
    283      * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method
    284      * is not enough to detect this, only if someone is trying to find the shared_ptr.
    285      */
    286     template<typename Tp, typename U>
    287     inline static void assign(std::shared_ptr<Tp> *, const std::weak_ptr<U> &) {
    288         static_assert(std::is_same<Tp, void>::value,
    289                       "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs");
    290     }
    291 };
    292 
    293 /**
    294  * Template specialization for non copy assignable, but copy constructible types.
    295  *
    296  * \todo Test this. No basic classes are copy constructible but not assignable.
    297  *
    298  */
    299 template<typename T>
    300 struct HIDE _AData_copier<T, false> {
    301     static_assert(!std::is_copy_assignable<T>::value, "T must not be copy assignable here");
    302     static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible here");
    303 
    304     inline static void copy(T *data, const T &src) {
    305         data->~T();
    306         new(data)T(src);
    307     }
    308 };
    309 
    310 /**
    311  * Helper utility class that moves an object of type T to a destination.
    312  *
    313  * T must be move assignable or move constructible.
    314  *
    315  * It provides multiple methods:
    316  *
    317  * void assign(T*, T&&)
    318  *
    319  * \param T type of object to assign
    320  */
    321 template<
    322         typename T,
    323         bool=std::is_move_assignable<T>::value>
    324 struct HIDE _AData_mover {
    325     static_assert(std::is_move_assignable<T>::value, "T must be move assignable here");
    326 
    327     /**
    328      * Moves src to data while likely modifying it.
    329      *
    330      * \param data pointer to destination
    331      * \param src source object
    332      */
    333     inline static void assign(T *data, T &&src) {
    334         *data = std::move(src);
    335     }
    336 
    337     template<typename U>
    338     using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type;
    339 
    340     /**
    341      * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<>
    342      */
    343     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
    344     inline static void assign(sp<Tp> *data, sp<U> &&src) {
    345         sp<U> __tmp = std::move(src); // move src out as get cannot
    346         *data = static_cast<Tp*>(__tmp.get());
    347     }
    348 
    349     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
    350     inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) {
    351         std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot
    352         *data = std::static_pointer_cast<Tp>(__tmp);
    353     }
    354 
    355     template<typename Tp, typename Td, typename U, typename Ud,
    356             typename=enable_if_T_is_same_as<std::unique_ptr<Tp, Td>>>
    357     inline static void assign(std::unique_ptr<Tp, Td> *data, std::unique_ptr<U, Ud> &&src) {
    358         *data = std::unique_ptr<Tp, Td>(static_cast<Tp*>(src.release()));
    359     }
    360 
    361     // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the
    362     // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that
    363     // they are stored as shared_ptrs.
    364     /**
    365      * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method
    366      * is not enough to detect this, only if someone is trying to remove the shared_ptr.
    367      */
    368     template<typename Tp, typename U>
    369     inline static void assign(std::shared_ptr<Tp> *, std::weak_ptr<U> &&) {
    370         static_assert(std::is_same<Tp, void>::value,
    371                       "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs");
    372     }
    373 
    374     // unique_ptrs are implicitly convertible to shared_ptrs but not vice versa, but picking the
    375     // first compatible type in Ts requires having unique_ptrs types before shared_ptrs types, so
    376     // that they are stored as unique_ptrs.
    377     /**
    378      * Provide sensible error message if encountering shared_ptr/unique_ptr ambiguity. This method
    379      * is not enough to detect this, only if someone is trying to remove the unique_ptr.
    380      */
    381     template<typename Tp, typename U>
    382     inline static void assign(std::unique_ptr<Tp> *, std::shared_ptr<U> &&) {
    383         static_assert(std::is_same<Tp, void>::value,
    384                       "unique/shared pointer ambiguity. move unique ptr types before shared_ptrs");
    385     }
    386 };
    387 
    388 /**
    389  * Template specialization for non move assignable, but move constructible types.
    390  *
    391  * \todo Test this. No basic classes are move constructible but not assignable.
    392  *
    393  */
    394 template<typename T>
    395 struct HIDE _AData_mover<T, false> {
    396     static_assert(!std::is_move_assignable<T>::value, "T must not be move assignable here");
    397     static_assert(std::is_move_constructible<T>::value, "T must be move constructible here");
    398 
    399     inline static void assign(T *data, T &&src) {
    400         data->~T();
    401         new(data)T(std::move(src));
    402     }
    403 };
    404 
    405 /**
    406  * Helper template that deletes an object of a specific type (member) in an AUnion.
    407  *
    408  * \param Flagger type flagger class (see AData)
    409  * \param U AUnion object in which the member should be deleted
    410  * \param Ts types to consider for the member
    411  */
    412 template<typename Flagger, typename U, typename ...Ts>
    413 struct HIDE _AData_deleter;
    414 
    415 /**
    416  * Template specialization when there are still types to consider (T and rest)
    417  */
    418 template<typename Flagger, typename U, typename T, typename ...Ts>
    419 struct HIDE _AData_deleter<Flagger, U, T, Ts...> {
    420     static bool del(typename Flagger::type flags, U &data) {
    421         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
    422             data.template del<T>();
    423             return true;
    424         }
    425         return _AData_deleter<Flagger, U, Ts...>::del(flags, data);
    426     }
    427 };
    428 
    429 /**
    430  * Template specialization when there are no more types to consider.
    431  */
    432 template<typename Flagger, typename U>
    433 struct HIDE _AData_deleter<Flagger, U> {
    434     inline static bool del(typename Flagger::type, U &) {
    435         return false;
    436     }
    437 };
    438 
    439 /**
    440  * Helper template that copy assigns an object of a specific type (member) in an
    441  * AUnion.
    442  *
    443  * \param Flagger type flagger class (see AData)
    444  * \param U AUnion object in which the member should be copy assigned
    445  * \param Ts types to consider for the member
    446  */
    447 template<typename Flagger, typename U, typename ...Ts>
    448 struct HIDE _AData_copy_assigner;
    449 
    450 /**
    451  * Template specialization when there are still types to consider (T and rest)
    452  */
    453 template<typename Flagger, typename U, typename T, typename ...Ts>
    454 struct HIDE _AData_copy_assigner<Flagger, U, T, Ts...> {
    455     static bool assign(typename Flagger::type flags, U &dst, const U &src) {
    456         static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
    457         // if we can delete as, we can also assign as
    458         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
    459             dst.template emplace<T>(src.template get<T>());
    460             return true;
    461         }
    462         return _AData_copy_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
    463     }
    464 };
    465 
    466 /**
    467  * Template specialization when there are no more types to consider.
    468  */
    469 template<typename Flagger, typename U>
    470 struct HIDE _AData_copy_assigner<Flagger, U> {
    471     inline static bool assign(typename Flagger::type, U &, const U &) {
    472         return false;
    473     }
    474 };
    475 
    476 /**
    477  * Helper template that move assigns an object of a specific type (member) in an
    478  * AUnion.
    479  *
    480  * \param Flagger type flagger class (see AData)
    481  * \param U AUnion object in which the member should be copy assigned
    482  * \param Ts types to consider for the member
    483  */
    484 template<typename Flagger, typename U, typename ...Ts>
    485 struct HIDE _AData_move_assigner;
    486 
    487 /**
    488  * Template specialization when there are still types to consider (T and rest)
    489  */
    490 template<typename Flagger, typename U, typename T, typename ...Ts>
    491 struct HIDE _AData_move_assigner<Flagger, U, T, Ts...> {
    492     template<typename V = T>
    493     static typename std::enable_if<std::is_move_constructible<V>::value, bool>::type
    494     assign(typename Flagger::type flags, U &dst, U &src) {
    495         // if we can delete as, we can also assign as
    496         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
    497             dst.template emplace<T>(std::move(src.template get<T>()));
    498             return true;
    499         }
    500         return _AData_move_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
    501     }
    502 
    503     // Fall back to copy construction if T is not move constructible
    504     template<typename V = T>
    505     static typename std::enable_if<!std::is_move_constructible<V>::value, bool>::type
    506     assign(typename Flagger::type flags, U &dst, U &src) {
    507         static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
    508         // if we can delete as, we can also assign as
    509         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
    510             dst.template emplace<T>(src.template get<T>());
    511             return true;
    512         }
    513         return _AData_move_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
    514     }
    515 };
    516 
    517 /**
    518  * Template specialization when there are no more types to consider.
    519  */
    520 template<typename Flagger, typename U>
    521 struct HIDE _AData_move_assigner<Flagger, U> {
    522     inline static bool assign(typename Flagger::type, U &, U &) {
    523         return false;
    524     }
    525 };
    526 
    527 /**
    528  * Container that can store an arbitrary object of a set of specified types.
    529  *
    530  * This struct is an outer class that contains various inner classes based on desired type
    531  * strictness. The following inner classes are supported:
    532  *
    533  * AData<types...>::Basic   - strict type support using uint32_t flag.
    534  *
    535  * AData<types...>::Strict<Flag> - strict type support using custom flag.
    536  * AData<types...>::Relaxed<Flag, MaxSize, Align>
    537  *                          - relaxed type support with compatible (usually derived) class support
    538  *                            for pointer types with added size checking for minimal additional
    539  *                            safety.
    540  *
    541  * AData<types...>::RelaxedBasic - strict type support using uint32_t flag.
    542  *
    543  * AData<types...>::Custom<flagger> - custom type support (flaggers determine the supported types
    544  *                                    and the base type to use for each)
    545  *
    546  */
    547 template<typename ...Ts>
    548 struct AData {
    549 private:
    550     static_assert(are_unique<Ts...>::value, "types must be unique");
    551 
    552     static constexpr size_t num_types = sizeof...(Ts); ///< number of types to support
    553 
    554 public:
    555     /**
    556      * Default (strict) type flagger provided.
    557      *
    558      * The default flagger simply returns the index of the type within Ts, or 0 for void.
    559      *
    560      * Type flaggers return a flag for a supported type.
    561      *
    562      * They must provide:
    563      *
    564      * - a flagFor(T*) method for supported types _and_ for T=void. T=void is used to mark that no
    565      *   object is stored in the container. For this, an arbitrary unique value may be returned.
    566      * - a mask field that contains the flag mask.
    567      * - a canDeleteAs(Flag, Flag) flag comparison method that checks if a type of a flag can be
    568      *   deleted as another type.
    569      *
    570      * \param Flag the underlying unsigned integral to use for the flags.
    571      */
    572     template<typename Flag>
    573     struct flagger {
    574     private:
    575         static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
    576         static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
    577 
    578         static constexpr Flag count = num_types + 1;
    579 
    580     public:
    581         typedef Flag type; ///< flag type
    582 
    583         static constexpr Flag mask = _Flagged_helper::minMask<Flag>(count); ///< flag mask
    584 
    585         /**
    586          * Return the stored type for T. This is itself.
    587          */
    588         template<typename T>
    589         struct store {
    590             typedef T as_type; ///< the base type that T is stored as
    591         };
    592 
    593         /**
    594          * Constexpr method that returns if two flags are compatible for deletion.
    595          *
    596          * \param objectFlag flag for object to be deleted
    597          * \param deleteFlag flag for type that object is to be deleted as
    598          */
    599         static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
    600             // default flagger requires strict type equality
    601             return objectFlag == deleteFlag;
    602         }
    603 
    604         /**
    605          * Constexpr method that returns the flag to use for a given type.
    606          *
    607          * Function overload for void*.
    608          */
    609         static constexpr Flag flagFor(void*) {
    610             return 0u;
    611         }
    612 
    613         /**
    614          * Constexpr method that returns the flag to use for a given supported type (T).
    615          */
    616         template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
    617         static constexpr Flag flagFor(T*) {
    618             return find_first<T, Ts...>::index;
    619         }
    620     };
    621 
    622     /**
    623      * Relaxed flagger returns the index of the type within Ts. However, for pointers T* it returns
    624      * the first type in Ts that T* can be converted into (this is normally a base type, but also
    625      * works for sp<>, shared_ptr<> or unique_ptr<>). For a bit more strictness, the flag also
    626      * contains the size of the class to avoid finding objects that were stored as a different
    627      * derived class of the same base class.
    628      *
    629      * Flag is basically the index of the (base) type in Ts multiplied by the max size stored plus
    630      * the size of the type (divided by alignment) for derived pointer types.
    631      *
    632      * \param MaxSize max supported size for derived class pointers
    633      * \param Align alignment to assume for derived class pointers
    634      */
    635     template<typename Flag, size_t MaxSize=1024, size_t Align=4>
    636     struct relaxed_flagger {
    637     private:
    638         static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
    639         static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
    640 
    641         static constexpr Flag count = num_types + 1;
    642         static_assert(std::numeric_limits<Flag>::max() / count > (MaxSize / Align),
    643                       "not enough bits to fit into flag");
    644 
    645         static constexpr Flag max_size_stored = MaxSize / Align + 1;
    646 
    647         // T can be converted if it's size is <= MaxSize and it can be converted to one of the Ts
    648         template<typename T, size_t size>
    649         using enable_if_can_be_converted = typename std::enable_if<
    650                 (size / Align < max_size_stored
    651                         && find_first_convertible_to<T, Ts...>::index)>::type;
    652 
    653 
    654         template<typename W, typename T, typename=enable_if_can_be_converted<W, sizeof(T)>>
    655         static constexpr Flag relaxedFlagFor(W*, T*) {
    656             return find_first_convertible_to<W, Ts...>::index * max_size_stored
    657                     + (is_one_of<W, Ts...>::value ? 0 : (sizeof(T) / Align));
    658         }
    659 
    660     public:
    661         typedef Flag type; ///< flag type
    662 
    663         static constexpr Flag mask =
    664             _Flagged_helper::minMask<Flag>(count * max_size_stored); ///< flag mask
    665 
    666         /**
    667          * Constexpr method that returns if two flags are compatible for deletion.
    668          *
    669          * \param objectFlag flag for object to be deleted
    670          * \param deleteFlag flag for type that object is to be deleted as
    671          */
    672         static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
    673             // can delete if objects have the same base type
    674             return
    675                 objectFlag / max_size_stored == deleteFlag / max_size_stored &&
    676                 (deleteFlag % max_size_stored) == 0;
    677         }
    678 
    679         /**
    680          * Constexpr method that returns the flag to use for a given type.
    681          *
    682          * Function overload for void*.
    683          */
    684         static constexpr Flag flagFor(void*) {
    685             return 0u;
    686         }
    687 
    688         /**
    689          * Constexpr method that returns the flag to use for a given supported type (T).
    690          *
    691          * This is a member method to enable both overloading as well as template specialization.
    692          */
    693         template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
    694         static constexpr Flag flagFor(T*) {
    695             return find_first<T, Ts...>::index * max_size_stored;
    696         }
    697 
    698         /**
    699          * For precaution, we only consider converting pointers to their base classes.
    700          */
    701 
    702         /**
    703          * Template specialization for derived class pointers and managed pointers.
    704          */
    705         template<typename T>
    706         static constexpr Flag flagFor(T**p) { return relaxedFlagFor(p, (T*)0); }
    707         template<typename T>
    708         static constexpr Flag flagFor(std::shared_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
    709         template<typename T>
    710         static constexpr Flag flagFor(std::unique_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
    711         template<typename T>
    712         static constexpr Flag flagFor(std::weak_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
    713         template<typename T>
    714         static constexpr Flag flagFor(sp<T>*p) { return relaxedFlagFor(p, (T*)0); }
    715         template<typename T>
    716         static constexpr Flag flagFor(wp<T>*p) { return relaxedFlagFor(p, (T*)0); }
    717 
    718         /**
    719          * Type support template that provodes the stored type for T.
    720          * This is itself if it is one of Ts, or the first type in Ts that T is convertible to.
    721          *
    722          * NOTE: This template may provide a base class for an unsupported type. Support is
    723          * determined by flagFor().
    724          */
    725         template<typename T>
    726         struct store {
    727             typedef typename std::conditional<
    728                     is_one_of<T, Ts...>::value,
    729                     T,
    730                     typename find_first_convertible_to<T, Ts...>::type>::type as_type;
    731         };
    732     };
    733 
    734     /**
    735      * Implementation of AData.
    736      */
    737     template<typename Flagger>
    738     struct Custom : protected Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask> {
    739         using data_t = AUnion<Ts...>;
    740         using base_t = Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask>;
    741 
    742         /**
    743          * Constructor. Initializes this to a container that does not contain any object.
    744          */
    745         Custom() : base_t(Flagger::flagFor((void*)0)) { }
    746 
    747         /**
    748          * Copy assignment operator.
    749          */
    750         Custom& operator=(const Custom &o) {
    751             if (&o != this) {
    752                 if (this->used() && !this->clear()) {
    753                     __builtin_trap();
    754                 }
    755                 if (o.used()) {
    756                     if (_AData_copy_assigner<Flagger, data_t, Ts...>::assign(
    757                             o.flags(), this->get(), o.get())) {
    758                         this->setFlags(o.flags());
    759                     } else {
    760                         __builtin_trap();
    761                     }
    762                 }
    763             }
    764             return *this;
    765         }
    766 
    767         /**
    768          * Copy constructor.
    769          */
    770         Custom(const Custom &o) : Custom() {
    771             *this = o;
    772         }
    773 
    774         /**
    775          * Move assignment operator.
    776          */
    777         Custom& operator=(Custom &&o) {
    778             if (&o != this) {
    779                 if (this->used() && !this->clear()) {
    780                     __builtin_trap();
    781                 }
    782                 if (o.used()) {
    783                     if (_AData_move_assigner<Flagger, data_t, Ts...>::assign(
    784                             o.flags(), this->get(), o.get())) {
    785                         this->setFlags(o.flags());
    786                         o.clear();
    787                     } else {
    788                         __builtin_trap();
    789                     }
    790                 }
    791             }
    792             return *this;
    793         }
    794 
    795         /**
    796          * Move constructor.
    797          */
    798         Custom(Custom &&o) : Custom() {
    799             *this = std::move(o);
    800         }
    801 
    802         /**
    803          * Removes the contained object, if any.
    804          */
    805         ~Custom() {
    806             if (!this->clear()) {
    807                 __builtin_trap();
    808                 // std::cerr << "could not delete data of type " << this->flags() << std::endl;
    809             }
    810         }
    811 
    812         /**
    813          * Returns whether there is any object contained.
    814          */
    815         inline bool used() const {
    816             return this->flags() != Flagger::flagFor((void*)0);
    817         }
    818 
    819         /**
    820          * Removes the contained object, if any. Returns true if there are no objects contained,
    821          * or false on any error (this is highly unexpected).
    822          */
    823         bool clear() {
    824             if (this->used()) {
    825                 if (_AData_deleter<Flagger, data_t, Ts...>::del(this->flags(), this->get())) {
    826                     this->setFlags(Flagger::flagFor((void*)0));
    827                     return true;
    828                 }
    829                 return false;
    830             }
    831             return true;
    832         }
    833 
    834         template<typename T>
    835         using is_supported_by_flagger =
    836             typename std::enable_if<Flagger::flagFor((T*)0) != Flagger::flagFor((void*)0)>::type;
    837 
    838         /**
    839          * Checks if there is a copiable object of type T in this container. If there is, it copies
    840          * that object into the provided address and returns true. Otherwise, it does nothing and
    841          * returns false.
    842          *
    843          * This method normally requires a flag equality between the stored and retrieved types.
    844          * However, it also allows retrieving the stored object as the stored type
    845          * (usually base type).
    846          *
    847          * \param T type of object to sought
    848          * \param data address at which the object should be retrieved
    849          *
    850          * \return true if the object was retrieved. false if it was not.
    851          */
    852         template<
    853                 typename T,
    854                 typename=is_supported_by_flagger<T>>
    855         bool find(T *data) const {
    856             using B = typename Flagger::template store<T>::as_type;
    857             if (this->flags() == Flagger::flagFor((T*)0) ||
    858                 Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
    859                 _AData_copier<T>::assign(data, this->get().template get<B>());
    860                 return true;
    861             }
    862             return false;
    863         }
    864 
    865         /**
    866          * Checks if there is an object of type T in this container. If there is, it moves that
    867          * object into the provided address and returns true. Otherwise, it does nothing and returns
    868          * false.
    869          *
    870          * This method normally requires a flag equality between the stored and retrieved types.
    871          * However, it also allows retrieving the stored object as the stored type
    872          * (usually base type).
    873          *
    874          * \param T type of object to sought
    875          * \param data address at which the object should be retrieved.
    876          *
    877          * \return true if the object was retrieved. false if it was not.
    878          */
    879         template<
    880                 typename T,
    881                 typename=is_supported_by_flagger<T>>
    882         bool remove(T *data) {
    883             using B = typename Flagger::template store<T>::as_type;
    884             if (this->flags() == Flagger::flagFor((T*)0) ||
    885                 Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
    886                 _AData_mover<T>::assign(data, std::move(this->get().template get<B>()));
    887                 return true;
    888             }
    889             return false;
    890         }
    891 
    892         /**
    893          * Stores an object into this container by copying. If it was successful, returns true.
    894          * Otherwise, (e.g. it could not destroy the already stored object) it returns false. This
    895          * latter would be highly unexpected.
    896          *
    897          * \param T type of object to store
    898          * \param data object to store
    899          *
    900          * \return true if the object was stored. false if it was not.
    901          */
    902         template<
    903                 typename T,
    904                 typename=is_supported_by_flagger<T>,
    905                 typename=typename std::enable_if<
    906                         std::is_copy_constructible<T>::value ||
    907                         (std::is_default_constructible<T>::value &&
    908                                 std::is_copy_assignable<T>::value)>::type>
    909         bool set(const T &data) {
    910             using B = typename Flagger::template store<T>::as_type;
    911 
    912             // if already contains an object of this type, simply assign
    913             if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
    914                 _AData_copier<B>::assign(&this->get().template get<B>(), data);
    915                 return true;
    916             } else if (this->used()) {
    917                 // destroy previous object
    918                 if (!this->clear()) {
    919                     return false;
    920                 }
    921             }
    922             this->get().template emplace<B>(data);
    923             this->setFlags(Flagger::flagFor((T *)0));
    924             return true;
    925         }
    926 
    927         /**
    928          * Moves an object into this container. If it was successful, returns true. Otherwise,
    929          * (e.g. it could not destroy the already stored object) it returns false. This latter
    930          * would be highly unexpected.
    931          *
    932          * \param T type of object to store
    933          * \param data object to store
    934          *
    935          * \return true if the object was stored. false if it was not.
    936          */
    937         template<
    938                 typename T,
    939                 typename=is_supported_by_flagger<T>>
    940         bool set(T &&data) {
    941             using B = typename Flagger::template store<T>::as_type;
    942 
    943             // if already contains an object of this type, simply assign
    944             if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
    945                 _AData_mover<B>::assign(&this->get().template get<B>(), std::forward<T&&>(data));
    946                 return true;
    947             } else if (this->used()) {
    948                 // destroy previous object
    949                 if (!this->clear()) {
    950                     return false;
    951                 }
    952             }
    953             this->get().template emplace<B>(std::forward<T&&>(data));
    954             this->setFlags(Flagger::flagFor((T *)0));
    955             return true;
    956         }
    957     };
    958 
    959     /**
    960      * Basic AData using the default type flagger and requested flag type.
    961      *
    962      * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
    963      */
    964     template<typename Flag>
    965     using Strict = Custom<flagger<Flag>>;
    966 
    967     /**
    968      * Basic AData using the default type flagger and uint32_t flag.
    969      */
    970     using Basic = Strict<uint32_t>;
    971 
    972     /**
    973      * AData using the relaxed type flagger for max size and requested flag type.
    974      *
    975      * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
    976      */
    977     template<typename Flag, size_t MaxSize = 1024, size_t Align = 4>
    978     using Relaxed = Custom<relaxed_flagger<Flag, MaxSize, Align>>;
    979 
    980     /**
    981      * Basic AData using the relaxed type flagger and uint32_t flag.
    982      */
    983     using RelaxedBasic = Relaxed<uint32_t>;
    984 };
    985 
    986 }  // namespace android
    987 
    988 #endif  // STAGEFRIGHT_FOUNDATION_A_DATA_H_
    989 
    990