示例#1
0
文件: u_string.cpp 项目: q66/neothyne
inline stringMemory::stringMemory()
    : m_head(neoMalloc(kMemorySize))
{
    memset(m_head, 0, kMemorySize);
    m_head->setSize(kMemorySize);
    m_head->setFree(true);
    m_tail = nextRegion(m_head);
}
示例#2
0
文件: u_string.cpp 项目: q66/neothyne
// Given a region of free memory and a size, split it in half repeatedly until the
// desired size is reached and return a pointer to that new free region.
inline stringMemory::region *stringMemory::divideRegion(region *reg, size_t size) {
    assert(reg);

    while (reg->size() > size) {
        const size_t regionSize = reg->size() / 2;
        reg->setSize(regionSize);
        reg = nextRegion(reg);
        reg->setSize(regionSize);
        reg->setFree(true);
    }
    return reg;
}
示例#3
0
文件: u_string.cpp 项目: q66/neothyne
// Single level merge of adjacent free blocks
bool stringMemory::mergeFree() {
    assert(m_head);

    region *reg = m_head;
    region *buddy = nextRegion(reg);
    bool modified = false;

    while (reg < m_tail && buddy < m_tail) {
        // Both region and buddy are free
        if (reg->free() && buddy->free() && reg->size() == buddy->size()) {
            reg->resize();
            reg = nextRegion(buddy);
            if (reg < m_tail)
                buddy = nextRegion(reg);
            modified = true;
        } else if (reg->size() > buddy->size()) {
            // Buddy has been split up into smaller chunks
            reg = buddy;
            buddy = nextRegion(buddy);
        } else {
            // Jump ahead two regions
            reg = nextRegion(buddy);
            if (reg < m_tail)
                buddy = nextRegion(reg);
        }
    }
    return modified;
}
示例#4
0
inline stringMemory::~stringMemory() {
#if !defined(NDEBUG)
    // walk the list to see if we leaked any memory
    bool leaks = false;
    for (region *reg = m_head; reg != m_tail; reg = nextRegion(reg))
    {
        if (U_LIKELY(reg->free()))
            continue;
        leaks = true;
        break;
    }
    if (leaks)
        print();
#endif
    neoFree(m_head);
}
示例#5
0
// Finds a free block that matches the size passed in.
// If it cannot find one of that size, but there is a larger free block, then
// it divides the larger block into smaller ones. If there is no larger block
// then it returns nullptr.
//
// Merges adjacent free blocks as it searches the list.
stringMemory::region *stringMemory::findAvailable(size_t size) {
    U_ASSERT(m_head);

    region *reg = m_head;
    region *buddy = nextRegion(reg);
    region *closest = nullptr;

    if (buddy == m_tail && reg->free())
        return divideRegion(reg, size);

    // Find minimum-sized match within the area of memory available
    size_t closestSize = 0;
    while (reg < m_tail && buddy < m_tail) {
        // When both the region and buddy are free
        if (reg->free() && buddy->free() && reg->size() == buddy->size()) {
            reg->resize();
            const size_t regSize = reg->size();
            if (size <= regSize && (!closest || regSize <= closest->size()))
                closest = reg;
            reg = nextRegion(buddy);
            if (reg < m_tail)
                buddy = nextRegion(reg);
        } else {
            if (closest)
                closestSize = closest->size();
            const size_t regSize = reg->size();
            if (reg->free() && size <= regSize && (!closest || regSize <= closestSize)) {
                closest = reg;
                closestSize = regSize;
            }
            const size_t buddySize = buddy->size();
            if (buddy->free() && size <= buddySize && (!closest || buddySize <= closestSize)) {
                closest = buddy;
                closestSize = buddySize;
            }
            // Buddy has been split up into smaller chunks
            if (regSize > buddySize) {
                reg = buddy;
                buddy = nextRegion(buddy);
            } else {
                // Jump ahead two regions
                reg = nextRegion(buddy);
                if (reg < m_tail)
                    buddy = nextRegion(reg);
            }
        }
    }

    if (closest) {
        if (closestSize == size)
            return closest;
        return divideRegion(closest, size);
    }
    return nullptr;
}
示例#6
0
文件: u_string.cpp 项目: q66/neothyne
void stringMemory::print() {
    auto escapeString = [](const char *str) {
        size_t length = strlen(str);
        // The longest possible sequence would be a string with "\x[0-F][0-F]"
        // for all, which is 4x as large as the input sequence, we also need + 1
        // for null terminator.
        u::unique_ptr<char> data(new char[length * 4 + 1]);
        char *put = data.get();
        for (const char *s = str; *s; s++) {
            unsigned char ch = *s;
            if (ch >= ' ' && ch <= '~' && ch != '\\' && ch != '"')
                *put++ = ch;
            else {
                *put++ = '\\';
                switch (ch) {
                case '"':  *put++ = '"';  break;
                case '\\': *put++ = '\\'; break;
                case '\t': *put++ = 't';  break;
                case '\r': *put++ = 'r';  break;
                case '\n': *put++ = 'n';  break;
                default:
                    *put++ = '\\';
                    *put++ = 'x';
                    *put++ = "0123456789ABCDEF"[ch >> 4];
                    *put++ = "0123456789ABCDEF"[ch & 0xF];
                    break;
                }
            }
        }
        *put++ = '\0';
        return data;
    };

    for (region *reg = m_head; reg < m_tail; reg = nextRegion(reg)) {
        if (reg->free()) {
            printf("Free (%p) [ size: %" PRIu32 " ]\n", (void *)reg, reg->size());
        } else {
            auto escape = escapeString((const char *)(reg + 1));
            printf("Used (%p) [ size: %" PRIu32 " contents: \"%.50s...\" ]\n",
                (void *)reg,
                reg->size(),
                escape.get()
            );
        }
    }
}