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> emplace_AUnion_impl96 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> del_AUnion_impl112 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> emplaceAUnion163 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> delAUnion180 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> getAUnion195 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> getAUnion208 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 */ assign_AData_copier236 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>>> assign_AData_copier247 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>>> assign_AData_copier252 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>>> assign_AData_copier258 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>>> assign_AData_copier264 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>>> assign_AData_copier269 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>>> assign_AData_copier275 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> assign_AData_copier287 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) noexcept { 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) noexcept : 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