Changeset 45520 in vbox
- Timestamp:
- Apr 12, 2013 2:22:41 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/list.h
r37861 r45520 5 5 6 6 /* 7 * Copyright (C) 2011 Oracle Corporation7 * Copyright (C) 2011-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 30 30 #include <VBox/com/ptr.h> 31 31 #include <VBox/com/string.h> 32 #include <VBox/com/array.h> 32 33 #include <iprt/cpp/list.h> 34 33 35 34 36 /** … … 55 57 * @throws std::bad_alloc 56 58 */ 57 RTCList(size_t cCapacity = BASE:: DefaultCapacity)58 : BASE(cCapacity) {}59 RTCList(size_t cCapacity = BASE::kDefaultCapacity) 60 : BASE(cCapacity) {} 59 61 60 62 /* Define our own new and delete. */ … … 85 87 * @throws std::bad_alloc 86 88 */ 87 RTCList(size_t cCapacity = BASE:: DefaultCapacity)88 : BASE(cCapacity) {}89 RTCList(size_t cCapacity = BASE::kDefaultCapacity) 90 : BASE(cCapacity) {} 89 91 90 92 /* Define our own new and delete. */ … … 98 100 */ 99 101 template <> 100 class RTCList< Utf8Str>: public RTCListBase<Utf8Str,Utf8Str*, false>102 class RTCList<com::Utf8Str>: public RTCListBase<com::Utf8Str, com::Utf8Str*, false> 101 103 { 102 104 /* Traits */ 103 typedef Utf8StrT;105 typedef com::Utf8Str T; 104 106 typedef T *ITYPE; 105 107 static const bool MT = false; … … 115 117 * @throws std::bad_alloc 116 118 */ 117 RTCList(size_t cCapacity = BASE:: DefaultCapacity)118 : BASE(cCapacity) {}119 RTCList(size_t cCapacity = BASE::kDefaultCapacity) 120 : BASE(cCapacity) {} 119 121 120 122 /** … … 131 133 { 132 134 com::SafeArray<IN_BSTR> sfaOther(ComSafeArrayInArg(other)); 133 realloc(sfaOther.size()); 134 m_cSize = sfaOther.size(); 135 for (size_t i = 0; i < m_cSize; ++i) 135 size_t const cElementsOther = sfaOther.size(); 136 resizeArray(cElementsOther); 137 m_cElements = cElementsOther; 138 for (size_t i = 0; i < cElementsOther; ++i) 136 139 RTCListHelper<T, ITYPE>::set(m_pArray, i, T(sfaOther[i])); 137 140 } … … 148 151 */ 149 152 RTCList(const com::SafeArray<IN_BSTR> &other) 150 : BASE(other.size())151 { 152 for (size_t i = 0; i < m_c Size; ++i)153 : BASE(other.size()) 154 { 155 for (size_t i = 0; i < m_cElements; ++i) 153 156 RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i])); 154 157 } … … 165 168 { 166 169 m_guard.enterWrite(); 170 167 171 /* Values cleanup */ 168 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); 172 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements); 173 169 174 /* Copy */ 170 if (other.size() != m_cCapacity) 171 realloc_no_elements_clean(other.size()); 172 m_cSize = other.size(); 173 for (size_t i = 0; i < other.size(); ++i) 175 size_t cElementsOther = other.size(); 176 if (cElementsOther != m_cCapacity) 177 resizeArrayNoErase(cElementsOther); 178 m_cElements = cElementsOther; 179 for (size_t i = 0; i < cElementsOther; ++i) 174 180 RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i])); 181 175 182 m_guard.leaveWrite(); 176 177 183 return *this; 178 184 } -
trunk/include/VBox/com/mtlist.h
r37861 r45520 5 5 6 6 /* 7 * Copyright (C) 2011 Oracle Corporation7 * Copyright (C) 2011-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 30 30 #include <VBox/com/ptr.h> 31 31 #include <VBox/com/string.h> 32 #include <VBox/com/array.h> 32 33 #include <iprt/cpp/mtlist.h> 33 34 … … 55 56 * @throws std::bad_alloc 56 57 */ 57 RTC List(size_t cCapacity = BASE::DefaultCapacity)58 : BASE(cCapacity) {}58 RTCMTList(size_t cCapacity = BASE::kDefaultCapacity) 59 : BASE(cCapacity) {} 59 60 60 61 /* Define our own new and delete. */ … … 85 86 * @throws std::bad_alloc 86 87 */ 87 RTC List(size_t cCapacity = BASE::DefaultCapacity)88 RTCMTList(size_t cCapacity = BASE::kDefaultCapacity) 88 89 : BASE(cCapacity) {} 89 90 … … 98 99 */ 99 100 template <> 100 class RTCMTList< Utf8Str>: public RTCListBase<Utf8Str, Utf8Str*, true>101 class RTCMTList<com::Utf8Str>: public RTCListBase<com::Utf8Str, com::Utf8Str *, true> 101 102 { 102 103 /* Traits */ 103 typedef Utf8StrT;104 typedef com::Utf8Str T; 104 105 typedef T *ITYPE; 105 106 static const bool MT = true; … … 115 116 * @throws std::bad_alloc 116 117 */ 117 RTCMTList(size_t cCapacity = BASE:: DefaultCapacity)118 : BASE(cCapacity) {}118 RTCMTList(size_t cCapacity = BASE::kDefaultCapacity) 119 : BASE(cCapacity) {} 119 120 120 121 /** … … 131 132 { 132 133 com::SafeArray<IN_BSTR> sfaOther(ComSafeArrayInArg(other)); 133 realloc(sfaOther.size()); 134 m_cSize = sfaOther.size(); 135 for (size_t i = 0; i < m_cSize; ++i) 134 size_t const cElementsOther = sfaOther.size(); 135 resizeArray(cElementsOther); 136 m_cElements = cElementsOther; 137 for (size_t i = 0; i < cElementsOther; ++i) 136 138 RTCListHelper<T, ITYPE>::set(m_pArray, i, T(sfaOther[i])); 137 139 } … … 150 152 : BASE(other.size()) 151 153 { 152 for (size_t i = 0; i < m_c Size; ++i)154 for (size_t i = 0; i < m_cElements; ++i) 153 155 RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i])); 154 156 } … … 166 168 m_guard.enterWrite(); 167 169 /* Values cleanup */ 168 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_c Size);170 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements); 169 171 /* Copy */ 170 172 if (other.size() != m_cCapacity) 171 re alloc_no_elements_clean(other.size());172 m_c Size= other.size();173 resizeArrayNoErase(other.size()); 174 m_cElements = other.size(); 173 175 for (size_t i = 0; i < other.size(); ++i) 174 176 RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i])); -
trunk/include/iprt/cpp/list.h
r37861 r45520 4 4 5 5 /* 6 * Copyright (C) 2011 Oracle Corporation6 * Copyright (C) 2011-2013 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 30 30 #include <iprt/mem.h> 31 31 #include <iprt/string.h> /* for memcpy */ 32 #include <iprt/assert.h> 32 33 33 34 #include <new> /* For std::bad_alloc */ … … 134 135 static inline void set(T2 *p, size_t i, const T1 &v) { p[i] = v; } 135 136 static inline T1 & at(T2 *p, size_t i) { return p[i]; } 136 static inline size_t find(T2 *p, const T1 &v, size_t cSize) 137 { 138 size_t i = 0; 139 while(i < cSize) 140 { 137 static inline size_t find(T2 *p, const T1 &v, size_t cElements) 138 { 139 size_t i = cElements; 140 while (i-- > 0) 141 141 if (p[i] == v) 142 break; 143 ++i; 144 } 145 return i; 142 return i; 143 return cElements; 146 144 } 147 145 static inline void copyTo(T2 *p, T2 *const p1 , size_t iTo, size_t cSize) … … 163 161 static inline void set(T1 **p, size_t i, const T1 &v) { p[i] = new T1(v); } 164 162 static inline T1 & at(T1 **p, size_t i) { return *p[i]; } 165 static inline size_t find(T1 **p, const T1 &v, size_t cSize) 166 { 167 size_t i = 0; 168 while(i < cSize) 169 { 163 static inline size_t find(T1 **p, const T1 &v, size_t cElements) 164 { 165 size_t i = cElements; 166 while (i-- > 0) 170 167 if (*p[i] == v) 171 break; 172 ++i; 173 } 174 return i; 168 return i; 169 return cElements; 175 170 } 176 171 static inline void copyTo(T1 **p, T1 **const p1 , size_t iTo, size_t cSize) … … 180 175 } 181 176 static inline void erase(T1 **p, size_t i) { delete p[i]; } 182 static inline void eraseRange(T1 **p, size_t cFrom, size_t cSize)183 { 184 for (size_t i = cFrom; i < cFrom + cSize; ++i)185 delete p[i ];177 static inline void eraseRange(T1 **p, size_t iFrom, size_t cItems) 178 { 179 while (cItems-- > 0) 180 delete p[iFrom++]; 186 181 } 187 182 }; … … 195 190 class RTCListBase 196 191 { 197 /** 198 * Traits 192 /** @name Traits. 199 193 * 200 194 * Defines the return type of most of the getter methods. If the internal 201 195 * used type is a pointer, we return a reference. If not we return by 202 196 * value. 197 * 198 * @{ 203 199 */ 204 200 typedef typename RTCIfPtr<ITYPE, T&, T>::result GET_RTYPE; 205 201 typedef typename RTCIfPtr<ITYPE, const T&, T>::result GET_CRTYPE; 202 /** @} */ 206 203 207 204 public: … … 214 211 * @throws std::bad_alloc 215 212 */ 216 RTCListBase(size_t cCapacity = DefaultCapacity)217 : m_pArray(0)218 , m_cSize(0)219 , m_cCapacity(0)213 RTCListBase(size_t cCapacity = kDefaultCapacity) 214 : m_pArray(0) 215 , m_cElements(0) 216 , m_cCapacity(0) 220 217 { 221 218 if (cCapacity > 0) 222 realloc_grow(cCapacity);219 growArray(cCapacity); 223 220 } 224 221 … … 233 230 */ 234 231 RTCListBase(const RTCListBase<T, ITYPE, MT>& other) 235 : m_pArray(0) 236 , m_cSize(0) 237 , m_cCapacity(0) 238 { 239 realloc_no_elements_clean(other.m_cSize); 240 RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); 241 m_cSize = other.m_cSize; 232 : m_pArray(0) 233 , m_cElements(0) 234 , m_cCapacity(0) 235 { 236 other.m_guard.enterRead(); 237 238 size_t const cElementsOther = other.m_cElements; 239 resizeArrayNoErase(cElementsOther); 240 RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, cElementsOther); 241 m_cElements = cElementsOther; 242 243 other.m_guard.leaveRead(); 242 244 } 243 245 … … 247 249 ~RTCListBase() 248 250 { 249 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_c Size);251 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements); 250 252 if (m_pArray) 253 { 251 254 RTMemFree(m_pArray); 255 m_pArray = NULL; 256 } 257 m_cElements = m_cCapacity = 0; 252 258 } 253 259 … … 256 262 * 257 263 * If the new capacity is bigger than the old size, it will be simply 258 * preallocated more space for the new items. If the new capacity is264 * preallocated more space for the new items. If the new capacity is 259 265 * smaller than the previous size, items at the end of the list will be 260 266 * deleted. … … 266 272 { 267 273 m_guard.enterWrite(); 268 re alloc(cCapacity);274 resizeArray(cCapacity); 269 275 m_guard.leaveWrite(); 270 276 } … … 275 281 * @return The actual capacity. 276 282 */ 277 size_t capacity() const { return m_cCapacity; } 283 size_t capacity() const 284 { 285 m_guard.enterRead(); 286 size_t cRet = m_cCapacity; 287 m_guard.leaveRead(); 288 return cRet; 289 } 278 290 279 291 /** … … 282 294 * @return True if there is more than zero items, false otherwise. 283 295 */ 284 bool isEmpty() const { return m_cSize == 0; } 296 bool isEmpty() const 297 { 298 m_guard.enterRead(); 299 bool fEmpty = m_cElements == 0; 300 m_guard.leaveRead(); 301 return fEmpty; 302 } 285 303 286 304 /** … … 289 307 * @return The current element count. 290 308 */ 291 size_t size() const { return m_cSize; } 309 size_t size() const 310 { 311 m_guard.enterRead(); 312 size_t cRet = m_cElements; 313 m_guard.leaveRead(); 314 return cRet; 315 } 292 316 293 317 /** 294 318 * Inserts an item to the list at position @a i. 295 319 * 296 * @param i The position of the new item. 320 * @param i The position of the new item. The must be within or at the 321 * exact end of the list. Indexes specified beyond the end of 322 * the list will be changed to an append() operation and strict 323 * builds will raise an assert. 297 324 * @param val The new item. 298 325 * @return a reference to this list. … … 302 329 { 303 330 m_guard.enterWrite(); 304 if (m_cSize == m_cCapacity) 305 realloc_grow(m_cCapacity + DefaultCapacity); 306 memmove(&m_pArray[i + 1], &m_pArray[i], (m_cSize - i) * sizeof(ITYPE)); 331 332 AssertMsgStmt(i <= m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements); 333 334 if (m_cElements == m_cCapacity) 335 growArray(m_cCapacity + kDefaultCapacity); 336 337 memmove(&m_pArray[i + 1], &m_pArray[i], (m_cElements - i) * sizeof(ITYPE)); 307 338 RTCListHelper<T, ITYPE>::set(m_pArray, i, val); 308 ++m_cSize; 309 m_guard.leaveWrite(); 310 339 ++m_cElements; 340 341 m_guard.leaveWrite(); 342 return *this; 343 } 344 345 /** 346 * Inserts a list to the list at position @a i. 347 * 348 * @param i The position of the new item. The must be within or at the 349 * exact end of the list. Indexes specified beyond the end of 350 * the list will be changed to an append() operation and strict 351 * builds will raise an assert. 352 * @param other The other list. This MUST not be the same as the destination 353 * list, will assert and return without doing anything if this 354 * happens. 355 * @return a reference to this list. 356 * @throws std::bad_alloc 357 */ 358 RTCListBase<T, ITYPE, MT> &insert(size_t i, const RTCListBase<T, ITYPE, MT> &other) 359 { 360 AssertReturn(this != &other, *this); 361 362 other.m_guard.enterRead(); 363 m_guard.enterWrite(); 364 365 AssertMsgStmt(i <= m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements); 366 367 size_t cElementsOther = other.m_cElements; 368 if (RT_LIKELY(cElementsOther > 0)) 369 { 370 if (m_cCapacity - m_cElements < cElementsOther) 371 growArray(m_cCapacity + (cElementsOther - (m_cCapacity - m_cElements))); 372 if (i < m_cElements) 373 memmove(&m_pArray[i + cElementsOther], &m_pArray[i], (m_cElements - i) * sizeof(ITYPE)); 374 375 RTCListHelper<T, ITYPE>::copyTo(&m_pArray[i], other.m_pArray, 0, cElementsOther); 376 m_cElements += cElementsOther; 377 } 378 379 m_guard.leaveWrite(); 380 other.m_guard.leaveRead(); 311 381 return *this; 312 382 } … … 333 403 RTCListBase<T, ITYPE, MT> &prepend(const RTCListBase<T, ITYPE, MT> &other) 334 404 { 335 m_guard.enterWrite(); 336 if (m_cCapacity - m_cSize < other.m_cSize) 337 realloc_grow(m_cCapacity + (other.m_cSize - (m_cCapacity - m_cSize))); 338 memmove(&m_pArray[other.m_cSize], &m_pArray[0], m_cSize * sizeof(ITYPE)); 339 RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); 340 m_cSize += other.m_cSize; 341 m_guard.leaveWrite(); 342 343 return *this; 405 return insert(0, other); 344 406 } 345 407 … … 354 416 { 355 417 m_guard.enterWrite(); 356 if (m_c Size== m_cCapacity)357 realloc_grow(m_cCapacity +DefaultCapacity);358 RTCListHelper<T, ITYPE>::set(m_pArray, m_c Size, val);359 ++m_c Size;418 if (m_cElements == m_cCapacity) 419 growArray(m_cCapacity + kDefaultCapacity); 420 RTCListHelper<T, ITYPE>::set(m_pArray, m_cElements, val); 421 ++m_cElements; 360 422 m_guard.leaveWrite(); 361 423 … … 366 428 * Append a list of type T to the list. 367 429 * 368 * @param other The list to append. 430 * @param other The list to append. Must not be the same as the destination 431 * list, will assert and return without doing anything. 369 432 * @return a reference to this list. 370 433 * @throws std::bad_alloc … … 372 435 RTCListBase<T, ITYPE, MT> &append(const RTCListBase<T, ITYPE, MT> &other) 373 436 { 374 m_guard.enterWrite(); 375 if (RT_LIKELY(other.m_cSize > 0)) 376 { 377 if (m_cCapacity - m_cSize < other.m_cSize) 378 realloc_grow(m_cCapacity + (other.m_cSize - (m_cCapacity - m_cSize))); 379 RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, m_cSize, other.m_cSize); 380 m_cSize += other.m_cSize; 381 } 382 m_guard.leaveWrite(); 383 437 AssertReturn(this != &other, *this); 438 439 other.m_guard.enterRead(); 440 m_guard.enterWrite(); 441 442 insert(m_cElements, other); 443 444 m_guard.leaveWrite(); 445 other.m_guard.leaveRead(); 384 446 return *this; 385 447 } 386 448 387 449 /** 388 * Copy the items of the other list into this list. All previous items of 389 * this list are deleted. 450 * Copy the items of the other list into this list. 451 * 452 * All previous items of this list are deleted. 390 453 * 391 454 * @param other The list to copy. … … 398 461 return *this; 399 462 400 m_guard.enterWrite(); 463 other.m_guard.enterRead(); 464 m_guard.enterWrite(); 465 401 466 /* Delete all items. */ 402 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); 467 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements); 468 403 469 /* Need we to realloc memory. */ 404 if (other.m_cSize != m_cCapacity) 405 realloc_no_elements_clean(other.m_cSize); 406 m_cSize = other.m_cSize; 470 if (other.m_cElements != m_cCapacity) 471 resizeArrayNoErase(other.m_cElements); 472 m_cElements = other.m_cElements; 473 407 474 /* Copy new items. */ 408 RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); 409 m_guard.leaveWrite(); 410 475 RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cElements); 476 477 m_guard.leaveWrite(); 478 other.m_guard.leaveRead(); 411 479 return *this; 412 480 } … … 415 483 * Replace an item in the list. 416 484 * 417 * @note No boundary checks are done. Make sure @a i is equal or greater zero 418 * and smaller than RTCList::size. 419 * 420 * @param i The position of the item to replace. 485 * @param i The position of the item to replace. If this is out of range, 486 * the request will be ignored, strict builds will assert. 421 487 * @param val The new value. 422 488 * @return a reference to this list. … … 425 491 { 426 492 m_guard.enterWrite(); 427 RTCListHelper<T, ITYPE>::erase(m_pArray, i); 428 RTCListHelper<T, ITYPE>::set(m_pArray, i, val); 429 m_guard.leaveWrite(); 430 493 494 if (i < m_cElements) 495 { 496 RTCListHelper<T, ITYPE>::erase(m_pArray, i); 497 RTCListHelper<T, ITYPE>::set(m_pArray, i, val); 498 } 499 else 500 AssertMsgFailed(("i=%zu m_cElements=%zu\n", i, m_cElements)); 501 502 m_guard.leaveWrite(); 431 503 return *this; 432 504 } … … 435 507 * Return the first item as constant object. 436 508 * 437 * @ note No boundary checks are done. Make sure there is at least one438 * element.439 * 440 * @return The first item.509 * @return A reference or pointer to the first item. 510 * 511 * @note No boundary checks are done. Make sure there is at least one 512 * element. 441 513 */ 442 514 GET_CRTYPE first() const 443 515 { 444 516 m_guard.enterRead(); 517 Assert(m_cElements > 0); 445 518 GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, 0); 446 519 m_guard.leaveRead(); … … 451 524 * Return the first item. 452 525 * 453 * @ note No boundary checks are done. Make sure there is at least one454 * element.455 * 456 * @return The first item.526 * @return A reference or pointer to the first item. 527 * 528 * @note No boundary checks are done. Make sure there is at least one 529 * element. 457 530 */ 458 531 GET_RTYPE first() 459 532 { 460 533 m_guard.enterRead(); 534 Assert(m_cElements > 0); 461 535 GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, 0); 462 536 m_guard.leaveRead(); … … 467 541 * Return the last item as constant object. 468 542 * 469 * @ note No boundary checks are done. Make sure there is at least one470 * element.471 * 472 * @return The last item.543 * @return A reference or pointer to the last item. 544 * 545 * @note No boundary checks are done. Make sure there is at least one 546 * element. 473 547 */ 474 548 GET_CRTYPE last() const 475 549 { 476 550 m_guard.enterRead(); 477 GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, m_cSize - 1); 551 Assert(m_cElements > 0); 552 GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, m_cElements - 1); 478 553 m_guard.leaveRead(); 479 554 return res; … … 483 558 * Return the last item. 484 559 * 485 * @ note No boundary checks are done. Make sure there is at least one486 * element.487 * 488 * @return The last item.560 * @return A reference or pointer to the last item. 561 * 562 * @note No boundary checks are done. Make sure there is at least one 563 * element. 489 564 */ 490 565 GET_RTYPE last() 491 566 { 492 567 m_guard.enterRead(); 493 GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, m_cSize - 1); 568 Assert(m_cElements > 0); 569 GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, m_cElements - 1); 494 570 m_guard.leaveRead(); 495 571 return res; … … 499 575 * Return the item at position @a i as constant object. 500 576 * 501 * @ note No boundary checks are done. Make sure @a i is equal or greater zero502 * and smaller than RTCList::size.503 * 504 * @param i The position of the item to return.577 * @param i The position of the item to return. This better not be out of 578 * bounds, however should it be the last element of the array 579 * will be return and strict builds will raise an assertion. 580 * Should the array be empty, a crash is very likely. 505 581 * @return The item at position @a i. 506 582 */ … … 508 584 { 509 585 m_guard.enterRead(); 586 AssertMsgStmt(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements - 1); 510 587 GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, i); 511 588 m_guard.leaveRead(); … … 516 593 * Return the item at position @a i. 517 594 * 518 * @ note No boundary checks are done. Make sure @a i is equal or greater zero519 * and smaller than RTCList::size.520 * 521 * @param i The position of the item to return.595 * @param i The position of the item to return. This better not be out of 596 * bounds, however should it be the last element of the array 597 * will be return and strict builds will raise an assertion. 598 * Should the array be empty, a crash is very likely. 522 599 * @return The item at position @a i. 523 600 */ … … 525 602 { 526 603 m_guard.enterRead(); 604 AssertMsgStmt(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements - 1); 527 605 GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, i); 528 606 m_guard.leaveRead(); … … 533 611 * Return the item at position @a i as mutable reference. 534 612 * 535 * @ note No boundary checks are done. Make sure @a i is equal or greater zero536 * and smaller than RTCList::size.537 * 538 * @param i The position of the item to return.613 * @param i The position of the item to return. This better not be out of 614 * bounds, however should it be the last element of the array 615 * will be return and strict builds will raise an assertion. 616 * Should the array be empty, a crash is very likely. 539 617 * @return The item at position @a i. 540 618 */ … … 542 620 { 543 621 m_guard.enterRead(); 622 AssertMsgStmt(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements - 1); 544 623 T &res = RTCListHelper<T, ITYPE>::at(m_pArray, i); 545 624 m_guard.leaveRead(); … … 548 627 549 628 /** 550 * Return the item at position @a i. If @a i isn't valid within the list a 551 * default value is returned. 629 * Return the item at position @a i or default value if out of range. 552 630 * 553 631 * @param i The position of the item to return. 554 * @return The item at position @a i .632 * @return The item at position @a i or default value. 555 633 */ 556 634 T value(size_t i) const 557 635 { 558 636 m_guard.enterRead(); 559 if (RT_UNLIKELY(i >= m_c Size))637 if (RT_UNLIKELY(i >= m_cElements)) 560 638 { 561 639 m_guard.leaveRead(); … … 568 646 569 647 /** 570 * Return the item at position @a i. If @a i isn't valid within the list 571 * @a defaultVal is returned. 648 * Return the item at position @a i, or @a defaultVal if out of range. 572 649 * 573 650 * @param i The position of the item to return. 574 651 * @param defaultVal The value to return in case @a i is invalid. 575 * @return The item at position @a i .652 * @return The item at position @a i or @a defaultVal. 576 653 */ 577 654 T value(size_t i, const T &defaultVal) const 578 655 { 579 656 m_guard.enterRead(); 580 if (RT_UNLIKELY(i >= m_c Size))657 if (RT_UNLIKELY(i >= m_cElements)) 581 658 { 582 659 m_guard.leaveRead(); … … 597 674 { 598 675 m_guard.enterRead(); 599 bool res = RTCListHelper<T, ITYPE>::find(m_pArray, val, m_cSize) != m_cSize;600 m_guard.leaveRead(); 601 return res;676 bool fRc = RTCListHelper<T, ITYPE>::find(m_pArray, val, m_cElements) < m_cElements; 677 m_guard.leaveRead(); 678 return fRc; 602 679 } 603 680 … … 605 682 * Remove the first item. 606 683 * 607 * @note No boundary checks are done. Make sure there is at least one608 * element.684 * @note You should make sure the list isn't empty. Strict builds will assert. 685 * The other builds will quietly ignore the request. 609 686 */ 610 687 void removeFirst() … … 616 693 * Remove the last item. 617 694 * 618 * @note No boundary checks are done. Make sure there is at least one619 * element.695 * @note You should make sure the list isn't empty. Strict builds will assert. 696 * The other builds will quietly ignore the request. 620 697 */ 621 698 void removeLast() 622 699 { 623 removeAt(m_cSize - 1); 700 m_guard.enterWrite(); 701 removeAtLocked(m_cElements - 1); 702 m_guard.leaveWrite(); 624 703 } 625 704 … … 627 706 * Remove the item at position @a i. 628 707 * 629 * @note No boundary checks are done. Make sure @a i is equal or greater zero 630 * and smaller than RTCList::size. 631 * 632 * @param i The position of the item to remove. 708 * @param i The position of the item to remove. Out of bounds values will 709 * be ignored and an assertion will be raised in strict builds. 633 710 */ 634 711 void removeAt(size_t i) 635 712 { 636 713 m_guard.enterWrite(); 637 RTCListHelper<T, ITYPE>::erase(m_pArray, i); 638 /* Not last element? */ 639 if (i < m_cSize - 1) 640 memmove(&m_pArray[i], &m_pArray[i + 1], (m_cSize - i - 1) * sizeof(ITYPE)); 641 --m_cSize; 714 removeAtLocked(i); 642 715 m_guard.leaveWrite(); 643 716 } … … 646 719 * Remove a range of items from the list. 647 720 * 648 * @note No boundary checks are done. Make sure @a iFrom is equal or 649 * greater zero and smaller than RTCList::size. @a iTo has to be 650 * greater than @a iFrom and equal or smaller than RTCList::size. 651 * 652 * @param iFrom The start position of the items to remove. 653 * @param iTo The end position of the items to remove (excluded). 654 */ 655 void removeRange(size_t iFrom, size_t iTo) 656 { 657 m_guard.enterWrite(); 658 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, iFrom, iTo - iFrom); 659 /* Not last elements? */ 660 if (m_cSize - iTo > 0) 661 memmove(&m_pArray[iFrom], &m_pArray[iTo], (m_cSize - iTo) * sizeof(ITYPE)); 662 m_cSize -= iTo - iFrom; 721 * @param iStart The start position of the items to remove. 722 * @param iEnd The end position of the items to remove (excluded). 723 */ 724 void removeRange(size_t iStart, size_t iEnd) 725 { 726 AssertReturnVoid(iStart <= iEnd); 727 m_guard.enterWrite(); 728 729 AssertMsgStmt(iEnd <= m_cElements, ("iEnd=%zu m_cElements=%zu\n", iEnd, m_cElements), iEnd = m_cElements); 730 AssertMsgStmt(iStart < m_cElements, ("iStart=%zu m_cElements=%zu\n", iStart, m_cElements), iStart = m_cElements); 731 size_t const cElements = iEnd - iStart; 732 if (cElements > 0) 733 { 734 Assert(iStart < m_cElements); 735 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, iStart, cElements); 736 if (m_cElements > iEnd) 737 memmove(&m_pArray[iStart], &m_pArray[iEnd], (m_cElements - iEnd) * sizeof(ITYPE)); 738 m_cElements -= cElements; 739 } 740 663 741 m_guard.leaveWrite(); 664 742 } … … 670 748 { 671 749 m_guard.enterWrite(); 750 672 751 /* Values cleanup */ 673 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); 674 if (m_cSize != DefaultCapacity) 675 realloc_no_elements_clean(DefaultCapacity); 676 m_cSize = 0; 677 m_guard.leaveWrite(); 678 } 679 680 /** 681 * Return the raw array. For native types this is a pointer to continuous 682 * memory of the items. For pointer types this is a continuous memory of 683 * pointers to the items. 752 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements); 753 if (m_cElements != kDefaultCapacity) 754 resizeArrayNoErase(kDefaultCapacity); 755 m_cElements = 0; 756 757 m_guard.leaveWrite(); 758 } 759 760 /** 761 * Return the raw array. 762 * 763 * For native types this is a pointer to continuous memory of the items. For 764 * pointer types this is a continuous memory of pointers to the items. 684 765 * 685 766 * @warning If you change anything in the underlaying list, this memory … … 689 770 * @returns the raw memory. 690 771 */ 691 ITYPE *raw() const692 { 693 m_guard.enterRead(); 694 ITYPE * res= m_pArray;695 m_guard.leaveRead(); 696 return res;772 ITYPE *raw() const 773 { 774 m_guard.enterRead(); 775 ITYPE *pRet = m_pArray; 776 m_guard.leaveRead(); 777 return pRet; 697 778 } 698 779 … … 708 789 * The default capacity of the list. This is also used as grow factor. 709 790 */ 710 static const size_t DefaultCapacity;791 static const size_t kDefaultCapacity; 711 792 712 793 protected: 713 794 714 795 /** 715 * Generic realloc, which does some kind of boundary checking. 716 */ 717 void realloc(size_t cNewSize) 796 * Generic resizes the array, surplus elements are erased. 797 * 798 * @param cElementsNew The new array size. 799 * @throws std::bad_alloc. 800 */ 801 void resizeArray(size_t cElementsNew) 718 802 { 719 803 /* Same size? */ 720 if (c NewSize== m_cCapacity)804 if (cElementsNew == m_cCapacity) 721 805 return; 722 806 723 807 /* If we get smaller we have to delete some of the objects at the end 724 808 of the list. */ 725 if ( c NewSize < m_cSize809 if ( cElementsNew < m_cElements 726 810 && m_pArray) 727 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, cNewSize, m_cSize - cNewSize); 728 realloc_no_elements_clean(cNewSize); 729 } 730 731 void realloc_no_elements_clean(size_t cNewSize) 811 RTCListHelper<T, ITYPE>::eraseRange(m_pArray, cElementsNew, m_cElements - cElementsNew); 812 813 resizeArrayNoErase(cElementsNew); 814 } 815 816 /** 817 * Resizes the array without doing the erase() thing on surplus elements. 818 * 819 * @param cElementsNew The new array size. 820 * @throws std::bad_alloc. 821 */ 822 void resizeArrayNoErase(size_t cElementsNew) 732 823 { 733 824 /* Same size? */ 734 if (c NewSize== m_cCapacity)825 if (cElementsNew == m_cCapacity) 735 826 return; 736 827 737 /* If we get smaller we have to delete some of the objects at the end 738 of the list. */ 739 if ( cNewSize < m_cSize 740 && m_pArray) 741 m_cSize -= m_cSize - cNewSize; 742 743 /* If we get zero we delete the array it self. */ 744 if ( cNewSize == 0 745 && m_pArray) 828 /* Resize the array. */ 829 if (cElementsNew > 0) 746 830 { 747 RTMemFree(m_pArray); 748 m_pArray = 0; 749 } 750 m_cCapacity = cNewSize; 751 752 /* Resize the array. */ 753 if (cNewSize > 0) 754 { 755 m_pArray = static_cast<ITYPE*>(RTMemRealloc(m_pArray, sizeof(ITYPE) * cNewSize)); 756 if (!m_pArray) 831 void *pvNew = RTMemRealloc(m_pArray, sizeof(ITYPE) * cElementsNew); 832 if (!pvNew) 757 833 { 758 /** @todo you leak memory. */759 m_cCapacity = 0;760 m_cSize = 0;761 834 #ifdef RT_EXCEPTIONS_ENABLED 762 835 throw std::bad_alloc(); 763 836 #endif 837 return; 764 838 } 839 m_pArray = static_cast<ITYPE*>(pvNew); 765 840 } 841 /* If we get zero we delete the array it self. */ 842 else if (m_pArray) 843 { 844 RTMemFree(m_pArray); 845 m_pArray = NULL; 846 } 847 848 m_cCapacity = cElementsNew; 849 if (m_cElements > cElementsNew) 850 m_cElements = cElementsNew; 766 851 } 767 852 … … 769 854 * Special realloc method which require that the array will grow. 770 855 * 856 * @param cElementsNew The new array size. 857 * @throws std::bad_alloc. 771 858 * @note No boundary checks are done! 772 859 */ 773 void realloc_grow(size_t cNewSize) 774 { 775 /* Resize the array. */ 776 m_cCapacity = cNewSize; 777 m_pArray = static_cast<ITYPE*>(RTMemRealloc(m_pArray, sizeof(ITYPE) * cNewSize)); 778 if (!m_pArray) 860 void growArray(size_t cElementsNew) 861 { 862 Assert(cElementsNew > m_cCapacity); 863 void *pvNew = RTMemRealloc(m_pArray, sizeof(ITYPE) * cElementsNew); 864 if (pvNew) 779 865 { 780 /** @todo you leak memory. */ 781 m_cCapacity = 0; 782 m_cSize = 0; 866 m_cCapacity = cElementsNew; 867 m_pArray = static_cast<ITYPE*>(pvNew); 868 } 869 else 870 { 783 871 #ifdef RT_EXCEPTIONS_ENABLED 784 872 throw std::bad_alloc(); … … 787 875 } 788 876 877 /** 878 * Remove the item at position @a i. 879 * 880 * @param i The position of the item to remove. Out of bounds values will 881 * be ignored and an assertion will be raised in strict builds. 882 * @remarks 883 */ 884 void removeAtLocked(size_t i) 885 { 886 AssertMsgReturnVoid(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements)); 887 888 RTCListHelper<T, ITYPE>::erase(m_pArray, i); 889 if (i < m_cElements - 1) 890 memmove(&m_pArray[i], &m_pArray[i + 1], (m_cElements - i - 1) * sizeof(ITYPE)); 891 --m_cElements; 892 } 893 894 789 895 /** The internal list array. */ 790 896 ITYPE *m_pArray; 791 897 /** The current count of items in use. */ 792 size_t m_c Size;898 size_t m_cElements; 793 899 /** The current capacity of the internal array. */ 794 900 size_t m_cCapacity; … … 798 904 799 905 template <class T, typename ITYPE, bool MT> 800 const size_t RTCListBase<T, ITYPE, MT>:: DefaultCapacity = 10;906 const size_t RTCListBase<T, ITYPE, MT>::kDefaultCapacity = 10; 801 907 802 908 /** … … 820 926 * @throws std::bad_alloc 821 927 */ 822 RTCList(size_t cCapacity = BASE:: DefaultCapacity)823 : BASE(cCapacity) {}928 RTCList(size_t cCapacity = BASE::kDefaultCapacity) 929 : BASE(cCapacity) {} 824 930 825 931 RTCList(const BASE &other) 826 : BASE(other) {}932 : BASE(other) {} 827 933 828 934 /* Define our own new and delete. */ … … 851 957 * @throws std::bad_alloc 852 958 */ 853 RTCList(size_t cCapacity = BASE:: DefaultCapacity)854 : BASE(cCapacity) {}959 RTCList(size_t cCapacity = BASE::kDefaultCapacity) 960 : BASE(cCapacity) {} 855 961 856 962 /* Define our own new and delete. */ … … 879 985 * @throws std::bad_alloc 880 986 */ 881 RTCList(size_t cCapacity = BASE:: DefaultCapacity)882 : BASE(cCapacity) {}987 RTCList(size_t cCapacity = BASE::kDefaultCapacity) 988 : BASE(cCapacity) {} 883 989 884 990 /* Define our own new and delete. */ -
trunk/include/iprt/cpp/mtlist.h
r36654 r45520 4 4 5 5 /* 6 * Copyright (C) 2011 Oracle Corporation6 * Copyright (C) 2011-2013 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 29 29 #include <iprt/cpp/list.h> 30 31 30 #include <iprt/semaphore.h> 32 31 … … 42 41 { 43 42 public: 44 RTCListGuard() { int rc = RTSemRWCreate(&m_hRWSem); AssertRC(rc); } 45 ~RTCListGuard() { RTSemRWDestroy(m_hRWSem); } 43 RTCListGuard() : m_hRWSem(NIL_RTSEMRW) 44 { 45 #if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) 46 RTLOCKVALCLASS hClass; 47 int rc = RTLockValidatorClassCreate(&hClass, true /*fAutodidact*/, RT_SRC_POS, "RTCListGuard"); 48 AssertStmt(RT_SUCCESS(rc), hClass = NIL_RTLOCKVALCLASS); 49 rc = RTSemRWCreateEx(&m_hRWSem, 0 /*fFlags*/, hClass, RTLOCKVAL_SUB_CLASS_NONE, NULL /*pszNameFmt*/); 50 AssertRC(rc); 51 #else 52 int rc = RTSemRWCreateEx(&m_hRWSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, 0, NULL); 53 AssertRC(rc); 54 #endif 55 } 56 57 ~RTCListGuard() 58 { 59 RTSemRWDestroy(m_hRWSem); 60 m_hRWSem = NIL_RTSEMRW; 61 } 62 46 63 inline void enterRead() const { int rc = RTSemRWRequestRead(m_hRWSem, RT_INDEFINITE_WAIT); AssertRC(rc); } 47 64 inline void leaveRead() const { int rc = RTSemRWReleaseRead(m_hRWSem); AssertRC(rc); } … … 87 104 * @throws std::bad_alloc 88 105 */ 89 RTCMTList(size_t cCapacity = BASE:: DefaultCapacity)90 : BASE(cCapacity) {}106 RTCMTList(size_t cCapacity = BASE::kDefaultCapacity) 107 : BASE(cCapacity) {} 91 108 92 109 /* Define our own new and delete. */ … … 115 132 * @throws std::bad_alloc 116 133 */ 117 RTCMTList(size_t cCapacity = BASE:: DefaultCapacity)118 : BASE(cCapacity) {}134 RTCMTList(size_t cCapacity = BASE::kDefaultCapacity) 135 : BASE(cCapacity) {} 119 136 120 137 /* Define our own new and delete. */ … … 143 160 * @throws std::bad_alloc 144 161 */ 145 RTCMTList(size_t cCapacity = BASE:: DefaultCapacity)146 : BASE(cCapacity) {}162 RTCMTList(size_t cCapacity = BASE::kDefaultCapacity) 163 : BASE(cCapacity) {} 147 164 148 165 /* Define our own new and delete. */ -
trunk/src/VBox/Runtime/testcase/tstIprtList.cpp
r37861 r45520 34 34 #include <iprt/rand.h> 35 35 #include <iprt/thread.h> 36 #include <iprt/time.h> 36 37 37 38 … … 166 167 L<T1, T2> testList; 167 168 168 const size_t defCap = L<T1, T2>:: DefaultCapacity;169 const size_t defCap = L<T1, T2>::kDefaultCapacity; 169 170 RTTESTI_CHECK(testList.isEmpty()); 170 171 RTTESTI_CHECK(testList.size() == 0); … … 376 377 RTTESTI_CHECK(testList5.capacity() == 0); 377 378 379 /* 380 * Negative testing. 381 */ 382 bool fMayPanic = RTAssertMayPanic(); 383 bool fQuiet = RTAssertAreQuiet(); 384 RTAssertSetMayPanic(false); 385 RTAssertSetQuiet(true); 386 387 L<T1, T2> testList6; 388 for (size_t i = 0; i < cTestItems; ++i) 389 testList6.insert(i, paTestData[i]); 390 RTTESTI_CHECK(testList6.size() == cTestItems); 391 392 /* Insertion beyond the end of the array ends up at the end. */ 393 size_t cBefore = testList6.size(); 394 testList6.insert(cBefore + 3, paTestData[0]); 395 RTTESTI_CHECK(testList6.size() == cBefore + 1); 396 RTTESTI_CHECK(testList6.at(cBefore) == paTestData[0]); 397 398 cBefore = testList6.size(); 399 L<T1, T2> testList7(testList6); 400 testList6.insert(testList6.size() + 42, testList7); 401 RTTESTI_CHECK(testList6.size() == cBefore + testList7.size()); 402 403 /* Inserting, appending or prepending a list to itself is not supported. */ 404 cBefore = testList6.size(); 405 testList6.insert(3, testList6); 406 RTTESTI_CHECK(testList6.size() == cBefore); 407 408 cBefore = testList6.size(); 409 testList6.append(testList6); 410 RTTESTI_CHECK(testList6.size() == cBefore); 411 412 cBefore = testList6.size(); 413 testList6.prepend(testList6); 414 RTTESTI_CHECK(testList6.size() == cBefore); 415 416 /* Replace does nothing if the index is bad. */ 417 cBefore = testList6.size(); 418 testList6.replace(cBefore, testList6[6]); 419 RTTESTI_CHECK(testList6.size() == cBefore); 420 421 cBefore = testList6.size(); 422 testList6.replace(cBefore + 64, testList6[6]); 423 RTTESTI_CHECK(testList6.size() == cBefore); 424 425 /* Indexing beyond the array returns the last element. */ 426 cBefore = testList6.size(); 427 RTTESTI_CHECK(testList6[cBefore] == testList6.last()); 428 RTTESTI_CHECK(testList6[cBefore + 42] == testList6.last()); 429 430 RTTESTI_CHECK(&testList6[cBefore] == &testList6[cBefore - 1]); 431 RTTESTI_CHECK(&testList6[cBefore + 42] == &testList6[cBefore - 1]); 432 433 /* removeAt does nothing if the index is bad. */ 434 cBefore = testList6.size(); 435 testList6.removeAt(cBefore); 436 RTTESTI_CHECK(testList6.size() == cBefore); 437 438 cBefore = testList6.size(); 439 testList6.removeAt(cBefore + 42); 440 RTTESTI_CHECK(testList6.size() == cBefore); 441 442 L<T1, T2> testListEmpty1; RTTESTI_CHECK(!testListEmpty1.size()); 443 testListEmpty1.removeFirst(); 444 RTTESTI_CHECK(!testListEmpty1.size()); 445 446 testListEmpty1.removeLast(); 447 RTTESTI_CHECK(!testListEmpty1.size()); 448 449 testListEmpty1.removeAt(128); 450 RTTESTI_CHECK(!testListEmpty1.size()); 451 452 /* removeRange interprets indexes beyond the end as the end of array (asserted). */ 453 testListEmpty1.removeRange(42, 128); 454 RTTESTI_CHECK(!testListEmpty1.size()); 455 456 cBefore = testList6.size(); 457 testList6.removeRange(cBefore, cBefore); 458 RTTESTI_CHECK(testList6.size() == cBefore); 459 460 cBefore = testList6.size(); 461 testList6.removeRange(cBefore + 12, cBefore + 128); 462 RTTESTI_CHECK(testList6.size() == cBefore); 463 464 /* If end is less or equal to the start, nothing is done. */ 465 testListEmpty1.removeRange(128, 0); 466 RTTESTI_CHECK(!testListEmpty1.size()); 467 468 cBefore = testList6.size(); 469 testList6.removeRange(cBefore, 0); 470 RTTESTI_CHECK(testList6.size() == cBefore); 471 472 cBefore = testList6.size(); 473 testList6.removeRange(0, 0); 474 RTTESTI_CHECK(testList6.size() == cBefore); 475 476 cBefore = testList6.size(); 477 testList6.removeRange(0, 0); 478 RTTESTI_CHECK(testList6.size() == cBefore); 479 480 RTAssertSetQuiet(fQuiet); 481 RTAssertSetMayPanic(fMayPanic); 378 482 } 379 483 380 484 /* define RTCList here to see what happens without MT support ;) 381 485 * (valgrind is the preferred tool to check). */ 382 #define MTTESTLISTTYPE RTCMTList383 #define MTTESTTYPE uint32_t384 #define MTTESTITEMS 1000486 #define MTTESTLISTTYPE RTCMTList 487 #define MTTESTTYPE uint32_t 488 #define MTTESTITEMS 1000 385 489 386 490 /** … … 390 494 * @param pvUser The provided user data. 391 495 */ 392 DECLCALLBACK(int) mttest1(RTTHREAD hSelf, void *pvUser)496 static DECLCALLBACK(int) MtTest1ThreadProc(RTTHREAD hSelf, void *pvUser) 393 497 { 394 498 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; … … 407 511 * @param pvUser The provided user data. 408 512 */ 409 DECLCALLBACK(int) mttest2(RTTHREAD hSelf, void *pvUser)513 static DECLCALLBACK(int) MtTest2ThreadProc(RTTHREAD hSelf, void *pvUser) 410 514 { 411 515 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; … … 424 528 * @param pvUser The provided user data. 425 529 */ 426 DECLCALLBACK(int) mttest3(RTTHREAD hSelf, void *pvUser)530 static DECLCALLBACK(int) MtTest3ThreadProc(RTTHREAD hSelf, void *pvUser) 427 531 { 428 532 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; … … 441 545 * @param pvUser The provided user data. 442 546 */ 443 DECLCALLBACK(int) mttest4(RTTHREAD hSelf, void *pvUser)547 static DECLCALLBACK(int) MtTest4ThreadProc(RTTHREAD hSelf, void *pvUser) 444 548 { 445 549 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; … … 450 554 { 451 555 /* Make sure there is at least one item in the list. */ 452 while (pTestList->isEmpty()) {}; 556 while (pTestList->isEmpty()) 557 RTThreadYield(); 453 558 a = pTestList->at(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1)); 454 559 } … … 463 568 * @param pvUser The provided user data. 464 569 */ 465 DECLCALLBACK(int) mttest5(RTTHREAD hSelf, void *pvUser)570 static DECLCALLBACK(int) MtTest5ThreadProc(RTTHREAD hSelf, void *pvUser) 466 571 { 467 572 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; … … 471 576 { 472 577 /* Make sure there is at least one item in the list. */ 473 while (pTestList->isEmpty()) {}; 578 while (pTestList->isEmpty()) 579 RTThreadYield(); 474 580 pTestList->replace(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1), 0xFF00FF00); 475 581 } … … 484 590 * @param pvUser The provided user data. 485 591 */ 486 DECLCALLBACK(int) mttest6(RTTHREAD hSelf, void *pvUser)592 static DECLCALLBACK(int) MtTest6ThreadProc(RTTHREAD hSelf, void *pvUser) 487 593 { 488 594 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; … … 492 598 { 493 599 /* Make sure there is at least one item in the list. */ 494 while (pTestList->isEmpty()) {}; 600 while (pTestList->isEmpty()) 601 RTThreadYield(); 495 602 pTestList->removeAt(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1)); 496 603 } … … 508 615 RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS); 509 616 510 RTTHREAD hThread1, hThread2, hThread3, hThread4, hThread5, hThread6; 511 int rc = VINF_SUCCESS; 512 513 MTTESTLISTTYPE<MTTESTTYPE> testList; 514 rc = RTThreadCreate(&hThread1, &mttest1, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest1"); 515 AssertRC(rc); 516 rc = RTThreadCreate(&hThread2, &mttest2, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest2"); 517 AssertRC(rc); 518 rc = RTThreadCreate(&hThread3, &mttest3, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest3"); 519 AssertRC(rc); 520 rc = RTThreadCreate(&hThread4, &mttest4, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest4"); 521 AssertRC(rc); 522 rc = RTThreadCreate(&hThread5, &mttest5, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest5"); 523 AssertRC(rc); 524 rc = RTThreadCreate(&hThread6, &mttest6, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest6"); 525 AssertRC(rc); 526 527 rc = RTThreadWait(hThread1, RT_INDEFINITE_WAIT, 0); 528 AssertRC(rc); 529 rc = RTThreadWait(hThread2, RT_INDEFINITE_WAIT, 0); 530 AssertRC(rc); 531 rc = RTThreadWait(hThread3, RT_INDEFINITE_WAIT, 0); 532 AssertRC(rc); 533 rc = RTThreadWait(hThread4, RT_INDEFINITE_WAIT, 0); 534 AssertRC(rc); 535 rc = RTThreadWait(hThread5, RT_INDEFINITE_WAIT, 0); 536 AssertRC(rc); 537 rc = RTThreadWait(hThread6, RT_INDEFINITE_WAIT, 0); 538 AssertRC(rc); 617 int rc; 618 MTTESTLISTTYPE<MTTESTTYPE> testList; 619 RTTHREAD ahThreads[6]; 620 static PFNRTTHREAD apfnThreads[6] = 621 { 622 MtTest1ThreadProc, MtTest2ThreadProc, MtTest3ThreadProc, MtTest4ThreadProc, MtTest5ThreadProc, MtTest6ThreadProc 623 }; 624 625 for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) 626 { 627 RTTESTI_CHECK_RC_RETV(RTThreadCreateF(&ahThreads[i], apfnThreads[i], &testList, 0, 628 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest%u", i), VINF_SUCCESS); 629 } 630 631 uint64_t tsMsDeadline = RTTimeMilliTS() + 60000; 632 for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) 633 { 634 uint64_t tsNow = RTTimeMilliTS(); 635 uint32_t cWait = tsNow > tsMsDeadline ? 5000 : tsMsDeadline - tsNow; 636 RTTESTI_CHECK_RC(RTThreadWait(ahThreads[i], tsNow, NULL), VINF_SUCCESS); 637 } 539 638 540 639 RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2); … … 557 656 RTTestBanner(hTest); 558 657 559 /* Some host info. */560 RTTestIPrintf(RTTESTLVL_ALWAYS, "sizeof(void*)=%d", sizeof(void*));561 562 /*563 * The tests.564 */565 566 658 /* 567 659 * Native types.
Note:
See TracChangeset
for help on using the changeset viewer.