Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d76781b authored by Mathias Agopian's avatar Mathias Agopian
Browse files

Make Flattenable not virtual (libutils)

Making an object Flattenable doesn't force it to
become virtual anymore. For instance, Fence and GraphicBuffer
are now non-virtual classes.

Also change Flatennable protocol a bit so that it updates
its parameters (pointers, sizes) to make it easier
to implement a flattenable in terms of other flattenables.

Change-Id: Ie81dc7637180b3c2cfcbaf644f8987ca804eb891
parent 7925b6bd
Loading
Loading
Loading
Loading
+6 −14
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@ namespace android {
// and then reloaded in a subsequent execution of the program.  This
// serialization is non-portable and the data should only be used by the device
// that generated it.
class BlobCache : public RefBase, public Flattenable {
class BlobCache : public RefBase {

public:

    // Create an empty blob cache. The blob cache will cache key/value pairs
@@ -78,14 +79,10 @@ public:
    //   0 <= valueSize
    size_t get(const void* key, size_t keySize, void* value, size_t valueSize);


    // getFlattenedSize returns the number of bytes needed to store the entire
    // serialized cache.
    virtual size_t getFlattenedSize() const;

    // getFdCount returns the number of file descriptors that will result from
    // flattening the cache.  This will always return 0 so as to allow the
    // flattened cache to be saved to disk and then later restored.
    virtual size_t getFdCount() const;
    size_t getFlattenedSize() const;

    // flatten serializes the current contents of the cache into the memory
    // pointed to by 'buffer'.  The serialized cache contents can later be
@@ -94,9 +91,7 @@ public:
    //
    // Preconditions:
    //   size >= this.getFlattenedSize()
    //   count == 0
    virtual status_t flatten(void* buffer, size_t size, int fds[],
            size_t count) const;
    status_t flatten(void* buffer, size_t size) const;

    // unflatten replaces the contents of the cache with the serialized cache
    // contents in the memory pointed to by 'buffer'.  The previous contents of
@@ -104,10 +99,7 @@ public:
    // unflattening the serialized cache contents then the BlobCache will be
    // left in an empty state.
    //
    // Preconditions:
    //   count == 0
    virtual status_t unflatten(void const* buffer, size_t size, int fds[],
            size_t count);
    status_t unflatten(void const* buffer, size_t size);

private:
    // Copying is disallowed.
+86 −25
Original line number Diff line number Diff line
@@ -21,30 +21,75 @@
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/Debug.h>

namespace android {


class FlattenableUtils {
public:
    template<int N>
    static size_t align(size_t size) {
        COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
        return (size + (N-1)) & ~(N-1);
    }

    template<int N>
    static size_t align(void*& buffer) {
        COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
        intptr_t b = intptr_t(buffer);
        buffer = (void*)((intptr_t(buffer) + (N-1)) & ~(N-1));
        return size_t(intptr_t(buffer) - b);
    }

    static void advance(void*& buffer, size_t& size, size_t offset) {
        buffer = reinterpret_cast<void*>( intptr_t(buffer) + offset );
        size -= offset;
    }

    static void advance(void const*& buffer, size_t& size, size_t offset) {
        buffer = reinterpret_cast<void const*>( intptr_t(buffer) + offset );
        size -= offset;
    }

    // write a POD structure
    template<typename T>
    static void write(void*& buffer, size_t& size, const T& value) {
        *static_cast<T*>(buffer) = value;
        advance(buffer, size, sizeof(T));
    }

    // read a POD structure
    template<typename T>
    static void read(void const*& buffer, size_t& size, T& value) {
        value = *static_cast<T const*>(buffer);
        advance(buffer, size, sizeof(T));
    }
};


/*
 * The Flattenable interface allows an object to serialize itself out
 * The Flattenable protocol allows an object to serialize itself out
 * to a byte-buffer and an array of file descriptors.
 * Flattenable objects must implement this protocol.
 */

class Flattenable
{
template <typename T>
class Flattenable {
public:
    // size in bytes of the flattened object
    virtual size_t getFlattenedSize() const = 0;
    inline size_t getFlattenedSize() const;

    // number of file descriptors to flatten
    virtual size_t getFdCount() const = 0;
    inline size_t getFdCount() const;

    // flattens the object into buffer.
    // size should be at least of getFlattenedSize()
    // file descriptors are written in the fds[] array but ownership is
    // not transfered (ie: they must be dupped by the caller of
    // flatten() if needed).
    virtual status_t flatten(void* buffer, size_t size,
            int fds[], size_t count) const = 0;
    inline status_t flatten(void*& buffer, size_t& size,
            int*& fds, size_t& count) const;

    // unflattens the object from buffer.
    // size should be equal to the value of getFlattenedSize() when the
@@ -53,21 +98,34 @@ public:
    // don't need to be dupped(). ie: the caller of unflatten doesn't
    // keep ownership. If a fd is not retained by unflatten() it must be
    // explicitly closed.
    virtual status_t unflatten(void const* buffer, size_t size,
            int fds[], size_t count) = 0;

protected:
    virtual ~Flattenable() = 0;

    inline status_t unflatten(void const*& buffer, size_t& size,
            int const*& fds, size_t& count);
};

template<typename T>
inline size_t Flattenable<T>::getFlattenedSize() const {
    return static_cast<T const*>(this)->T::getFlattenedSize();
}
template<typename T>
inline size_t Flattenable<T>::getFdCount() const {
    return static_cast<T const*>(this)->T::getFdCount();
}
template<typename T>
inline status_t Flattenable<T>::flatten(
        void*& buffer, size_t& size, int*& fds, size_t& count) const {
    return static_cast<T const*>(this)->T::flatten(buffer, size, fds, count);
}
template<typename T>
inline status_t Flattenable<T>::unflatten(
        void const*& buffer, size_t& size, int const*& fds, size_t& count) {
    return static_cast<T*>(this)->T::unflatten(buffer, size, fds, count);
}

/*
 * LightFlattenable is a protocol allowing object to serialize themselves out
 * to a byte-buffer.
 *
 * to a byte-buffer. Because it doesn't handle file-descriptors,
 * LightFlattenable is usually more size efficient than Flattenable.
 * LightFlattenable objects must implement this protocol.
 *
 * LightFlattenable doesn't require the object to be virtual.
 */
template <typename T>
class LightFlattenable {
@@ -77,10 +135,10 @@ public:
    inline bool isFixedSize() const;

    // returns size in bytes of the flattened object. must be a constant.
    inline size_t getSize() const;
    inline size_t getFlattenedSize() const;

    // flattens the object into buffer.
    inline status_t flatten(void* buffer) const;
    inline status_t flatten(void* buffer, size_t size) const;

    // unflattens the object from buffer of given size.
    inline status_t unflatten(void const* buffer, size_t size);
@@ -91,12 +149,12 @@ inline bool LightFlattenable<T>::isFixedSize() const {
    return static_cast<T const*>(this)->T::isFixedSize();
}
template <typename T>
inline size_t LightFlattenable<T>::getSize() const {
    return static_cast<T const*>(this)->T::getSize();
inline size_t LightFlattenable<T>::getFlattenedSize() const {
    return static_cast<T const*>(this)->T::getFlattenedSize();
}
template <typename T>
inline status_t LightFlattenable<T>::flatten(void* buffer) const {
    return static_cast<T const*>(this)->T::flatten(buffer);
inline status_t LightFlattenable<T>::flatten(void* buffer, size_t size) const {
    return static_cast<T const*>(this)->T::flatten(buffer, size);
}
template <typename T>
inline status_t LightFlattenable<T>::unflatten(void const* buffer, size_t size) {
@@ -106,6 +164,8 @@ inline status_t LightFlattenable<T>::unflatten(void const* buffer, size_t size)
/*
 * LightFlattenablePod is an implementation of the LightFlattenable protocol
 * for POD (plain-old-data) objects.
 * Simply derive from LightFlattenablePod<Foo> to make Foo flattenable; no
 * need to implement any methods; obviously Foo must be a POD structure.
 */
template <typename T>
class LightFlattenablePod : public LightFlattenable<T> {
@@ -114,10 +174,11 @@ public:
        return true;
    }

    inline size_t getSize() const {
    inline size_t getFlattenedSize() const {
        return sizeof(T);
    }
    inline status_t flatten(void* buffer) const {
    inline status_t flatten(void* buffer, size_t size) const {
        if (size < sizeof(T)) return NO_MEMORY;
        *reinterpret_cast<T*>(buffer) = *static_cast<T const*>(this);
        return NO_ERROR;
    }
+0 −1
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ commonSources:= \
	BlobCache.cpp \
	CallStack.cpp \
	FileMap.cpp \
	Flattenable.cpp \
	JenkinsHash.cpp \
	LinearAllocator.cpp \
	LinearTransform.cpp \
+2 −18
Original line number Diff line number Diff line
@@ -176,17 +176,7 @@ size_t BlobCache::getFlattenedSize() const {
    return size;
}

size_t BlobCache::getFdCount() const {
    return 0;
}

status_t BlobCache::flatten(void* buffer, size_t size, int fds[], size_t count)
        const {
    if (count != 0) {
        ALOGE("flatten: nonzero fd count: %zu", count);
        return BAD_VALUE;
    }

status_t BlobCache::flatten(void* buffer, size_t size) const {
    // Write the cache header
    if (size < sizeof(Header)) {
        ALOGE("flatten: not enough room for cache header");
@@ -228,16 +218,10 @@ status_t BlobCache::flatten(void* buffer, size_t size, int fds[], size_t count)
    return OK;
}

status_t BlobCache::unflatten(void const* buffer, size_t size, int fds[],
        size_t count) {
status_t BlobCache::unflatten(void const* buffer, size_t size) {
    // All errors should result in the BlobCache being in an empty state.
    mCacheEntries.clear();

    if (count != 0) {
        ALOGE("unflatten: nonzero fd count: %zu", count);
        return BAD_VALUE;
    }

    // Read the cache header
    if (size < sizeof(Header)) {
        ALOGE("unflatten: not enough room for cache header");

libs/utils/Flattenable.cpp

deleted100644 → 0
+0 −24
Original line number Diff line number Diff line
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <utils/Flattenable.h>

namespace android {

Flattenable::~Flattenable() {
}

}; // namespace android