176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik/*
276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * Copyright 2015, The Android Open Source Project
376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik *
476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * Redistribution and use in source and binary forms, with or without
576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * modification, are permitted provided that the following conditions
676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * are met:
776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik *  * Redistributions of source code must retain the above copyright
876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik *    notice, this list of conditions and the following disclaimer.
976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik *  * Redistributions in binary form must reproduce the above copyright
1076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik *    notice, this list of conditions and the following disclaimer in the
1176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik *    documentation and/or other materials provided with the distribution.
1276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik *
1376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
1476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
1776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik */
2576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
2676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik#ifndef ANDROID_FAT_VECTOR_H
2776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik#define ANDROID_FAT_VECTOR_H
2876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
2976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik#include "utils/Macros.h"
3076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
3176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik#include <stddef.h>
3230bcf69df9cfae40b621335958656cb0e4afd7d5Doris Liu#include <stdlib.h>
3376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik#include <utils/Log.h>
341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <type_traits>
3576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
3676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik#include <vector>
3776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
3876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craiknamespace android {
3976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craiknamespace uirenderer {
4076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
4176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craiktemplate <typename T, size_t SIZE>
4276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craikclass InlineStdAllocator {
4376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craikpublic:
4476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    struct Allocation {
4576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        PREVENT_COPY_AND_ASSIGN(Allocation);
461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
4776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    public:
481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        Allocation(){};
4976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        // char array instead of T array, so memory is uninitialized, with no destructors run
5076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        char array[sizeof(T) * SIZE];
5176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        bool inUse = false;
5276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    };
5376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
541bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    typedef T value_type;  // needed to implement std::allocator
551bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    typedef T* pointer;    // needed to implement std::allocator
5676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {}
581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {}
5976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    ~InlineStdAllocator() {}
6076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
6176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    T* allocate(size_t num, const void* = 0) {
6276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        if (!mAllocation.inUse && num <= SIZE) {
6376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            mAllocation.inUse = true;
641bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            return (T*)mAllocation.array;
6576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        } else {
661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            return (T*)malloc(num * sizeof(T));
6776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        }
6876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    }
6976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
7076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    void deallocate(pointer p, size_t num) {
7176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        if (p == (T*)mAllocation.array) {
7276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            mAllocation.inUse = false;
7376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        } else {
7476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            // 'free' instead of delete here - destruction handled separately
7576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            free(p);
7676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        }
7776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    }
7876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    Allocation& mAllocation;
7976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik};
8076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
8176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik/**
8276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * std::vector with SIZE elements preallocated into an internal buffer.
8376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik *
8476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * Useful for avoiding the cost of malloc in cases where only SIZE or
8576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik * fewer elements are needed in the common case.
8676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik */
8776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craiktemplate <typename T, size_t SIZE>
8876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craikclass FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> {
8976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craikpublic:
901bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    FatVector()
911bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            : std::vector<T, InlineStdAllocator<T, SIZE>>(
921bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                      InlineStdAllocator<T, SIZE>(mAllocation)) {
9376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        this->reserve(SIZE);
9476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    }
958d2cf943d9c7292e54726399faefdec4a01c084bChris Craik
961bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); }
9730bcf69df9cfae40b621335958656cb0e4afd7d5Doris Liu
9876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craikprivate:
9976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
10076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik};
10176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
1021bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace uirenderer
1031bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace android
10476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
1051bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#endif  // ANDROID_FAT_VECTOR_H
106