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