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