1 /* 2 * Copyright (c) 2019, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for a generic singly linked list. 32 */ 33 34 #ifndef LINKED_LIST_HPP_ 35 #define LINKED_LIST_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <stdio.h> 40 41 #include "common/const_cast.hpp" 42 #include "common/error.hpp" 43 #include "common/iterator_utils.hpp" 44 45 namespace ot { 46 47 /** 48 * @addtogroup core-linked-list 49 * 50 * @brief 51 * This module includes definitions for OpenThread Singly Linked List. 52 * 53 * @{ 54 * 55 */ 56 57 /** 58 * This template class represents a linked list entry. 59 * 60 * This class provides methods to `GetNext()` and `SetNext()` in the linked list entry. 61 * 62 * Users of this class should follow CRTP-style inheritance, i.e., the `Type` class itself should publicly inherit 63 * from `LinkedListEntry<Type>`. 64 * 65 * The template type `Type` should contain a `mNext` member variable. The `mNext` should be of a type that can be 66 * down-casted to `Type` itself. 67 * 68 */ 69 template <class Type> class LinkedListEntry 70 { 71 public: 72 /** 73 * This method gets the next entry in the linked list. 74 * 75 * @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list. 76 * 77 */ GetNext(void) const78 const Type *GetNext(void) const { return static_cast<const Type *>(static_cast<const Type *>(this)->mNext); } 79 80 /** 81 * This method gets the next entry in the linked list. 82 * 83 * @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list. 84 * 85 */ GetNext(void)86 Type *GetNext(void) { return static_cast<Type *>(static_cast<Type *>(this)->mNext); } 87 88 /** 89 * This method sets the next pointer on the entry. 90 * 91 * @param[in] aNext A pointer to the next entry. 92 * 93 */ SetNext(Type * aNext)94 void SetNext(Type *aNext) { static_cast<Type *>(this)->mNext = aNext; } 95 }; 96 97 /** 98 * This template class represents a singly linked list. 99 * 100 * The template type `Type` should provide `GetNext()` and `SetNext()` methods (which can be realized by `Type` 101 * inheriting from `LinkedListEntry<Type>` class). 102 * 103 */ 104 template <typename Type> class LinkedList 105 { 106 class Iterator; 107 class ConstIterator; 108 109 public: 110 /** 111 * This constructor initializes the linked list. 112 * 113 */ LinkedList(void)114 LinkedList(void) 115 : mHead(nullptr) 116 { 117 } 118 119 /** 120 * This method returns the entry at the head of the linked list 121 * 122 * @returns Pointer to the entry at the head of the linked list, or `nullptr` if the list is empty. 123 * 124 */ GetHead(void)125 Type *GetHead(void) { return mHead; } 126 127 /** 128 * This method returns the entry at the head of the linked list. 129 * 130 * @returns Pointer to the entry at the head of the linked list, or `nullptr` if the list is empty. 131 * 132 */ GetHead(void) const133 const Type *GetHead(void) const { return mHead; } 134 135 /** 136 * This method sets the head of the linked list to a given entry. 137 * 138 * @param[in] aHead A pointer to an entry to set as the head of the linked list. 139 * 140 */ SetHead(Type * aHead)141 void SetHead(Type *aHead) { mHead = aHead; } 142 143 /** 144 * This method clears the linked list. 145 * 146 */ Clear(void)147 void Clear(void) { mHead = nullptr; } 148 149 /** 150 * This method indicates whether the linked list is empty or not. 151 * 152 * @retval TRUE If the linked list is empty. 153 * @retval FALSE If the linked list is not empty. 154 * 155 */ IsEmpty(void) const156 bool IsEmpty(void) const { return (mHead == nullptr); } 157 158 /** 159 * This method pushes an entry at the head of the linked list. 160 * 161 * @param[in] aEntry A reference to an entry to push at the head of linked list. 162 * 163 */ Push(Type & aEntry)164 void Push(Type &aEntry) 165 { 166 aEntry.SetNext(mHead); 167 mHead = &aEntry; 168 } 169 170 /** 171 * This method pushes an entry after a given previous existing entry in the linked list. 172 * 173 * @param[in] aEntry A reference to an entry to push into the list. 174 * @param[in] aPrevEntry A reference to a previous entry (new entry @p aEntry will be pushed after this). 175 * 176 */ PushAfter(Type & aEntry,Type & aPrevEntry)177 void PushAfter(Type &aEntry, Type &aPrevEntry) 178 { 179 aEntry.SetNext(aPrevEntry.GetNext()); 180 aPrevEntry.SetNext(&aEntry); 181 } 182 183 /** 184 * This method pops an entry from head of the linked list. 185 * 186 * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before. 187 * 188 * @returns The entry that was popped if the list is not empty, or `nullptr` if the list is empty. 189 * 190 */ Pop(void)191 Type *Pop(void) 192 { 193 Type *entry = mHead; 194 195 if (mHead != nullptr) 196 { 197 mHead = mHead->GetNext(); 198 } 199 200 return entry; 201 } 202 203 /** 204 * This method pops an entry after a given previous entry. 205 * 206 * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before. 207 * 208 * @param[in] aPrevEntry A pointer to a previous entry. If it is not `nullptr` the entry after this will be popped, 209 * otherwise (if it is `nullptr`) the entry at the head of the list is popped. 210 * 211 * @returns Pointer to the entry that was popped, or `nullptr` if there is no entry to pop. 212 * 213 */ PopAfter(Type * aPrevEntry)214 Type *PopAfter(Type *aPrevEntry) 215 { 216 Type *entry; 217 218 if (aPrevEntry == nullptr) 219 { 220 entry = Pop(); 221 } 222 else 223 { 224 entry = aPrevEntry->GetNext(); 225 226 if (entry != nullptr) 227 { 228 aPrevEntry->SetNext(entry->GetNext()); 229 } 230 } 231 232 return entry; 233 } 234 235 /** 236 * This method indicates whether the linked list contains a given entry. 237 * 238 * @param[in] aEntry A reference to an entry. 239 * 240 * @retval TRUE The linked list contains @p aEntry. 241 * @retval FALSE The linked list does not contain @p aEntry. 242 * 243 */ Contains(const Type & aEntry) const244 bool Contains(const Type &aEntry) const 245 { 246 const Type *prev; 247 248 return Find(aEntry, prev) == kErrorNone; 249 } 250 251 /** 252 * This template method indicates whether the linked list contains an entry matching a given entry indicator. 253 * 254 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 255 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 256 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 257 * 258 * bool Type::Matches(const Indicator &aIndicator) const 259 * 260 * @param[in] aIndicator An entry indicator to match against entries in the list. 261 * 262 * @retval TRUE The linked list contains an entry matching @p aIndicator. 263 * @retval FALSE The linked list contains no entry matching @p aIndicator. 264 * 265 */ ContainsMatching(const Indicator & aIndicator) const266 template <typename Indicator> bool ContainsMatching(const Indicator &aIndicator) const 267 { 268 return FindMatching(aIndicator) != nullptr; 269 } 270 271 /** 272 * This method adds an entry (at the head of the linked list) if it is not already in the list. 273 * 274 * @param[in] aEntry A reference to an entry to add. 275 * 276 * @retval kErrorNone The entry was successfully added at the head of the list. 277 * @retval kErrorAlready The entry is already in the list. 278 * 279 */ Add(Type & aEntry)280 Error Add(Type &aEntry) 281 { 282 Error error = kErrorNone; 283 284 if (Contains(aEntry)) 285 { 286 error = kErrorAlready; 287 } 288 else 289 { 290 Push(aEntry); 291 } 292 293 return error; 294 } 295 296 /** 297 * This method removes an entry from the linked list. 298 * 299 * @note This method does not change the removed entry @p aEntry itself (it is `const`), i.e., the entry next 300 * pointer of @p aEntry stays as before. 301 * 302 * @param[in] aEntry A reference to an entry to remove. 303 * 304 * @retval kErrorNone The entry was successfully removed from the list. 305 * @retval kErrorNotFound Could not find the entry in the list. 306 * 307 */ Remove(const Type & aEntry)308 Error Remove(const Type &aEntry) 309 { 310 Type *prev; 311 Error error = Find(aEntry, prev); 312 313 if (error == kErrorNone) 314 { 315 PopAfter(prev); 316 } 317 318 return error; 319 } 320 321 /** 322 * This template method removes an entry matching a given entry indicator from the linked list. 323 * 324 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 325 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 326 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 327 * 328 * bool Type::Matches(const Indicator &aIndicator) const 329 * 330 * @note This method does not change the removed entry itself (which is returned in case of success), i.e., the 331 * entry next pointer stays as before. 332 * 333 * 334 * @param[in] aIndicator An entry indicator to match against entries in the list. 335 * 336 * @returns A pointer to the removed matching entry if one could be found, or `nullptr` if no matching entry is 337 * found. 338 * 339 */ RemoveMatching(const Indicator & aIndicator)340 template <typename Indicator> Type *RemoveMatching(const Indicator &aIndicator) 341 { 342 Type *prev; 343 Type *entry = FindMatching(aIndicator, prev); 344 345 if (entry != nullptr) 346 { 347 PopAfter(prev); 348 } 349 350 return entry; 351 } 352 353 /** 354 * This template method removes all entries in the list matching a given entry indicator from the list and adds 355 * them to a new list. 356 * 357 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 358 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 359 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 360 * 361 * bool Type::Matches(const Indicator &aIndicator) const 362 * 363 * @param[in] aIndicator An entry indicator to match against entries in the list. 364 * @param[in] aRemovedList The list to add the removed entries to. 365 * 366 */ RemoveAllMatching(const Indicator & aIndicator,LinkedList & aRemovedList)367 template <typename Indicator> void RemoveAllMatching(const Indicator &aIndicator, LinkedList &aRemovedList) 368 { 369 Type *entry; 370 Type *prev; 371 Type *next; 372 373 for (prev = nullptr, entry = GetHead(); entry != nullptr; entry = next) 374 { 375 next = entry->GetNext(); 376 377 if (entry->Matches(aIndicator)) 378 { 379 PopAfter(prev); 380 aRemovedList.Push(*entry); 381 382 // When the entry is removed from the list 383 // we keep the `prev` pointer same as before. 384 } 385 else 386 { 387 prev = entry; 388 } 389 } 390 } 391 392 /** 393 * This method searches within the linked list to find an entry and if found returns a pointer to previous entry. 394 * 395 * @param[in] aEntry A reference to an entry to find. 396 * @param[out] aPrevEntry A pointer to output the previous entry on success (when @p aEntry is found in the list). 397 * @p aPrevEntry is set to `nullptr` if @p aEntry is the head of the list. Otherwise it is 398 * updated to point to the previous entry before @p aEntry in the list. 399 * 400 * @retval kErrorNone The entry was found in the list and @p aPrevEntry was updated successfully. 401 * @retval kErrorNotFound The entry was not found in the list. 402 * 403 */ Find(const Type & aEntry,const Type * & aPrevEntry) const404 Error Find(const Type &aEntry, const Type *&aPrevEntry) const 405 { 406 Error error = kErrorNotFound; 407 408 aPrevEntry = nullptr; 409 410 for (const Type *entry = mHead; entry != nullptr; aPrevEntry = entry, entry = entry->GetNext()) 411 { 412 if (entry == &aEntry) 413 { 414 error = kErrorNone; 415 break; 416 } 417 } 418 419 return error; 420 } 421 422 /** 423 * This method searches within the linked list to find an entry and if found returns a pointer to previous entry. 424 * 425 * @param[in] aEntry A reference to an entry to find. 426 * @param[out] aPrevEntry A pointer to output the previous entry on success (when @p aEntry is found in the list). 427 * @p aPrevEntry is set to `nullptr` if @p aEntry is the head of the list. Otherwise it is 428 * updated to point to the previous entry before @p aEntry in the list. 429 * 430 * @retval kErrorNone The entry was found in the list and @p aPrevEntry was updated successfully. 431 * @retval kErrorNotFound The entry was not found in the list. 432 * 433 */ Find(const Type & aEntry,Type * & aPrevEntry)434 Error Find(const Type &aEntry, Type *&aPrevEntry) 435 { 436 return AsConst(this)->Find(aEntry, const_cast<const Type *&>(aPrevEntry)); 437 } 438 439 /** 440 * This template method searches within a given range of the linked list to find an entry matching a given 441 * indicator. 442 * 443 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 444 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 445 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 446 * 447 * bool Type::Matches(const Indicator &aIndicator) const 448 * 449 * @param[in] aBegin A pointer to the begin of the range. 450 * @param[in] aEnd A pointer to the end of the range, or `nullptr` to search all entries after @p aBegin. 451 * @param[in] aIndicator An indicator to match with entries in the list. 452 * @param[out] aPrevEntry A pointer to output the previous entry on success (when a match is found in the list). 453 * @p aPrevEntry is set to `nullptr` if the matching entry is the head of the list. 454 * Otherwise it is updated to point to the previous entry before the matching entry in the 455 * list. 456 * 457 * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found. 458 * 459 */ 460 template <typename Indicator> FindMatching(const Type * aBegin,const Type * aEnd,const Indicator & aIndicator,const Type * & aPrevEntry) const461 const Type *FindMatching(const Type *aBegin, 462 const Type *aEnd, 463 const Indicator &aIndicator, 464 const Type *&aPrevEntry) const 465 { 466 const Type *entry; 467 468 aPrevEntry = nullptr; 469 470 for (entry = aBegin; entry != aEnd; aPrevEntry = entry, entry = entry->GetNext()) 471 { 472 if (entry->Matches(aIndicator)) 473 { 474 break; 475 } 476 } 477 478 return entry; 479 } 480 481 /** 482 * This template method searches within a given range of the linked list to find an entry matching a given 483 * indicator. 484 * 485 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 486 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 487 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 488 * 489 * bool Type::Matches(const Indicator &aIndicator) const 490 * 491 * @param[in] aBegin A pointer to the begin of the range. 492 * @param[in] aEnd A pointer to the end of the range, or `nullptr` to search all entries after @p aBegin. 493 * @param[in] aIndicator An indicator to match with entries in the list. 494 * @param[out] aPrevEntry A pointer to output the previous entry on success (when a match is found in the list). 495 * @p aPrevEntry is set to `nullptr` if the matching entry is the head of the list. 496 * Otherwise it is updated to point to the previous entry before the matching entry in the 497 * list. 498 * 499 * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found. 500 * 501 */ 502 template <typename Indicator> FindMatching(const Type * aBegin,const Type * aEnd,const Indicator & aIndicator,Type * & aPrevEntry)503 Type *FindMatching(const Type *aBegin, const Type *aEnd, const Indicator &aIndicator, Type *&aPrevEntry) 504 { 505 return AsNonConst(FindMatching(aBegin, aEnd, aIndicator, const_cast<const Type *&>(aPrevEntry))); 506 } 507 508 /** 509 * This template method searches within the linked list to find an entry matching a given indicator. 510 * 511 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 512 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 513 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 514 * 515 * bool Type::Matches(const Indicator &aIndicator) const 516 * 517 * @param[in] aIndicator An indicator to match with entries in the list. 518 * @param[out] aPrevEntry A pointer to output the previous entry on success (when a match is found in the list). 519 * @p aPrevEntry is set to `nullptr` if the matching entry is the head of the list. 520 * Otherwise it is updated to point to the previous entry before the matching entry in the 521 * list. 522 * 523 * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found. 524 * 525 */ FindMatching(const Indicator & aIndicator,const Type * & aPrevEntry) const526 template <typename Indicator> const Type *FindMatching(const Indicator &aIndicator, const Type *&aPrevEntry) const 527 { 528 return FindMatching(mHead, nullptr, aIndicator, aPrevEntry); 529 } 530 531 /** 532 * This template method searches within the linked list to find an entry matching a given indicator, and if found 533 * returns a pointer to its previous entry in the list. 534 * 535 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 536 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 537 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 538 * 539 * bool Type::Matches(const Indicator &aIndicator) const 540 * 541 * @param[in] aIndicator An indicator to match with entries in the list. 542 * @param[out] aPrevEntry A pointer to output the previous entry on success (when a match is found in the list). 543 * @p aPrevEntry is set to `nullptr` if the matching entry is the head of the list. 544 * Otherwise it is updated to point to the previous entry before the matching entry in the 545 * list. 546 * 547 * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found. 548 * 549 */ FindMatching(const Indicator & aIndicator,Type * & aPrevEntry)550 template <typename Indicator> Type *FindMatching(const Indicator &aIndicator, Type *&aPrevEntry) 551 { 552 return AsNonConst(AsConst(this)->FindMatching(aIndicator, const_cast<const Type *&>(aPrevEntry))); 553 } 554 555 /** 556 * This template method searches within the linked list to find an entry matching a given indicator. 557 * 558 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 559 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 560 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 561 * 562 * bool Type::Matches(const Indicator &aIndicator) const 563 * 564 * @param[in] aIndicator An indicator to match with entries in the list. 565 * 566 * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found. 567 * 568 */ FindMatching(const Indicator & aIndicator) const569 template <typename Indicator> const Type *FindMatching(const Indicator &aIndicator) const 570 { 571 const Type *prev; 572 573 return FindMatching(aIndicator, prev); 574 } 575 576 /** 577 * This template method searches within the linked list to find an entry matching a given indicator. 578 * 579 * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries 580 * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each 581 * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly: 582 * 583 * bool Type::Matches(const Indicator &aIndicator) const 584 * 585 * @param[in] aIndicator An indicator to match with entries in the list. 586 * 587 * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found. 588 * 589 */ FindMatching(const Indicator & aIndicator)590 template <typename Indicator> Type *FindMatching(const Indicator &aIndicator) 591 { 592 return AsNonConst(AsConst(this)->FindMatching(aIndicator)); 593 } 594 595 /** 596 * This method returns the tail of the linked list (i.e., the last entry in the list). 597 * 598 * @returns A pointer to the tail entry in the linked list or `nullptr` if the list is empty. 599 * 600 */ GetTail(void) const601 const Type *GetTail(void) const 602 { 603 const Type *tail = mHead; 604 605 if (tail != nullptr) 606 { 607 while (tail->GetNext() != nullptr) 608 { 609 tail = tail->GetNext(); 610 } 611 } 612 613 return tail; 614 } 615 616 /** 617 * This method returns the tail of the linked list (i.e., the last entry in the list). 618 * 619 * @returns A pointer to the tail entry in the linked list or `nullptr` if the list is empty. 620 * 621 */ GetTail(void)622 Type *GetTail(void) { return AsNonConst(AsConst(this)->GetTail()); } 623 624 // The following methods are intended to support range-based `for` 625 // loop iteration over the linked-list entries and should not be 626 // used directly. 627 begin(void)628 Iterator begin(void) { return Iterator(GetHead()); } end(void)629 Iterator end(void) { return Iterator(nullptr); } 630 begin(void) const631 ConstIterator begin(void) const { return ConstIterator(GetHead()); } end(void) const632 ConstIterator end(void) const { return ConstIterator(nullptr); } 633 634 private: 635 class Iterator : public ItemPtrIterator<Type, Iterator> 636 { 637 friend class LinkedList; 638 friend class ItemPtrIterator<Type, Iterator>; 639 640 using ItemPtrIterator<Type, Iterator>::mItem; 641 Iterator(Type * aItem)642 explicit Iterator(Type *aItem) 643 : ItemPtrIterator<Type, Iterator>(aItem) 644 { 645 } 646 Advance(void)647 void Advance(void) { mItem = mItem->GetNext(); } 648 }; 649 650 class ConstIterator : public ItemPtrIterator<const Type, ConstIterator> 651 { 652 friend class LinkedList; 653 friend class ItemPtrIterator<const Type, ConstIterator>; 654 655 using ItemPtrIterator<const Type, ConstIterator>::mItem; 656 ConstIterator(const Type * aItem)657 explicit ConstIterator(const Type *aItem) 658 : ItemPtrIterator<const Type, ConstIterator>(aItem) 659 { 660 } 661 Advance(void)662 void Advance(void) { mItem = mItem->GetNext(); } 663 }; 664 665 Type *mHead; 666 }; 667 668 /** 669 * @} 670 * 671 */ 672 673 } // namespace ot 674 675 #endif // LINKED_LIST_HPP_ 676