Changeset 36524 in vbox for trunk/include/iprt
- Timestamp:
- Apr 4, 2011 12:46:30 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 70945
- Location:
- trunk/include/iprt
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/cpp/list.h
r36508 r36524 78 78 * they are save to use. 79 79 * 80 * Please note that the return type of some of the getter methods are slightly 81 * different depending on the list type. Native types return the item by value, 82 * items with a size greater than sizeof(void*) by reference. As native types 83 * saved directly in the internal array, returning a reference to them (and 84 * saving them in a reference as well) would make them invalid (or pointing to 85 * a wrong item) when the list is changed in the meanwhile. Returning a 86 * reference for bigger types isn't problematic and makes sure we get out the 87 * best speed of the list. The one exception to this rule is the index 88 * operator[]. This operator always return a reference to make it possible to 89 * use it as a lvalue. Its your responsibility to make sure the list isn't 90 * changed when using the value as reference returned by this operator. 91 * 92 * The list class is reentrant. For a thread-safe variant see mtlist. 93 * 80 94 * Implementation details: 81 95 * It is possible to specialize any type. This might be necessary to get the … … 90 104 * @{ 91 105 */ 106 107 /** 108 * The guard definition. 109 */ 110 template <bool G> 111 class ListGuard; 112 113 /** 114 * The default guard which does nothing. 115 */ 116 template <> 117 class ListGuard<false> 118 { 119 public: 120 inline void enterRead() const {} 121 inline void leaveRead() const {} 122 inline void enterWrite() {} 123 inline void leaveWrite() {} 124 }; 92 125 93 126 /** … … 136 169 * list interface to the user. 137 170 */ 138 template <class T, typename TYPE>171 template <class T, typename ITYPE, bool MT> 139 172 class ListBase 140 173 { 174 /** 175 * Defines the return type of most of the getter methods. If the internal 176 * used type is a pointer, we return a reference. If not we return by 177 * value. 178 */ 179 typedef typename if_ptr<ITYPE, T&, T>::result GET_RTYPE; 180 141 181 public: 142 182 /** … … 165 205 * @throws std::bad_alloc 166 206 */ 167 ListBase(const ListBase<T, TYPE>& other)207 ListBase(const ListBase<T, ITYPE, MT>& other) 168 208 : m_pArray(0) 169 209 , m_cSize(0) … … 171 211 { 172 212 realloc_grow(other.m_cSize); 173 ListHelper<T, list_type>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize);213 ListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); 174 214 m_cSize = other.m_cSize; 175 215 } … … 180 220 ~ListBase() 181 221 { 182 ListHelper<T, list_type>::eraseRange(m_pArray, 0, m_cSize);222 ListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); 183 223 if (m_pArray) 184 224 RTMemFree(m_pArray); … … 196 236 * @throws std::bad_alloc 197 237 */ 198 void setCapacity(size_t cCapacity) { realloc(cCapacity); } 238 void setCapacity(size_t cCapacity) 239 { 240 m_guard.enterWrite(); 241 realloc(cCapacity); 242 m_guard.leaveWrite(); 243 } 199 244 200 245 /** … … 227 272 * @throws std::bad_alloc 228 273 */ 229 ListBase<T, TYPE> &insert(size_t i, const T &val) 230 { 274 ListBase<T, ITYPE, MT> &insert(size_t i, const T &val) 275 { 276 m_guard.enterWrite(); 231 277 if (m_cSize == m_cCapacity) 232 278 realloc_grow(m_cCapacity + DefaultCapacity); 233 memmove(&m_pArray[i + 1], &m_pArray[i], (m_cSize - i) * sizeof( list_type));234 ListHelper<T, list_type>::set(m_pArray, i, val);279 memmove(&m_pArray[i + 1], &m_pArray[i], (m_cSize - i) * sizeof(ITYPE)); 280 ListHelper<T, ITYPE>::set(m_pArray, i, val); 235 281 ++m_cSize; 282 m_guard.leaveWrite(); 236 283 237 284 return *this; … … 245 292 * @throws std::bad_alloc 246 293 */ 247 ListBase<T, TYPE> &prepend(const T &val)294 ListBase<T, ITYPE, MT> &prepend(const T &val) 248 295 { 249 296 return insert(0, val); … … 257 304 * @throws std::bad_alloc 258 305 */ 259 ListBase<T, TYPE> &prepend(const ListBase<T, TYPE> &other) 260 { 306 ListBase<T, ITYPE, MT> &prepend(const ListBase<T, ITYPE, MT> &other) 307 { 308 m_guard.enterWrite(); 261 309 if (m_cCapacity - m_cSize < other.m_cSize) 262 310 realloc_grow(m_cCapacity + (other.m_cSize - (m_cCapacity - m_cSize))); 263 memmove(&m_pArray[other.m_cSize], &m_pArray[0], m_cSize * sizeof( list_type));264 ListHelper<T, list_type>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize);311 memmove(&m_pArray[other.m_cSize], &m_pArray[0], m_cSize * sizeof(ITYPE)); 312 ListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); 265 313 m_cSize += other.m_cSize; 314 m_guard.leaveWrite(); 266 315 267 316 return *this; … … 275 324 * @throws std::bad_alloc 276 325 */ 277 ListBase<T, TYPE> &append(const T &val) 278 { 326 ListBase<T, ITYPE, MT> &append(const T &val) 327 { 328 m_guard.enterWrite(); 279 329 if (m_cSize == m_cCapacity) 280 330 realloc_grow(m_cCapacity + DefaultCapacity); 281 ListHelper<T, list_type>::set(m_pArray, m_cSize, val);331 ListHelper<T, ITYPE>::set(m_pArray, m_cSize, val); 282 332 ++m_cSize; 333 m_guard.leaveWrite(); 283 334 284 335 return *this; … … 292 343 * @throws std::bad_alloc 293 344 */ 294 ListBase<T, TYPE> &append(const ListBase<T, TYPE> &other) 295 { 345 ListBase<T, ITYPE, MT> &append(const ListBase<T, ITYPE, MT> &other) 346 { 347 m_guard.enterWrite(); 296 348 if (m_cCapacity - m_cSize < other.m_cSize) 297 349 realloc_grow(m_cCapacity + (other.m_cSize - (m_cCapacity - m_cSize))); 298 ListHelper<T, list_type>::copyTo(m_pArray, other.m_pArray, m_cSize, other.m_cSize);350 ListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, m_cSize, other.m_cSize); 299 351 m_cSize += other.m_cSize; 352 m_guard.leaveWrite(); 300 353 301 354 return *this; … … 309 362 * @return a reference to this list. 310 363 */ 311 ListBase<T, TYPE> &operator=(const ListBase<T, TYPE>& other)364 ListBase<T, ITYPE, MT> &operator=(const ListBase<T, ITYPE, MT>& other) 312 365 { 313 366 /* Prevent self assignment */ … … 315 368 return *this; 316 369 370 m_guard.enterWrite(); 317 371 /* Values cleanup */ 318 ListHelper<T, list_type>::eraseRange(m_pArray, 0, m_cSize);372 ListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); 319 373 320 374 /* Copy */ … … 322 376 realloc_grow(other.m_cSize); 323 377 m_cSize = other.m_cSize; 324 ListHelper<T, list_type>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); 378 ListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); 379 m_guard.leaveWrite(); 325 380 326 381 return *this; … … 337 392 * @return a reference to this list. 338 393 */ 339 ListBase<T, TYPE> &replace(size_t i, const T &val) 340 { 341 ListHelper<T, list_type>::erase(m_pArray, i); 342 ListHelper<T, list_type>::set(m_pArray, i, val); 394 ListBase<T, ITYPE, MT> &replace(size_t i, const T &val) 395 { 396 m_guard.enterWrite(); 397 ListHelper<T, ITYPE>::erase(m_pArray, i); 398 ListHelper<T, ITYPE>::set(m_pArray, i, val); 399 m_guard.leaveWrite(); 343 400 344 401 return *this; … … 346 403 347 404 /** 348 * Return the first item as constant reference.405 * Return the first item as constant object. 349 406 * 350 407 * @note No boundary checks are done. Make sure @a i is equal or greater zero … … 353 410 * @return The first item. 354 411 */ 355 const T &first() const 356 { 357 return ListHelper<T, list_type>::at(m_pArray, 0); 358 } 359 360 /** 361 * Return the first item as mutable reference. 412 const GET_RTYPE first() const 413 { 414 m_guard.enterRead(); 415 const GET_RTYPE res = ListHelper<T, ITYPE>::at(m_pArray, 0); 416 m_guard.leaveRead(); 417 return res; 418 } 419 420 /** 421 * Return the first item. 362 422 * 363 423 * @note No boundary checks are done. Make sure @a i is equal or greater zero … … 366 426 * @return The first item. 367 427 */ 368 T &first() 369 { 370 return ListHelper<T, list_type>::at(m_pArray, 0); 371 } 372 373 /** 374 * Return the last item as constant reference. 428 GET_RTYPE first() 429 { 430 m_guard.enterRead(); 431 GET_RTYPE res = ListHelper<T, ITYPE>::at(m_pArray, 0); 432 m_guard.leaveRead(); 433 return res; 434 } 435 436 /** 437 * Return the last item as constant object. 375 438 * 376 439 * @note No boundary checks are done. Make sure @a i is equal or greater zero … … 379 442 * @return The last item. 380 443 */ 381 const T &last() const 382 { 383 return ListHelper<T, list_type>::at(m_pArray, m_cSize - 1); 384 } 385 386 /** 387 * Return the last item as mutable reference. 444 const GET_RTYPE last() const 445 { 446 m_guard.enterRead(); 447 const GET_RTYPE res = ListHelper<T, ITYPE>::at(m_pArray, m_cSize - 1); 448 m_guard.leaveRead(); 449 return res; 450 } 451 452 /** 453 * Return the last item. 388 454 * 389 455 * @note No boundary checks are done. Make sure @a i is equal or greater zero … … 392 458 * @return The last item. 393 459 */ 394 T &last() 395 { 396 return ListHelper<T, list_type>::at(m_pArray, m_cSize - 1); 397 } 398 399 /** 400 * Return the item at position @a i as constant reference. 460 GET_RTYPE last() 461 { 462 m_guard.enterRead(); 463 GET_RTYPE res = ListHelper<T, ITYPE>::at(m_pArray, m_cSize - 1); 464 m_guard.leaveRead(); 465 return res; 466 } 467 468 /** 469 * Return the item at position @a i as constant object. 401 470 * 402 471 * @note No boundary checks are done. Make sure @a i is equal or greater zero … … 406 475 * @return The item at position @a i. 407 476 */ 408 const T &at(size_t i) const 409 { 410 return ListHelper<T, list_type>::at(m_pArray, i); 411 } 412 413 /** 414 * Return the item at position @a i as mutable reference. 477 const GET_RTYPE at(size_t i) const 478 { 479 m_guard.enterRead(); 480 const GET_RTYPE res = ListHelper<T, ITYPE>::at(m_pArray, i); 481 m_guard.leaveRead(); 482 return res; 483 } 484 485 /** 486 * Return the item at position @a i. 415 487 * 416 488 * @note No boundary checks are done. Make sure @a i is equal or greater zero … … 420 492 * @return The item at position @a i. 421 493 */ 422 T &at(size_t i) 423 { 424 return ListHelper<T, list_type>::at(m_pArray, i); 494 GET_RTYPE at(size_t i) 495 { 496 m_guard.enterRead(); 497 GET_RTYPE res = ListHelper<T, ITYPE>::at(m_pArray, i); 498 m_guard.leaveRead(); 499 return res; 425 500 } 426 501 … … 436 511 T &operator[](size_t i) 437 512 { 438 return ListHelper<T, list_type>::at(m_pArray, i); 513 m_guard.enterRead(); 514 T &res = ListHelper<T, ITYPE>::at(m_pArray, i); 515 m_guard.leaveRead(); 516 return res; 439 517 } 440 518 … … 448 526 T value(size_t i) const 449 527 { 528 m_guard.enterRead(); 450 529 if (i >= m_cSize) 530 { 531 m_guard.leaveRead(); 451 532 return T(); 452 return ListHelper<T, list_type>::at(m_pArray, i); 533 } 534 T res = ListHelper<T, ITYPE>::at(m_pArray, i); 535 m_guard.leaveRead(); 536 return res; 453 537 } 454 538 … … 463 547 T value(size_t i, const T &defaultVal) const 464 548 { 549 m_guard.enterRead(); 465 550 if (i >= m_cSize) 551 { 552 m_guard.leaveRead(); 466 553 return defaultVal; 467 return ListHelper<T, list_type>::at(m_pArray, i); 554 } 555 T res = ListHelper<T, ITYPE>::at(m_pArray, i); 556 m_guard.leaveRead(); 557 return res; 468 558 } 469 559 … … 478 568 void removeAt(size_t i) 479 569 { 480 ListHelper<T, list_type>::erase(m_pArray, i); 570 m_guard.enterWrite(); 571 ListHelper<T, ITYPE>::erase(m_pArray, i); 481 572 /* Not last element? */ 482 573 if (i < m_cSize - 1) 483 memmove(&m_pArray[i], &m_pArray[i + 1], (m_cSize - i - 1) * sizeof( list_type));574 memmove(&m_pArray[i], &m_pArray[i + 1], (m_cSize - i - 1) * sizeof(ITYPE)); 484 575 --m_cSize; 576 m_guard.leaveWrite(); 485 577 } 486 578 … … 497 589 void removeRange(size_t iFrom, size_t iTo) 498 590 { 499 ListHelper<T, list_type>::eraseRange(m_pArray, iFrom, iTo - iFrom); 591 m_guard.enterWrite(); 592 ListHelper<T, ITYPE>::eraseRange(m_pArray, iFrom, iTo - iFrom); 500 593 /* Not last elements? */ 501 594 if (m_cSize - iTo > 0) 502 memmove(&m_pArray[iFrom], &m_pArray[iTo], (m_cSize - iTo) * sizeof( list_type));595 memmove(&m_pArray[iFrom], &m_pArray[iTo], (m_cSize - iTo) * sizeof(ITYPE)); 503 596 m_cSize -= iTo - iFrom; 597 m_guard.leaveWrite(); 504 598 } 505 599 … … 509 603 void clear() 510 604 { 605 m_guard.enterWrite(); 511 606 /* Values cleanup */ 512 ListHelper<T, list_type>::eraseRange(m_pArray, 0, m_cSize);607 ListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); 513 608 if (m_cSize != DefaultCapacity) 514 609 realloc_grow(DefaultCapacity); 515 610 m_cSize = 0; 611 m_guard.leaveWrite(); 516 612 } 517 613 … … 536 632 && m_pArray) 537 633 { 538 ListHelper<T, list_type>::eraseRange(m_pArray, cNewSize, m_cSize - cNewSize);634 ListHelper<T, ITYPE>::eraseRange(m_pArray, cNewSize, m_cSize - cNewSize); 539 635 m_cSize -= m_cSize - cNewSize; 540 636 } … … 552 648 if (cNewSize > 0) 553 649 { 554 m_pArray = static_cast< list_type*>(RTMemRealloc(m_pArray, sizeof(list_type) * cNewSize));650 m_pArray = static_cast<ITYPE*>(RTMemRealloc(m_pArray, sizeof(ITYPE) * cNewSize)); 555 651 if (!m_pArray) 556 652 { … … 574 670 /* Resize the array. */ 575 671 m_cCapacity = cNewSize; 576 m_pArray = static_cast< list_type*>(RTMemRealloc(m_pArray, sizeof(list_type) * cNewSize));672 m_pArray = static_cast<ITYPE*>(RTMemRealloc(m_pArray, sizeof(ITYPE) * cNewSize)); 577 673 if (!m_pArray) 578 674 { … … 586 682 } 587 683 588 /**589 * Which type of list should be created. This depends on the size of T. If590 * T is a native type (int, bool, ptr, ...), the list will contain the591 * values itself. If the size is bigger than the size of a void*, the list592 * contains pointers to the values. This could be specialized like for the593 * 64-bit integer types.594 */595 typedef TYPE list_type;596 597 684 /** The internal list array. */ 598 list_type*m_pArray;685 ITYPE *m_pArray; 599 686 /** The current count of items in use. */ 600 687 size_t m_cSize; 601 688 /** The current capacity of the internal array. */ 602 689 size_t m_cCapacity; 690 /** The guard used to serialize the access to the items. */ 691 ListGuard<MT> m_guard; 603 692 }; 604 693 605 template <class T, typename TYPE>606 const size_t ListBase<T, TYPE>::DefaultCapacity = 10;694 template <class T, typename ITYPE, bool MT> 695 const size_t ListBase<T, ITYPE, MT>::DefaultCapacity = 10; 607 696 608 697 /** … … 611 700 * @see ListBase 612 701 */ 613 template <class T, typename TYPE = typename if_<(sizeof(T) > sizeof(void*)), T*, T>::result>614 class list : public ListBase<T, TYPE> {};702 template <class T, typename ITYPE = typename if_<(sizeof(T) > sizeof(void*)), T*, T>::result> 703 class list : public ListBase<T, ITYPE, false> {}; 615 704 616 705 /** 617 * Specializ ationclass for using the native type list for unsigned 64-bit706 * Specialized class for using the native type list for unsigned 64-bit 618 707 * values even on a 32-bit host. 619 708 * … … 621 710 */ 622 711 template <> 623 class list<uint64_t>: public ListBase<uint64_t, uint64_t > {};712 class list<uint64_t>: public ListBase<uint64_t, uint64_t, false> {}; 624 713 625 714 /** 626 * Specializ ationclass for using the native type list for signed 64-bit715 * Specialized class for using the native type list for signed 64-bit 627 716 * values even on a 32-bit host. 628 717 * … … 630 719 */ 631 720 template <> 632 class list<int64_t>: public ListBase<int64_t, int64_t > {};721 class list<int64_t>: public ListBase<int64_t, int64_t, false> {}; 633 722 634 723 /** @} */ -
trunk/include/iprt/cpp/meta.h
r36508 r36524 70 70 }; 71 71 72 /** 73 * Check if @a T is a pointer or not at compile time and dependent of the 74 * result TrueResult or FalseResult will be defined. 75 * 76 * False version of if_ptr. 77 * 78 * @param Condition Condition to check. 79 * @param TrueResult Result when condition is true. 80 * @param FalseResult Result when condition is false 81 */ 82 template <class T, typename TrueResult, typename FalseResult> 83 struct if_ptr 84 { 85 typedef FalseResult result; 86 }; 87 88 /** 89 * Check if @a T is a pointer or not at compile time and dependent of the 90 * result TrueResult or FalseResult will be defined. 91 * 92 * True specialization of of_ptr. 93 * 94 * @param Condition Condition to check. 95 * @param TrueResult Result when condition is true. 96 * @param FalseResult Result when condition is false 97 */ 98 template <class T, typename TrueResult, typename FalseResult> 99 struct if_ptr<T*, TrueResult, FalseResult> 100 { 101 typedef TrueResult result; 102 }; 103 72 104 /** @} */ 73 105 -
trunk/include/iprt/semaphore.h
r36190 r36524 40 40 * This module implements all kinds of event and mutex semaphores; in addition 41 41 * to these, IPRT implements "critical sections", which are fast recursive 42 * mutexes (see @ref grp_rt_critsect ). C++ users may find @ref grp_rt_ lock42 * mutexes (see @ref grp_rt_critsect ). C++ users may find @ref grp_rt_cpp_lock 43 43 * interesting. 44 44 *
Note:
See TracChangeset
for help on using the changeset viewer.