1*8d67ca89SAndroid Build Coastguard Worker /* 2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*8d67ca89SAndroid Build Coastguard Worker * All rights reserved. 4*8d67ca89SAndroid Build Coastguard Worker * 5*8d67ca89SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without 6*8d67ca89SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions 7*8d67ca89SAndroid Build Coastguard Worker * are met: 8*8d67ca89SAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright 9*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer. 10*8d67ca89SAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright 11*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in 12*8d67ca89SAndroid Build Coastguard Worker * the documentation and/or other materials provided with the 13*8d67ca89SAndroid Build Coastguard Worker * distribution. 14*8d67ca89SAndroid Build Coastguard Worker * 15*8d67ca89SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16*8d67ca89SAndroid Build Coastguard Worker * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17*8d67ca89SAndroid Build Coastguard Worker * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18*8d67ca89SAndroid Build Coastguard Worker * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19*8d67ca89SAndroid Build Coastguard Worker * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20*8d67ca89SAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21*8d67ca89SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22*8d67ca89SAndroid Build Coastguard Worker * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23*8d67ca89SAndroid Build Coastguard Worker * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24*8d67ca89SAndroid Build Coastguard Worker * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25*8d67ca89SAndroid Build Coastguard Worker * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*8d67ca89SAndroid Build Coastguard Worker * SUCH DAMAGE. 27*8d67ca89SAndroid Build Coastguard Worker */ 28*8d67ca89SAndroid Build Coastguard Worker 29*8d67ca89SAndroid Build Coastguard Worker #pragma once 30*8d67ca89SAndroid Build Coastguard Worker 31*8d67ca89SAndroid Build Coastguard Worker #include <android-base/macros.h> 32*8d67ca89SAndroid Build Coastguard Worker 33*8d67ca89SAndroid Build Coastguard Worker template<typename T> 34*8d67ca89SAndroid Build Coastguard Worker struct LinkedListEntry { 35*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* next; 36*8d67ca89SAndroid Build Coastguard Worker T* element; 37*8d67ca89SAndroid Build Coastguard Worker }; 38*8d67ca89SAndroid Build Coastguard Worker 39*8d67ca89SAndroid Build Coastguard Worker // ForwardInputIterator 40*8d67ca89SAndroid Build Coastguard Worker template<typename T> 41*8d67ca89SAndroid Build Coastguard Worker class LinkedListIterator { 42*8d67ca89SAndroid Build Coastguard Worker public: LinkedListIterator()43*8d67ca89SAndroid Build Coastguard Worker LinkedListIterator() : entry_(nullptr) {} LinkedListIterator(const LinkedListIterator<T> & that)44*8d67ca89SAndroid Build Coastguard Worker LinkedListIterator(const LinkedListIterator<T>& that) : entry_(that.entry_) {} LinkedListIterator(LinkedListEntry<T> * entry)45*8d67ca89SAndroid Build Coastguard Worker explicit LinkedListIterator(LinkedListEntry<T>* entry) : entry_(entry) {} 46*8d67ca89SAndroid Build Coastguard Worker 47*8d67ca89SAndroid Build Coastguard Worker LinkedListIterator<T>& operator=(const LinkedListIterator<T>& that) { 48*8d67ca89SAndroid Build Coastguard Worker entry_ = that.entry_; 49*8d67ca89SAndroid Build Coastguard Worker return *this; 50*8d67ca89SAndroid Build Coastguard Worker } 51*8d67ca89SAndroid Build Coastguard Worker 52*8d67ca89SAndroid Build Coastguard Worker LinkedListIterator<T>& operator++() { 53*8d67ca89SAndroid Build Coastguard Worker entry_ = entry_->next; 54*8d67ca89SAndroid Build Coastguard Worker return *this; 55*8d67ca89SAndroid Build Coastguard Worker } 56*8d67ca89SAndroid Build Coastguard Worker 57*8d67ca89SAndroid Build Coastguard Worker T* const operator*() { 58*8d67ca89SAndroid Build Coastguard Worker return entry_->element; 59*8d67ca89SAndroid Build Coastguard Worker } 60*8d67ca89SAndroid Build Coastguard Worker 61*8d67ca89SAndroid Build Coastguard Worker bool operator==(const LinkedListIterator<T>& that) const { 62*8d67ca89SAndroid Build Coastguard Worker return entry_ == that.entry_; 63*8d67ca89SAndroid Build Coastguard Worker } 64*8d67ca89SAndroid Build Coastguard Worker 65*8d67ca89SAndroid Build Coastguard Worker bool operator!=(const LinkedListIterator<T>& that) const { 66*8d67ca89SAndroid Build Coastguard Worker return entry_ != that.entry_; 67*8d67ca89SAndroid Build Coastguard Worker } 68*8d67ca89SAndroid Build Coastguard Worker 69*8d67ca89SAndroid Build Coastguard Worker private: 70*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T> *entry_; 71*8d67ca89SAndroid Build Coastguard Worker }; 72*8d67ca89SAndroid Build Coastguard Worker 73*8d67ca89SAndroid Build Coastguard Worker /* 74*8d67ca89SAndroid Build Coastguard Worker * Represents linked list of objects of type T 75*8d67ca89SAndroid Build Coastguard Worker */ 76*8d67ca89SAndroid Build Coastguard Worker template<typename T, typename Allocator> 77*8d67ca89SAndroid Build Coastguard Worker class LinkedList { 78*8d67ca89SAndroid Build Coastguard Worker public: 79*8d67ca89SAndroid Build Coastguard Worker typedef LinkedListIterator<T> iterator; 80*8d67ca89SAndroid Build Coastguard Worker typedef T* value_type; 81*8d67ca89SAndroid Build Coastguard Worker 82*8d67ca89SAndroid Build Coastguard Worker // Allocating the head/tail fields separately from the LinkedList struct saves memory in the 83*8d67ca89SAndroid Build Coastguard Worker // Zygote (e.g. because adding an soinfo to a namespace doesn't dirty the page containing the 84*8d67ca89SAndroid Build Coastguard Worker // soinfo). 85*8d67ca89SAndroid Build Coastguard Worker struct LinkedListHeader { 86*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* head; 87*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* tail; 88*8d67ca89SAndroid Build Coastguard Worker }; 89*8d67ca89SAndroid Build Coastguard Worker 90*8d67ca89SAndroid Build Coastguard Worker // The allocator returns a LinkedListEntry<T>* but we want to treat it as a LinkedListHeader 91*8d67ca89SAndroid Build Coastguard Worker // struct instead. 92*8d67ca89SAndroid Build Coastguard Worker static_assert(sizeof(LinkedListHeader) == sizeof(LinkedListEntry<T>)); 93*8d67ca89SAndroid Build Coastguard Worker static_assert(alignof(LinkedListHeader) == alignof(LinkedListEntry<T>)); 94*8d67ca89SAndroid Build Coastguard Worker LinkedList()95*8d67ca89SAndroid Build Coastguard Worker constexpr LinkedList() : header_(nullptr) {} ~LinkedList()96*8d67ca89SAndroid Build Coastguard Worker ~LinkedList() { 97*8d67ca89SAndroid Build Coastguard Worker clear(); 98*8d67ca89SAndroid Build Coastguard Worker if (header_ != nullptr) { 99*8d67ca89SAndroid Build Coastguard Worker Allocator::free(reinterpret_cast<LinkedListEntry<T>*>(header_)); 100*8d67ca89SAndroid Build Coastguard Worker } 101*8d67ca89SAndroid Build Coastguard Worker } 102*8d67ca89SAndroid Build Coastguard Worker LinkedList(LinkedList && that)103*8d67ca89SAndroid Build Coastguard Worker LinkedList(LinkedList&& that) noexcept { 104*8d67ca89SAndroid Build Coastguard Worker this->header_ = that.header_; 105*8d67ca89SAndroid Build Coastguard Worker that.header_ = nullptr; 106*8d67ca89SAndroid Build Coastguard Worker } 107*8d67ca89SAndroid Build Coastguard Worker empty()108*8d67ca89SAndroid Build Coastguard Worker bool empty() const { 109*8d67ca89SAndroid Build Coastguard Worker return header_ == nullptr || header_->head == nullptr; 110*8d67ca89SAndroid Build Coastguard Worker } 111*8d67ca89SAndroid Build Coastguard Worker push_front(T * const element)112*8d67ca89SAndroid Build Coastguard Worker void push_front(T* const element) { 113*8d67ca89SAndroid Build Coastguard Worker alloc_header(); 114*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* new_entry = Allocator::alloc(); 115*8d67ca89SAndroid Build Coastguard Worker new_entry->next = header_->head; 116*8d67ca89SAndroid Build Coastguard Worker new_entry->element = element; 117*8d67ca89SAndroid Build Coastguard Worker header_->head = new_entry; 118*8d67ca89SAndroid Build Coastguard Worker if (header_->tail == nullptr) { 119*8d67ca89SAndroid Build Coastguard Worker header_->tail = new_entry; 120*8d67ca89SAndroid Build Coastguard Worker } 121*8d67ca89SAndroid Build Coastguard Worker } 122*8d67ca89SAndroid Build Coastguard Worker push_back(T * const element)123*8d67ca89SAndroid Build Coastguard Worker void push_back(T* const element) { 124*8d67ca89SAndroid Build Coastguard Worker alloc_header(); 125*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* new_entry = Allocator::alloc(); 126*8d67ca89SAndroid Build Coastguard Worker new_entry->next = nullptr; 127*8d67ca89SAndroid Build Coastguard Worker new_entry->element = element; 128*8d67ca89SAndroid Build Coastguard Worker if (header_->tail == nullptr) { 129*8d67ca89SAndroid Build Coastguard Worker header_->tail = header_->head = new_entry; 130*8d67ca89SAndroid Build Coastguard Worker } else { 131*8d67ca89SAndroid Build Coastguard Worker header_->tail->next = new_entry; 132*8d67ca89SAndroid Build Coastguard Worker header_->tail = new_entry; 133*8d67ca89SAndroid Build Coastguard Worker } 134*8d67ca89SAndroid Build Coastguard Worker } 135*8d67ca89SAndroid Build Coastguard Worker pop_front()136*8d67ca89SAndroid Build Coastguard Worker T* pop_front() { 137*8d67ca89SAndroid Build Coastguard Worker if (empty()) return nullptr; 138*8d67ca89SAndroid Build Coastguard Worker 139*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* entry = header_->head; 140*8d67ca89SAndroid Build Coastguard Worker T* element = entry->element; 141*8d67ca89SAndroid Build Coastguard Worker header_->head = entry->next; 142*8d67ca89SAndroid Build Coastguard Worker Allocator::free(entry); 143*8d67ca89SAndroid Build Coastguard Worker 144*8d67ca89SAndroid Build Coastguard Worker if (header_->head == nullptr) { 145*8d67ca89SAndroid Build Coastguard Worker header_->tail = nullptr; 146*8d67ca89SAndroid Build Coastguard Worker } 147*8d67ca89SAndroid Build Coastguard Worker 148*8d67ca89SAndroid Build Coastguard Worker return element; 149*8d67ca89SAndroid Build Coastguard Worker } 150*8d67ca89SAndroid Build Coastguard Worker front()151*8d67ca89SAndroid Build Coastguard Worker T* front() const { 152*8d67ca89SAndroid Build Coastguard Worker return empty() ? nullptr : header_->head->element; 153*8d67ca89SAndroid Build Coastguard Worker } 154*8d67ca89SAndroid Build Coastguard Worker clear()155*8d67ca89SAndroid Build Coastguard Worker void clear() { 156*8d67ca89SAndroid Build Coastguard Worker if (empty()) return; 157*8d67ca89SAndroid Build Coastguard Worker 158*8d67ca89SAndroid Build Coastguard Worker while (header_->head != nullptr) { 159*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* p = header_->head; 160*8d67ca89SAndroid Build Coastguard Worker header_->head = header_->head->next; 161*8d67ca89SAndroid Build Coastguard Worker Allocator::free(p); 162*8d67ca89SAndroid Build Coastguard Worker } 163*8d67ca89SAndroid Build Coastguard Worker 164*8d67ca89SAndroid Build Coastguard Worker header_->tail = nullptr; 165*8d67ca89SAndroid Build Coastguard Worker } 166*8d67ca89SAndroid Build Coastguard Worker 167*8d67ca89SAndroid Build Coastguard Worker template<typename F> for_each(F action)168*8d67ca89SAndroid Build Coastguard Worker void for_each(F action) const { 169*8d67ca89SAndroid Build Coastguard Worker visit([&] (T* si) { 170*8d67ca89SAndroid Build Coastguard Worker action(si); 171*8d67ca89SAndroid Build Coastguard Worker return true; 172*8d67ca89SAndroid Build Coastguard Worker }); 173*8d67ca89SAndroid Build Coastguard Worker } 174*8d67ca89SAndroid Build Coastguard Worker 175*8d67ca89SAndroid Build Coastguard Worker template<typename F> visit(F action)176*8d67ca89SAndroid Build Coastguard Worker bool visit(F action) const { 177*8d67ca89SAndroid Build Coastguard Worker for (LinkedListEntry<T>* e = head(); e != nullptr; e = e->next) { 178*8d67ca89SAndroid Build Coastguard Worker if (!action(e->element)) { 179*8d67ca89SAndroid Build Coastguard Worker return false; 180*8d67ca89SAndroid Build Coastguard Worker } 181*8d67ca89SAndroid Build Coastguard Worker } 182*8d67ca89SAndroid Build Coastguard Worker return true; 183*8d67ca89SAndroid Build Coastguard Worker } 184*8d67ca89SAndroid Build Coastguard Worker 185*8d67ca89SAndroid Build Coastguard Worker template<typename F> remove_if(F predicate)186*8d67ca89SAndroid Build Coastguard Worker void remove_if(F predicate) { 187*8d67ca89SAndroid Build Coastguard Worker if (empty()) return; 188*8d67ca89SAndroid Build Coastguard Worker for (LinkedListEntry<T>* e = header_->head, *p = nullptr; e != nullptr;) { 189*8d67ca89SAndroid Build Coastguard Worker if (predicate(e->element)) { 190*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* next = e->next; 191*8d67ca89SAndroid Build Coastguard Worker if (p == nullptr) { 192*8d67ca89SAndroid Build Coastguard Worker header_->head = next; 193*8d67ca89SAndroid Build Coastguard Worker } else { 194*8d67ca89SAndroid Build Coastguard Worker p->next = next; 195*8d67ca89SAndroid Build Coastguard Worker } 196*8d67ca89SAndroid Build Coastguard Worker 197*8d67ca89SAndroid Build Coastguard Worker if (header_->tail == e) { 198*8d67ca89SAndroid Build Coastguard Worker header_->tail = p; 199*8d67ca89SAndroid Build Coastguard Worker } 200*8d67ca89SAndroid Build Coastguard Worker 201*8d67ca89SAndroid Build Coastguard Worker Allocator::free(e); 202*8d67ca89SAndroid Build Coastguard Worker 203*8d67ca89SAndroid Build Coastguard Worker e = next; 204*8d67ca89SAndroid Build Coastguard Worker } else { 205*8d67ca89SAndroid Build Coastguard Worker p = e; 206*8d67ca89SAndroid Build Coastguard Worker e = e->next; 207*8d67ca89SAndroid Build Coastguard Worker } 208*8d67ca89SAndroid Build Coastguard Worker } 209*8d67ca89SAndroid Build Coastguard Worker } 210*8d67ca89SAndroid Build Coastguard Worker remove(T * element)211*8d67ca89SAndroid Build Coastguard Worker void remove(T* element) { 212*8d67ca89SAndroid Build Coastguard Worker remove_if([&](T* e) { 213*8d67ca89SAndroid Build Coastguard Worker return e == element; 214*8d67ca89SAndroid Build Coastguard Worker }); 215*8d67ca89SAndroid Build Coastguard Worker } 216*8d67ca89SAndroid Build Coastguard Worker 217*8d67ca89SAndroid Build Coastguard Worker template<typename F> find_if(F predicate)218*8d67ca89SAndroid Build Coastguard Worker T* find_if(F predicate) const { 219*8d67ca89SAndroid Build Coastguard Worker for (LinkedListEntry<T>* e = head(); e != nullptr; e = e->next) { 220*8d67ca89SAndroid Build Coastguard Worker if (predicate(e->element)) { 221*8d67ca89SAndroid Build Coastguard Worker return e->element; 222*8d67ca89SAndroid Build Coastguard Worker } 223*8d67ca89SAndroid Build Coastguard Worker } 224*8d67ca89SAndroid Build Coastguard Worker 225*8d67ca89SAndroid Build Coastguard Worker return nullptr; 226*8d67ca89SAndroid Build Coastguard Worker } 227*8d67ca89SAndroid Build Coastguard Worker begin()228*8d67ca89SAndroid Build Coastguard Worker iterator begin() const { 229*8d67ca89SAndroid Build Coastguard Worker return iterator(head()); 230*8d67ca89SAndroid Build Coastguard Worker } 231*8d67ca89SAndroid Build Coastguard Worker end()232*8d67ca89SAndroid Build Coastguard Worker iterator end() const { 233*8d67ca89SAndroid Build Coastguard Worker return iterator(nullptr); 234*8d67ca89SAndroid Build Coastguard Worker } 235*8d67ca89SAndroid Build Coastguard Worker find(T * value)236*8d67ca89SAndroid Build Coastguard Worker iterator find(T* value) const { 237*8d67ca89SAndroid Build Coastguard Worker for (LinkedListEntry<T>* e = head(); e != nullptr; e = e->next) { 238*8d67ca89SAndroid Build Coastguard Worker if (e->element == value) { 239*8d67ca89SAndroid Build Coastguard Worker return iterator(e); 240*8d67ca89SAndroid Build Coastguard Worker } 241*8d67ca89SAndroid Build Coastguard Worker } 242*8d67ca89SAndroid Build Coastguard Worker 243*8d67ca89SAndroid Build Coastguard Worker return end(); 244*8d67ca89SAndroid Build Coastguard Worker } 245*8d67ca89SAndroid Build Coastguard Worker copy_to_array(T * array[],size_t array_length)246*8d67ca89SAndroid Build Coastguard Worker size_t copy_to_array(T* array[], size_t array_length) const { 247*8d67ca89SAndroid Build Coastguard Worker size_t sz = 0; 248*8d67ca89SAndroid Build Coastguard Worker for (LinkedListEntry<T>* e = head(); sz < array_length && e != nullptr; e = e->next) { 249*8d67ca89SAndroid Build Coastguard Worker array[sz++] = e->element; 250*8d67ca89SAndroid Build Coastguard Worker } 251*8d67ca89SAndroid Build Coastguard Worker 252*8d67ca89SAndroid Build Coastguard Worker return sz; 253*8d67ca89SAndroid Build Coastguard Worker } 254*8d67ca89SAndroid Build Coastguard Worker contains(const T * el)255*8d67ca89SAndroid Build Coastguard Worker bool contains(const T* el) const { 256*8d67ca89SAndroid Build Coastguard Worker for (LinkedListEntry<T>* e = head(); e != nullptr; e = e->next) { 257*8d67ca89SAndroid Build Coastguard Worker if (e->element == el) { 258*8d67ca89SAndroid Build Coastguard Worker return true; 259*8d67ca89SAndroid Build Coastguard Worker } 260*8d67ca89SAndroid Build Coastguard Worker } 261*8d67ca89SAndroid Build Coastguard Worker return false; 262*8d67ca89SAndroid Build Coastguard Worker } 263*8d67ca89SAndroid Build Coastguard Worker make_list(T * const element)264*8d67ca89SAndroid Build Coastguard Worker static LinkedList make_list(T* const element) { 265*8d67ca89SAndroid Build Coastguard Worker LinkedList<T, Allocator> one_element_list; 266*8d67ca89SAndroid Build Coastguard Worker one_element_list.push_back(element); 267*8d67ca89SAndroid Build Coastguard Worker return one_element_list; 268*8d67ca89SAndroid Build Coastguard Worker } 269*8d67ca89SAndroid Build Coastguard Worker size()270*8d67ca89SAndroid Build Coastguard Worker size_t size() const { 271*8d67ca89SAndroid Build Coastguard Worker size_t result = 0; 272*8d67ca89SAndroid Build Coastguard Worker for_each([&](T*) { ++result; }); 273*8d67ca89SAndroid Build Coastguard Worker return result; 274*8d67ca89SAndroid Build Coastguard Worker } 275*8d67ca89SAndroid Build Coastguard Worker 276*8d67ca89SAndroid Build Coastguard Worker private: alloc_header()277*8d67ca89SAndroid Build Coastguard Worker void alloc_header() { 278*8d67ca89SAndroid Build Coastguard Worker if (header_ == nullptr) { 279*8d67ca89SAndroid Build Coastguard Worker header_ = reinterpret_cast<LinkedListHeader*>(Allocator::alloc()); 280*8d67ca89SAndroid Build Coastguard Worker header_->head = header_->tail = nullptr; 281*8d67ca89SAndroid Build Coastguard Worker } 282*8d67ca89SAndroid Build Coastguard Worker } 283*8d67ca89SAndroid Build Coastguard Worker head()284*8d67ca89SAndroid Build Coastguard Worker LinkedListEntry<T>* head() const { 285*8d67ca89SAndroid Build Coastguard Worker return header_ != nullptr ? header_->head : nullptr; 286*8d67ca89SAndroid Build Coastguard Worker } 287*8d67ca89SAndroid Build Coastguard Worker 288*8d67ca89SAndroid Build Coastguard Worker LinkedListHeader* header_; 289*8d67ca89SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(LinkedList); 290*8d67ca89SAndroid Build Coastguard Worker }; 291