<commit_before>#include "Club.h"

using namespace std;

Club::Club(): money_(0), installations_() {

    for (int i = 0; i < 7; ++i) {
        players_.push_back(new NonFieldPlayer());

        team_->setPlayer(*players_.at((unsigned int)i), i);

    }
}

Club::Club(JsonValue * json) {
    JsonDict * club = JDICT(json);
    JsonDict * ins;

    if (club == NULL) {
        throw ModelUnserializationError("Club initialized from non dict");
    }

    JsonInt * money_int = JINT((*club)["money"]);
    if (money_int == NULL) {
        throw ModelUnserializationError("Missing int at key 'money' in Club");
    }

    int money = *money_int;
    Installation installations[5];

    JsonList * installations_list = JLIST((*club)["installations"]);
    if (installations_list == NULL) {
        throw ModelUnserializationError("Missing list at key 'installations' in Club");
    }
    if (installations_list->size() != 5) {
        throw ModelUnserializationError("Bad 'installations' size in Club");
    }

    for (int i = 0; i < 5; i++) {
        ins = JDICT((*installations_list)[i]);
        if (ins == NULL) {
            throw ModelUnserializationError("Null installation in Club");
        }

        installations[i] = Installation(ins);
    }

    Team * team = new Team((*club)["team"]);
    JsonList * player_list = JLIST((*club)["players"]);
    if (player_list == NULL) {
        throw ModelUnserializationError("Missing list at key 'players' in Club");
    }

    vector<NonFieldPlayer *> players;
    for (int i = 0; i < player_list->size(); i++) {
        players.push_back(new NonFieldPlayer((*player_list)[i]));
    }
    //TODO uncomment
    //for (int i = 0; i < 7; i++) {
    //    if (team_->getPlayer(i) != NULL) {
    //        players.push_back(team_->getPlayer(i));
    //    }
    //}

    new (this)Club(money, installations, team, players);
}

Club::Club(int money, Installation * installations, Team * team, vector<NonFieldPlayer *> players): money_(money), players_(players) {
    for (int i = 0; i < 5; ++i) {
        installations_[i] = installations[i];
    }
    team_ = team;
}

Club::~Club() {}

int Club::addMoney(const int deltaMoney) {
    return money_ += deltaMoney;
}

int Club::getMoney() {
    return money_;
}

int Club::getLevel() {
    int level = 0;
    for (int i = 0; i < 5; ++i) {
        level += installations_[i].getLevel();
    }
    return level;
}

Team * Club::getTeam() {
    return team_;
}

std::vector<NonFieldPlayer *> Club::getNonFieldPlayers() {
    return players_;
}

void Club::addNonFieldPlayer(NonFieldPlayer * player) {
    players_.push_back(player);
}

NonFieldPlayer * Club::removeNonFieldPlayer(unsigned int pos) {
    NonFieldPlayer * tmpPlayer = players_[pos];
    players_.erase(players_.begin() + pos);
    return tmpPlayer;
}

void Club::addInstallation(Installation & installation, int pos) {
    installations_[pos] = installation;
}

Installation * Club::getInstallations() {
    return installations_;
}

Club::operator JsonDict() const {
    JsonDict r;

    r.add("money", new JsonInt(money_));

    JsonDict * team = new JsonDict(*team_);
    r.add("team", team);

    JsonList * installations = new JsonList();
    for (int i = 0; i < 5; i++) {
        JsonDict * install = new JsonDict(installations_[i]);
        installations->add(install);
    }
    r.add("installations", installations);

    JsonList * players = new JsonList();
    for (int i = 0; i < players_.size(); i++) {
        bool present = false;
        for (int j = 0; (j < 7) && (!present); j++) {
            present = players_[i] == team_->getPlayer(j);
        }
        if (!present) {
            JsonDict * player = new JsonDict(*(players_[i]));
            players->add(player);
        }
    }
    r.add("players", players);

    return r;
}
<commit_msg>Fix problem when login with an existing username.<commit_after>#include "Club.h"

using namespace std;

Club::Club(): money_(0), installations_() {

    for (int i = 0; i < 7; ++i) {
        players_.push_back(new NonFieldPlayer());

        team_->setPlayer(*players_.at((unsigned int)i), i);

    }
}

Club::Club(JsonValue * json) {
    JsonDict * club = JDICT(json);
    JsonDict * ins;

    if (club == NULL) {
        throw ModelUnserializationError("Club initialized from non dict");
    }

    JsonInt * money_int = JINT((*club)["money"]);
    if (money_int == NULL) {
        throw ModelUnserializationError("Missing int at key 'money' in Club");
    }

    int money = *money_int;
    Installation installations[5];

    JsonList * installations_list = JLIST((*club)["installations"]);
    if (installations_list == NULL) {
        throw ModelUnserializationError("Missing list at key 'installations' in Club");
    }
    if (installations_list->size() != 5) {
        throw ModelUnserializationError("Bad 'installations' size in Club");
    }

    for (int i = 0; i < 5; i++) {
        ins = JDICT((*installations_list)[i]);
        if (ins == NULL) {
            throw ModelUnserializationError("Null installation in Club");
        }

        installations[i] = Installation(ins);
    }

    Team * team = new Team((*club)["team"]);
    JsonList * player_list = JLIST((*club)["players"]);
    if (player_list == NULL) {
        throw ModelUnserializationError("Missing list at key 'players' in Club");
    }

    vector<NonFieldPlayer *> players;
    for (int i = 0; i < player_list->size(); i++) {
        players.push_back(new NonFieldPlayer((*player_list)[i]));
    }
    for (int i = 0; i < 7; i++) {
        if (team->getPlayer(i) != NULL) {
            players.push_back(team->getPlayer(i));
        }
    }

    new (this)Club(money, installations, team, players);
}

Club::Club(int money, Installation * installations, Team * team, vector<NonFieldPlayer *> players): money_(money), players_(players) {
    for (int i = 0; i < 5; ++i) {
        installations_[i] = installations[i];
    }
    team_ = team;
}

Club::~Club() {}

int Club::addMoney(const int deltaMoney) {
    return money_ += deltaMoney;
}

int Club::getMoney() {
    return money_;
}

int Club::getLevel() {
    int level = 0;
    for (int i = 0; i < 5; ++i) {
        level += installations_[i].getLevel();
    }
    return level;
}

Team * Club::getTeam() {
    return team_;
}

std::vector<NonFieldPlayer *> Club::getNonFieldPlayers() {
    return players_;
}

void Club::addNonFieldPlayer(NonFieldPlayer * player) {
    players_.push_back(player);
}

NonFieldPlayer * Club::removeNonFieldPlayer(unsigned int pos) {
    NonFieldPlayer * tmpPlayer = players_[pos];
    players_.erase(players_.begin() + pos);
    return tmpPlayer;
}

void Club::addInstallation(Installation & installation, int pos) {
    installations_[pos] = installation;
}

Installation * Club::getInstallations() {
    return installations_;
}

Club::operator JsonDict() const {
    JsonDict r;

    r.add("money", new JsonInt(money_));

    JsonDict * team = new JsonDict(*team_);
    r.add("team", team);

    JsonList * installations = new JsonList();
    for (int i = 0; i < 5; i++) {
        JsonDict * install = new JsonDict(installations_[i]);
        installations->add(install);
    }
    r.add("installations", installations);

    JsonList * players = new JsonList();
    for (int i = 0; i < players_.size(); i++) {
        bool present = false;
        for (int j = 0; (j < 7) && (!present); j++) {
            present = players_[i] == team_->getPlayer(j);
        }
        if (!present) {
            JsonDict * player = new JsonDict(*(players_[i]));
            players->add(player);
        }
    }
    r.add("players", players);

    return r;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "compiler/PoolAlloc.h"

#ifndef _MSC_VER
#include <stdint.h>
#endif

#include "compiler/InitializeGlobals.h"
#include "compiler/osinclude.h"

OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;

void InitializeGlobalPools()
{
    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
    if (globalPools)
        return;

    TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true);

    TThreadGlobalPools* threadData = new TThreadGlobalPools();

    threadData->globalPoolAllocator = globalPoolAllocator;

    OS_SetTLSValue(PoolIndex, threadData);
    globalPoolAllocator->push();
}

void FreeGlobalPools()
{
    // Release the allocated memory for this thread.
    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
    if (!globalPools)
        return;

    GlobalPoolAllocator.popAll();
    delete &GlobalPoolAllocator;
    delete globalPools;
}

bool InitializePoolIndex()
{
    // Allocate a TLS index.
    if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
        return false;

    return true;
}

void FreePoolIndex()
{
    // Release the TLS index.
    OS_FreeTLSIndex(PoolIndex);
}

TPoolAllocator& GetGlobalPoolAllocator()
{
    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));

    return *threadData->globalPoolAllocator;
}

void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator)
{
    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));

    threadData->globalPoolAllocator = poolAllocator;
}

//
// Implement the functionality of the TPoolAllocator class, which
// is documented in PoolAlloc.h.
//
TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignment) :
    global(g),
    pageSize(growthIncrement),
    alignment(allocationAlignment),
    freeList(0),
    inUseList(0),
    numCalls(0)
{
    //
    // Don't allow page sizes we know are smaller than all common
    // OS page sizes.
    //
    if (pageSize < 4*1024)
        pageSize = 4*1024;

    //
    // A large currentPageOffset indicates a new page needs to
    // be obtained to allocate memory.
    //
    currentPageOffset = pageSize;

    //
    // Adjust alignment to be at least pointer aligned and
    // power of 2.
    //
    size_t minAlign = sizeof(void*);
    alignment &= ~(minAlign - 1);
    if (alignment < minAlign)
        alignment = minAlign;
    size_t a = 1;
    while (a < alignment)
        a <<= 1;
    alignment = a;
    alignmentMask = a - 1;

    //
    // Align header skip
    //
    headerSkip = minAlign;
    if (headerSkip < sizeof(tHeader)) {
        headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
    }
}

TPoolAllocator::~TPoolAllocator()
{
    if (!global) {
        //
        // Then we know that this object is not being
        // allocated after other, globally scoped objects
        // that depend on it.  So we can delete the "in use" memory.
        //
        while (inUseList) {
            tHeader* next = inUseList->nextPage;
            inUseList->~tHeader();
            delete [] reinterpret_cast<char*>(inUseList);
            inUseList = next;
        }
    }

    //
    // Always delete the free list memory - it can't be being
    // (correctly) referenced, whether the pool allocator was
    // global or not.  We should not check the guard blocks
    // here, because we did it already when the block was
    // placed into the free list.
    //
    while (freeList) {
        tHeader* next = freeList->nextPage;
        delete [] reinterpret_cast<char*>(freeList);
        freeList = next;
    }
}

// Support MSVC++ 6.0
const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
const unsigned char TAllocation::userDataFill       = 0xcd;

#ifdef GUARD_BLOCKS
    const size_t TAllocation::guardBlockSize = 16;
#else
    const size_t TAllocation::guardBlockSize = 0;
#endif

//
// Check a single guard block for damage
//
void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
{
    for (size_t x = 0; x < guardBlockSize; x++) {
        if (blockMem[x] != val) {
            char assertMsg[80];

            // We don't print the assert message.  It's here just to be helpful.
            sprintf(assertMsg, "PoolAlloc: Damage %s %u byte allocation at 0x%p\n",
                    locText, size, data());
            assert(0 && "PoolAlloc: Damage in guard block");
        }
    }
}

void TPoolAllocator::push()
{
    tAllocState state = { currentPageOffset, inUseList };

    stack.push_back(state);

    //
    // Indicate there is no current page to allocate from.
    //
    currentPageOffset = pageSize;
}

//
// Do a mass-deallocation of all the individual allocations
// that have occurred since the last push(), or since the
// last pop(), or since the object's creation.
//
// The deallocated pages are saved for future allocations.
//
void TPoolAllocator::pop()
{
    if (stack.size() < 1)
        return;

    tHeader* page = stack.back().page;
    currentPageOffset = stack.back().offset;

    while (inUseList != page) {
        // invoke destructor to free allocation list
        inUseList->~tHeader();

        tHeader* nextInUse = inUseList->nextPage;
        if (inUseList->pageCount > 1)
            delete [] reinterpret_cast<char*>(inUseList);
        else {
            inUseList->nextPage = freeList;
            freeList = inUseList;
        }
        inUseList = nextInUse;
    }

    stack.pop_back();
}

//
// Do a mass-deallocation of all the individual allocations
// that have occurred.
//
void TPoolAllocator::popAll()
{
    while (stack.size() > 0)
        pop();
}

void* TPoolAllocator::allocate(size_t numBytes)
{
    // If we are using guard blocks, all allocations are bracketed by
    // them: [guardblock][allocation][guardblock].  numBytes is how
    // much memory the caller asked for.  allocationSize is the total
    // size including guard blocks.  In release build,
    // guardBlockSize=0 and this all gets optimized away.
    size_t allocationSize = TAllocation::allocationSize(numBytes);

    //
    // Just keep some interesting statistics.
    //
    ++numCalls;
    totalBytes += numBytes;

    //
    // Do the allocation, most likely case first, for efficiency.
    // This step could be moved to be inline sometime.
    //
    if (currentPageOffset + allocationSize <= pageSize) {
        //
        // Safe to allocate from currentPageOffset.
        //
        unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
        currentPageOffset += allocationSize;
        currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;

        return initializeAllocation(inUseList, memory, numBytes);
    }

    if (allocationSize + headerSkip > pageSize) {
        //
        // Do a multi-page allocation.  Don't mix these with the others.
        // The OS is efficient and allocating and free-ing multiple pages.
        //
        size_t numBytesToAlloc = allocationSize + headerSkip;
        tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
        if (memory == 0)
            return 0;

        // Use placement-new to initialize header
        new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
        inUseList = memory;

        currentPageOffset = pageSize;  // make next allocation come from a new page

        // No guard blocks for multi-page allocations (yet)
        return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
    }

    //
    // Need a simple page to allocate from.
    //
    tHeader* memory;
    if (freeList) {
        memory = freeList;
        freeList = freeList->nextPage;
    } else {
        memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
        if (memory == 0)
            return 0;
    }

    // Use placement-new to initialize header
    new(memory) tHeader(inUseList, 1);
    inUseList = memory;

    unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
    currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;

    return initializeAllocation(inUseList, ret, numBytes);
}

//
// Check all allocations in a list for damage by calling check on each.
//
void TAllocation::checkAllocList() const
{
    for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
        alloc->check();
}
<commit_msg>Fixed compile error with gcc 4.4. TBR=gman@chromium.org Review URL: http://codereview.appspot.com/1199047<commit_after>//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "compiler/PoolAlloc.h"

#ifndef _MSC_VER
#include <stdint.h>
#endif
#include <stdio.h>

#include "compiler/InitializeGlobals.h"
#include "compiler/osinclude.h"

OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;

void InitializeGlobalPools()
{
    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
    if (globalPools)
        return;

    TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true);

    TThreadGlobalPools* threadData = new TThreadGlobalPools();

    threadData->globalPoolAllocator = globalPoolAllocator;

    OS_SetTLSValue(PoolIndex, threadData);
    globalPoolAllocator->push();
}

void FreeGlobalPools()
{
    // Release the allocated memory for this thread.
    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
    if (!globalPools)
        return;

    GlobalPoolAllocator.popAll();
    delete &GlobalPoolAllocator;
    delete globalPools;
}

bool InitializePoolIndex()
{
    // Allocate a TLS index.
    if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
        return false;

    return true;
}

void FreePoolIndex()
{
    // Release the TLS index.
    OS_FreeTLSIndex(PoolIndex);
}

TPoolAllocator& GetGlobalPoolAllocator()
{
    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));

    return *threadData->globalPoolAllocator;
}

void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator)
{
    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));

    threadData->globalPoolAllocator = poolAllocator;
}

//
// Implement the functionality of the TPoolAllocator class, which
// is documented in PoolAlloc.h.
//
TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignment) :
    global(g),
    pageSize(growthIncrement),
    alignment(allocationAlignment),
    freeList(0),
    inUseList(0),
    numCalls(0)
{
    //
    // Don't allow page sizes we know are smaller than all common
    // OS page sizes.
    //
    if (pageSize < 4*1024)
        pageSize = 4*1024;

    //
    // A large currentPageOffset indicates a new page needs to
    // be obtained to allocate memory.
    //
    currentPageOffset = pageSize;

    //
    // Adjust alignment to be at least pointer aligned and
    // power of 2.
    //
    size_t minAlign = sizeof(void*);
    alignment &= ~(minAlign - 1);
    if (alignment < minAlign)
        alignment = minAlign;
    size_t a = 1;
    while (a < alignment)
        a <<= 1;
    alignment = a;
    alignmentMask = a - 1;

    //
    // Align header skip
    //
    headerSkip = minAlign;
    if (headerSkip < sizeof(tHeader)) {
        headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
    }
}

TPoolAllocator::~TPoolAllocator()
{
    if (!global) {
        //
        // Then we know that this object is not being
        // allocated after other, globally scoped objects
        // that depend on it.  So we can delete the "in use" memory.
        //
        while (inUseList) {
            tHeader* next = inUseList->nextPage;
            inUseList->~tHeader();
            delete [] reinterpret_cast<char*>(inUseList);
            inUseList = next;
        }
    }

    //
    // Always delete the free list memory - it can't be being
    // (correctly) referenced, whether the pool allocator was
    // global or not.  We should not check the guard blocks
    // here, because we did it already when the block was
    // placed into the free list.
    //
    while (freeList) {
        tHeader* next = freeList->nextPage;
        delete [] reinterpret_cast<char*>(freeList);
        freeList = next;
    }
}

// Support MSVC++ 6.0
const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
const unsigned char TAllocation::userDataFill       = 0xcd;

#ifdef GUARD_BLOCKS
    const size_t TAllocation::guardBlockSize = 16;
#else
    const size_t TAllocation::guardBlockSize = 0;
#endif

//
// Check a single guard block for damage
//
void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
{
    for (size_t x = 0; x < guardBlockSize; x++) {
        if (blockMem[x] != val) {
            char assertMsg[80];

            // We don't print the assert message.  It's here just to be helpful.
            sprintf(assertMsg, "PoolAlloc: Damage %s %u byte allocation at 0x%p\n",
                    locText, size, data());
            assert(0 && "PoolAlloc: Damage in guard block");
        }
    }
}

void TPoolAllocator::push()
{
    tAllocState state = { currentPageOffset, inUseList };

    stack.push_back(state);

    //
    // Indicate there is no current page to allocate from.
    //
    currentPageOffset = pageSize;
}

//
// Do a mass-deallocation of all the individual allocations
// that have occurred since the last push(), or since the
// last pop(), or since the object's creation.
//
// The deallocated pages are saved for future allocations.
//
void TPoolAllocator::pop()
{
    if (stack.size() < 1)
        return;

    tHeader* page = stack.back().page;
    currentPageOffset = stack.back().offset;

    while (inUseList != page) {
        // invoke destructor to free allocation list
        inUseList->~tHeader();

        tHeader* nextInUse = inUseList->nextPage;
        if (inUseList->pageCount > 1)
            delete [] reinterpret_cast<char*>(inUseList);
        else {
            inUseList->nextPage = freeList;
            freeList = inUseList;
        }
        inUseList = nextInUse;
    }

    stack.pop_back();
}

//
// Do a mass-deallocation of all the individual allocations
// that have occurred.
//
void TPoolAllocator::popAll()
{
    while (stack.size() > 0)
        pop();
}

void* TPoolAllocator::allocate(size_t numBytes)
{
    // If we are using guard blocks, all allocations are bracketed by
    // them: [guardblock][allocation][guardblock].  numBytes is how
    // much memory the caller asked for.  allocationSize is the total
    // size including guard blocks.  In release build,
    // guardBlockSize=0 and this all gets optimized away.
    size_t allocationSize = TAllocation::allocationSize(numBytes);

    //
    // Just keep some interesting statistics.
    //
    ++numCalls;
    totalBytes += numBytes;

    //
    // Do the allocation, most likely case first, for efficiency.
    // This step could be moved to be inline sometime.
    //
    if (currentPageOffset + allocationSize <= pageSize) {
        //
        // Safe to allocate from currentPageOffset.
        //
        unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
        currentPageOffset += allocationSize;
        currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;

        return initializeAllocation(inUseList, memory, numBytes);
    }

    if (allocationSize + headerSkip > pageSize) {
        //
        // Do a multi-page allocation.  Don't mix these with the others.
        // The OS is efficient and allocating and free-ing multiple pages.
        //
        size_t numBytesToAlloc = allocationSize + headerSkip;
        tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
        if (memory == 0)
            return 0;

        // Use placement-new to initialize header
        new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
        inUseList = memory;

        currentPageOffset = pageSize;  // make next allocation come from a new page

        // No guard blocks for multi-page allocations (yet)
        return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
    }

    //
    // Need a simple page to allocate from.
    //
    tHeader* memory;
    if (freeList) {
        memory = freeList;
        freeList = freeList->nextPage;
    } else {
        memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
        if (memory == 0)
            return 0;
    }

    // Use placement-new to initialize header
    new(memory) tHeader(inUseList, 1);
    inUseList = memory;

    unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
    currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;

    return initializeAllocation(inUseList, ret, numBytes);
}

//
// Check all allocations in a list for damage by calling check on each.
//
void TAllocation::checkAllocList() const
{
    for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
        alloc->check();
}
<|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*               Copyright 2002-2003 by Ullrich Koethe                  */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    You may use, modify, and distribute this software according       */
/*    to the terms stated in the LICENSE file included in               */
/*    the VIGRA distribution.                                           */
/*                                                                      */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        koethe@informatik.uni-hamburg.de                              */
/*                                                                      */
/*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
/*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_ARRAY_VECTOR_HXX
#define VIGRA_ARRAY_VECTOR_HXX

#include <memory>
#include <algorithm>
#include <vigra/memory.hxx>

namespace vigra
{

template <class T, class Alloc = std::allocator<T> >
class ArrayVector
{
    typedef ArrayVector<T, Alloc> this_type;

public:
    typedef T value_type;
    typedef value_type & reference;
    typedef value_type const & const_reference;
    typedef value_type * pointer;
    typedef value_type const * const_pointer;
    typedef value_type * iterator;
    typedef value_type const * const_iterator;
    typedef unsigned int size_type;
    typedef int          difference_type;
    typedef Alloc        allocator_type;

public:
    ArrayVector();

    explicit ArrayVector(Alloc const & alloc);

    explicit ArrayVector( size_type size, Alloc const & alloc = Alloc());

    ArrayVector( size_type size, value_type const & initial, Alloc const & alloc = Alloc());

    ArrayVector( this_type const & rhs );

    template <class InputIterator>
    ArrayVector(InputIterator i, InputIterator end);

    template <class InputIterator>
    ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc);

    this_type & operator=( this_type const & rhs );

    ~ArrayVector();

    inline const_pointer data() const
    {
        return data_;
    }

    inline pointer data()
    {
        return data_;
    }

    inline const_iterator begin() const
    {
        return data();
    }

    inline iterator begin()
    {
        return data();
    }

    inline const_iterator end() const
    {
        return data() + size();
    }

    inline iterator end()
    {
        return data() + size();
    }

    reference front()
    {
        return *data_;
    }

    const_reference front() const
    {
        return *data_;
    }

    reference back()
    {
        return data_[size_-1];
    }

    const_reference back() const
    {
        return data_[size_-1];
    }

    reference operator[]( size_type i )
    {
        return data()[i];
    }

    const_reference operator[]( size_type i ) const
    {
        return data()[i];
    }

    void pop_back();

    void push_back( value_type const & t );

    iterator insert(iterator p, value_type const & v);

    iterator insert(iterator p, size_type n, value_type const & v);

    template <class InputIterator>
    iterator insert(iterator p, InputIterator i, InputIterator iend);

    iterator erase(iterator p);

    iterator erase(iterator p, iterator q);

    void clear();

    void reserve( size_type new_capacity );

    void reserve();

    void resize( size_type new_size, value_type const & initial );

    void resize( size_type new_size )
    {
        resize(new_size, value_type());
    }

    bool empty() const
    {
        return size_ == 0;
    }

    size_type size() const
    {
        return size_;
    }

    size_type capacity() const
    {
        return capacity_;
    }

    void swap(this_type & rhs);

  private:

    void deallocate(pointer data, size_type size);

    pointer reserve_raw(size_type capacity);

    Alloc alloc_;
    size_type size_, capacity_;
    pointer data_;
};

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector()
: alloc_(Alloc()),
  size_(0),
  capacity_(5),
  data_(reserve_raw(5))
{}

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector(Alloc const & alloc)
: alloc_(alloc),
  size_(0),
  capacity_(5),
  data_(reserve_raw(5))
{}

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector( size_type size, Alloc const & alloc)
: alloc_(alloc),
  size_(size),
  capacity_(size),
  data_(reserve_raw(size))
{
    if(size_ > 0)
        std::uninitialized_fill(data_, data_+size_, value_type());
}

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector( size_type size,
                         value_type const & initial, Alloc const & alloc)
: alloc_(alloc),
  size_(size),
  capacity_(size),
  data_(reserve_raw(size))
{
    if(size_ > 0)
        std::uninitialized_fill(data_, data_+size_, initial);
}

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector( this_type const & rhs )
: alloc_(rhs.alloc_),
  size_(rhs.size_),
  capacity_(rhs.capacity_),
  data_(reserve_raw(rhs.capacity_))
{
    if(size_ > 0)
        std::uninitialized_copy(rhs.data_, rhs.data_+size_, data_);
}

template <class T, class Alloc>
template <class InputIterator>
ArrayVector<T, Alloc>::ArrayVector(InputIterator i, InputIterator end)
: alloc_(),
  size_(std::distance(i, end)),
  capacity_(size_),
  data_(reserve_raw(size_))
{
    std::uninitialized_copy(i, end, data_);
}

template <class T, class Alloc>
template <class InputIterator>
ArrayVector<T, Alloc>::ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc)
: alloc_(alloc),
  size_(std::distance(i, end)),
  capacity_(size_),
  data_(reserve_raw(size_))
{
    std::uninitialized_copy(i, end, data_);
}

template <class T, class Alloc>
ArrayVector<T, Alloc> & ArrayVector<T, Alloc>::operator=( this_type const & rhs )
{
    if(this == &rhs)
        return *this;
    ArrayVector new_vector(rhs);
    swap(new_vector);
    return *this;
}

template <class T, class Alloc>
ArrayVector<T, Alloc>::~ArrayVector()
{
    deallocate(data_, size_);
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::pop_back()
{
    --size_;
    alloc_.destroy(data_ + size_);
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::push_back( value_type const & t )
{
    reserve();
    alloc_.construct(data_ + size_, t);
    ++size_;
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::clear()
{
    detail::destroy_n(data_, size_);
    size_ = 0;
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::insert(iterator p, value_type const & v)
{
    difference_type pos = p - begin();
    if(p == end())
    {
        push_back(v);
        p = begin() + pos;
    }
    else
    {
        push_back(back());
        p = begin() + pos;
        std::copy_backward(p, end() - 2, end() - 1);
        *p = v;
    }
    return p;
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::insert(iterator p, size_type n, value_type const & v)
{
    difference_type pos = p - begin();
    size_type new_size = size() + n;
    if(new_size >= capacity_)
    {
        pointer new_data = reserve_raw(new_size);
        std::uninitialized_copy(begin(), p, new_data);
        std::uninitialized_fill(new_data + pos, new_data + pos + n, v);
        std::uninitialized_copy(p, end(), new_data + pos + n);
        deallocate(data_, size_);
        capacity_ = new_size;
        data_ = new_data;
    }
    else if(pos + n >= size_)
    {
        size_type diff = pos + n - size_;
        std::uninitialized_copy(p, end(), end() + diff);
        std::uninitialized_fill(end(), end() + diff, v);
        std::fill(p, end(), v);
    }
    else
    {
        size_type diff = size_ - (pos + n);
        std::uninitialized_copy(end() - n, end(), end());
        std::copy_backward(p, p + diff, end());
        std::fill(p, p + n, v);
    }
    size_ = new_size;
    return begin() + pos;
}

template <class T, class Alloc>
template <class InputIterator>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator iend)
{
    difference_type n = iend - i;
    difference_type pos = p - begin();
    size_type new_size = size() + n;
    if(new_size >= capacity_)
    {
        pointer new_data = reserve_raw(new_size);
        std::uninitialized_copy(begin(), p, new_data);
        std::uninitialized_copy(i, iend, new_data + pos);
        std::uninitialized_copy(p, end(), new_data + pos + n);
        std::deallocate(data_, size_);
        capacity_ = new_size;
        data_ = new_data;
    }
    else if(pos + n >= size_)
    {
        size_type diff = pos + n - size_;
        std::uninitialized_copy(p, end(), end() + diff);
        std::uninitialized_copy(iend - diff, iend, end());
        std::copy(i, iend - diff, p);
    }
    else
    {
        size_type diff = size_ - (pos + n);
        std::uninitialized_copy(end() - n, end(), end());
        std::copy_backward(p, p + diff, end());
        std::copy(i, iend, p);
    }
    size_ = new_size;
    return begin() + pos;
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::erase(iterator p)
{
    std::copy(p+1, end(), p);
    pop_back();
    return p;
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::erase(iterator p, iterator q)
{
    std::copy(q, end(), p);
    size_type eraseCount = q - p;
    detail::destroy_n(end() - eraseCount, eraseCount);
    size_ -= eraseCount;
    return p;
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::reserve( size_type new_capacity )
{
    if(new_capacity <= capacity_)
        return;
    pointer new_data = reserve_raw(new_capacity);
    if(size_ > 0)
        std::uninitialized_copy(data_, data_+size_, new_data);
    deallocate(data_, size_);
    data_ = new_data;
    capacity_ = new_capacity;
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::reserve()
{
    if(size_ == capacity_)
        reserve(2*capacity_);
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::resize( size_type new_size, value_type const & initial)
{
    if(new_size < size_)
        erase(begin() + new_size, end());
    else if(size_ < new_size)
    {
        insert(end(), new_size - size(), initial);
    }
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::swap(this_type & rhs)
{
    std::swap(size_, rhs.size_);
    std::swap(capacity_, rhs.capacity_);
    std::swap(data_, rhs.data_);
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::deallocate(pointer data, size_type size)
{
    if(data)
    {
        detail::destroy_n(data, size);
        alloc_.deallocate(data, size);
    }
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::pointer
ArrayVector<T, Alloc>::reserve_raw(size_type capacity)
{
    pointer data = 0;
    if(capacity)
    {
        data = alloc_.allocate(capacity);
    }
    return data;
}

} // namespace vigra

#endif /* VIGRA_ARRAY_VECTOR_HXX */
<commit_msg>added reverse iterator interface<commit_after>/************************************************************************/
/*                                                                      */
/*               Copyright 2002-2003 by Ullrich Koethe                  */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    You may use, modify, and distribute this software according       */
/*    to the terms stated in the LICENSE file included in               */
/*    the VIGRA distribution.                                           */
/*                                                                      */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        koethe@informatik.uni-hamburg.de                              */
/*                                                                      */
/*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
/*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_ARRAY_VECTOR_HXX
#define VIGRA_ARRAY_VECTOR_HXX

#include <memory>
#include <algorithm>
#include <vigra/memory.hxx>

namespace vigra
{

template <class T, class Alloc = std::allocator<T> >
class ArrayVector
{
    typedef ArrayVector<T, Alloc> this_type;

public:
    typedef T value_type;
    typedef value_type & reference;
    typedef value_type const & const_reference;
    typedef value_type * pointer;
    typedef value_type const * const_pointer;
    typedef value_type * iterator;
    typedef value_type const * const_iterator;
    typedef unsigned int size_type;
    typedef int          difference_type;
    typedef Alloc        allocator_type;
    typedef std::reverse_iterator<iterator> reverse_iterator;
    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

public:
    ArrayVector();

    explicit ArrayVector(Alloc const & alloc);

    explicit ArrayVector( size_type size, Alloc const & alloc = Alloc());

    ArrayVector( size_type size, value_type const & initial, Alloc const & alloc = Alloc());

    ArrayVector( this_type const & rhs );

    template <class InputIterator>
    ArrayVector(InputIterator i, InputIterator end);

    template <class InputIterator>
    ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc);

    this_type & operator=( this_type const & rhs );

    ~ArrayVector();

    inline const_pointer data() const
    {
        return data_;
    }

    inline pointer data()
    {
        return data_;
    }

    inline const_iterator begin() const
    {
        return data();
    }

    inline iterator begin()
    {
        return data();
    }

    inline const_iterator end() const
    {
        return data() + size();
    }

    inline iterator end()
    {
        return data() + size();
    }

    inline reverse_iterator rbegin()
    {
        return (reverse_iterator(end()));
    }

    inline const_reverse_iterator rbegin() const
    {
        return (const_reverse_iterator(end()));
    }

    inline reverse_iterator rend()
    {
        return (reverse_iterator(begin()));
    }

    inline const_reverse_iterator rend() const
    {
        return (const_reverse_iterator(begin()));
    }

    reference front()
    {
        return *data_;
    }

    const_reference front() const
    {
        return *data_;
    }

    reference back()
    {
        return data_[size_-1];
    }

    const_reference back() const
    {
        return data_[size_-1];
    }

    reference operator[]( size_type i )
    {
        return data()[i];
    }

    const_reference operator[]( size_type i ) const
    {
        return data()[i];
    }

    void pop_back();

    void push_back( value_type const & t );

    iterator insert(iterator p, value_type const & v);

    iterator insert(iterator p, size_type n, value_type const & v);

    template <class InputIterator>
    iterator insert(iterator p, InputIterator i, InputIterator iend);

    iterator erase(iterator p);

    iterator erase(iterator p, iterator q);

    void clear();

    void reserve( size_type new_capacity );

    void reserve();

    void resize( size_type new_size, value_type const & initial );

    void resize( size_type new_size )
    {
        resize(new_size, value_type());
    }

    bool empty() const
    {
        return size_ == 0;
    }

    size_type size() const
    {
        return size_;
    }

    size_type capacity() const
    {
        return capacity_;
    }

    void swap(this_type & rhs);

  private:

    void deallocate(pointer data, size_type size);

    pointer reserve_raw(size_type capacity);

    Alloc alloc_;
    size_type size_, capacity_;
    pointer data_;
};

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector()
: alloc_(Alloc()),
  size_(0),
  capacity_(5),
  data_(reserve_raw(5))
{}

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector(Alloc const & alloc)
: alloc_(alloc),
  size_(0),
  capacity_(5),
  data_(reserve_raw(5))
{}

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector( size_type size, Alloc const & alloc)
: alloc_(alloc),
  size_(size),
  capacity_(size),
  data_(reserve_raw(size))
{
    if(size_ > 0)
        std::uninitialized_fill(data_, data_+size_, value_type());
}

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector( size_type size,
                         value_type const & initial, Alloc const & alloc)
: alloc_(alloc),
  size_(size),
  capacity_(size),
  data_(reserve_raw(size))
{
    if(size_ > 0)
        std::uninitialized_fill(data_, data_+size_, initial);
}

template <class T, class Alloc>
ArrayVector<T, Alloc>::ArrayVector( this_type const & rhs )
: alloc_(rhs.alloc_),
  size_(rhs.size_),
  capacity_(rhs.capacity_),
  data_(reserve_raw(rhs.capacity_))
{
    if(size_ > 0)
        std::uninitialized_copy(rhs.data_, rhs.data_+size_, data_);
}

template <class T, class Alloc>
template <class InputIterator>
ArrayVector<T, Alloc>::ArrayVector(InputIterator i, InputIterator end)
: alloc_(),
  size_(std::distance(i, end)),
  capacity_(size_),
  data_(reserve_raw(size_))
{
    std::uninitialized_copy(i, end, data_);
}

template <class T, class Alloc>
template <class InputIterator>
ArrayVector<T, Alloc>::ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc)
: alloc_(alloc),
  size_(std::distance(i, end)),
  capacity_(size_),
  data_(reserve_raw(size_))
{
    std::uninitialized_copy(i, end, data_);
}

template <class T, class Alloc>
ArrayVector<T, Alloc> & ArrayVector<T, Alloc>::operator=( this_type const & rhs )
{
    if(this == &rhs)
        return *this;
    ArrayVector new_vector(rhs);
    swap(new_vector);
    return *this;
}

template <class T, class Alloc>
ArrayVector<T, Alloc>::~ArrayVector()
{
    deallocate(data_, size_);
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::pop_back()
{
    --size_;
    alloc_.destroy(data_ + size_);
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::push_back( value_type const & t )
{
    reserve();
    alloc_.construct(data_ + size_, t);
    ++size_;
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::clear()
{
    detail::destroy_n(data_, size_);
    size_ = 0;
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::insert(iterator p, value_type const & v)
{
    difference_type pos = p - begin();
    if(p == end())
    {
        push_back(v);
        p = begin() + pos;
    }
    else
    {
        push_back(back());
        p = begin() + pos;
        std::copy_backward(p, end() - 2, end() - 1);
        *p = v;
    }
    return p;
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::insert(iterator p, size_type n, value_type const & v)
{
    difference_type pos = p - begin();
    size_type new_size = size() + n;
    if(new_size >= capacity_)
    {
        pointer new_data = reserve_raw(new_size);
        std::uninitialized_copy(begin(), p, new_data);
        std::uninitialized_fill(new_data + pos, new_data + pos + n, v);
        std::uninitialized_copy(p, end(), new_data + pos + n);
        deallocate(data_, size_);
        capacity_ = new_size;
        data_ = new_data;
    }
    else if(pos + n >= size_)
    {
        size_type diff = pos + n - size_;
        std::uninitialized_copy(p, end(), end() + diff);
        std::uninitialized_fill(end(), end() + diff, v);
        std::fill(p, end(), v);
    }
    else
    {
        size_type diff = size_ - (pos + n);
        std::uninitialized_copy(end() - n, end(), end());
        std::copy_backward(p, p + diff, end());
        std::fill(p, p + n, v);
    }
    size_ = new_size;
    return begin() + pos;
}

template <class T, class Alloc>
template <class InputIterator>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator iend)
{
    difference_type n = iend - i;
    difference_type pos = p - begin();
    size_type new_size = size() + n;
    if(new_size >= capacity_)
    {
        pointer new_data = reserve_raw(new_size);
        std::uninitialized_copy(begin(), p, new_data);
        std::uninitialized_copy(i, iend, new_data + pos);
        std::uninitialized_copy(p, end(), new_data + pos + n);
        std::deallocate(data_, size_);
        capacity_ = new_size;
        data_ = new_data;
    }
    else if(pos + n >= size_)
    {
        size_type diff = pos + n - size_;
        std::uninitialized_copy(p, end(), end() + diff);
        std::uninitialized_copy(iend - diff, iend, end());
        std::copy(i, iend - diff, p);
    }
    else
    {
        size_type diff = size_ - (pos + n);
        std::uninitialized_copy(end() - n, end(), end());
        std::copy_backward(p, p + diff, end());
        std::copy(i, iend, p);
    }
    size_ = new_size;
    return begin() + pos;
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::erase(iterator p)
{
    std::copy(p+1, end(), p);
    pop_back();
    return p;
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::erase(iterator p, iterator q)
{
    std::copy(q, end(), p);
    size_type eraseCount = q - p;
    detail::destroy_n(end() - eraseCount, eraseCount);
    size_ -= eraseCount;
    return p;
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::reserve( size_type new_capacity )
{
    if(new_capacity <= capacity_)
        return;
    pointer new_data = reserve_raw(new_capacity);
    if(size_ > 0)
        std::uninitialized_copy(data_, data_+size_, new_data);
    deallocate(data_, size_);
    data_ = new_data;
    capacity_ = new_capacity;
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::reserve()
{
    if(size_ == capacity_)
        reserve(2*capacity_);
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::resize( size_type new_size, value_type const & initial)
{
    if(new_size < size_)
        erase(begin() + new_size, end());
    else if(size_ < new_size)
    {
        insert(end(), new_size - size(), initial);
    }
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::swap(this_type & rhs)
{
    std::swap(size_, rhs.size_);
    std::swap(capacity_, rhs.capacity_);
    std::swap(data_, rhs.data_);
}

template <class T, class Alloc>
void ArrayVector<T, Alloc>::deallocate(pointer data, size_type size)
{
    if(data)
    {
        detail::destroy_n(data, size);
        alloc_.deallocate(data, size);
    }
}

template <class T, class Alloc>
typename ArrayVector<T, Alloc>::pointer
ArrayVector<T, Alloc>::reserve_raw(size_type capacity)
{
    pointer data = 0;
    if(capacity)
    {
        data = alloc_.allocate(capacity);
    }
    return data;
}

} // namespace vigra

#endif /* VIGRA_ARRAY_VECTOR_HXX */
<|endoftext|>


<commit_before>#include <iostream>
#include <typeinfo>
#include <string>

#include "listize.hpp"
#include "to_string.hpp"
#include "context.hpp"
#include "backtrace.hpp"
#include "error_handling.hpp"

namespace Sass {

  Listize::Listize(Context& ctx)
  : ctx(ctx)
  {  }

  Expression* Listize::operator()(Selector_List* sel)
  {
    List* l = SASS_MEMORY_NEW(ctx.mem, List, sel->pstate(), sel->length(), SASS_COMMA);
    for (size_t i = 0, L = sel->length(); i < L; ++i) {
      if (!(*sel)[i]) continue;
      *l << (*sel)[i]->perform(this);
    }
    return l;
  }

  Expression* Listize::operator()(Compound_Selector* sel)
  {
    To_String to_string;
    std::string str;
    for (size_t i = 0, L = sel->length(); i < L; ++i) {
      Expression* e = (*sel)[i]->perform(this);
      if (e) str += e->perform(&to_string);
    }
    return SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), str);
  }

  Expression* Listize::operator()(Complex_Selector* sel)
  {
    List* l = SASS_MEMORY_NEW(ctx.mem, List, sel->pstate(), 2);

    Compound_Selector* head = sel->head();
    if (head && !head->is_empty_reference())
    {
      Expression* hh = head->perform(this);
      if (hh) *l << hh;
    }

    To_String to_string;
    std::string reference = ! sel->reference() ? ""
      : sel->reference()->perform(&to_string);
    switch(sel->combinator())
    {
      case Complex_Selector::PARENT_OF:
        *l << SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), ">");
      break;
      case Complex_Selector::ADJACENT_TO:
        *l << SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), "+");
      break;
      case Complex_Selector::REFERENCE:
        *l << SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), "/" + reference + "/");
      break;
      case Complex_Selector::PRECEDES:
        *l << SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), "~");
      break;
      case Complex_Selector::ANCESTOR_OF:
      break;
    }

    Complex_Selector* tail = sel->tail();
    if (tail)
    {
      Expression* tt = tail->perform(this);
      if (tt && tt->concrete_type() == Expression::LIST)
      { *l += static_cast<List*>(tt); }
      else if (tt) *l << static_cast<List*>(tt);
    }
    if (l->length() == 0) return 0;
    return l;
  }

  Expression* Listize::fallback_impl(AST_Node* n)
  {
    return dynamic_cast<Expression*>(n);
  }

}
<commit_msg>selector-unify should return null instead of an empty list<commit_after>#include <iostream>
#include <typeinfo>
#include <string>

#include "listize.hpp"
#include "to_string.hpp"
#include "context.hpp"
#include "backtrace.hpp"
#include "error_handling.hpp"

namespace Sass {

  Listize::Listize(Context& ctx)
  : ctx(ctx)
  {  }

  Expression* Listize::operator()(Selector_List* sel)
  {
    List* l = SASS_MEMORY_NEW(ctx.mem, List, sel->pstate(), sel->length(), SASS_COMMA);
    for (size_t i = 0, L = sel->length(); i < L; ++i) {
      if (!(*sel)[i]) continue;
      *l << (*sel)[i]->perform(this);
    }
    if (l->length()) return l;
    return SASS_MEMORY_NEW(ctx.mem, Null, l->pstate());
  }

  Expression* Listize::operator()(Compound_Selector* sel)
  {
    To_String to_string;
    std::string str;
    for (size_t i = 0, L = sel->length(); i < L; ++i) {
      Expression* e = (*sel)[i]->perform(this);
      if (e) str += e->perform(&to_string);
    }
    return SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), str);
  }

  Expression* Listize::operator()(Complex_Selector* sel)
  {
    List* l = SASS_MEMORY_NEW(ctx.mem, List, sel->pstate(), 2);

    Compound_Selector* head = sel->head();
    if (head && !head->is_empty_reference())
    {
      Expression* hh = head->perform(this);
      if (hh) *l << hh;
    }

    To_String to_string;
    std::string reference = ! sel->reference() ? ""
      : sel->reference()->perform(&to_string);
    switch(sel->combinator())
    {
      case Complex_Selector::PARENT_OF:
        *l << SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), ">");
      break;
      case Complex_Selector::ADJACENT_TO:
        *l << SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), "+");
      break;
      case Complex_Selector::REFERENCE:
        *l << SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), "/" + reference + "/");
      break;
      case Complex_Selector::PRECEDES:
        *l << SASS_MEMORY_NEW(ctx.mem, String_Quoted, sel->pstate(), "~");
      break;
      case Complex_Selector::ANCESTOR_OF:
      break;
    }

    Complex_Selector* tail = sel->tail();
    if (tail)
    {
      Expression* tt = tail->perform(this);
      if (tt && tt->concrete_type() == Expression::LIST)
      { *l += static_cast<List*>(tt); }
      else if (tt) *l << static_cast<List*>(tt);
    }
    if (l->length() == 0) return 0;
    return l;
  }

  Expression* Listize::fallback_impl(AST_Node* n)
  {
    return dynamic_cast<Expression*>(n);
  }

}
<|endoftext|>


<commit_before>/* This file is part of Zanshin Todo.

   Copyright 2011 Kevin Ottens <ervin@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
   USA.
*/

#include "zanshinrunner.h"

#include <KDE/Akonadi/CollectionFetchJob>
#include <KDE/Akonadi/CollectionFetchScope>
#include <KDE/Akonadi/Item>
#include <KDE/Akonadi/ItemCreateJob>

#include <KDE/KCalCore/Todo>

#include <KDE/KDebug>
#include <KDE/KIcon>
#include <KDE/KLocale>

ZanshinRunner::ZanshinRunner(QObject *parent, const QVariantList &args)
    : Plasma::AbstractRunner(parent, args)
{
    setObjectName(QLatin1String("Zanshin"));
    setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File |
                    Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Help);

    connect(this, SIGNAL(prepare()), this, SLOT(prep()));
    connect(this, SIGNAL(teardown()), this, SLOT(down()));
}

ZanshinRunner::~ZanshinRunner()
{
}

void ZanshinRunner::match(Plasma::RunnerContext &context)
{
    const QString command = context.query().trimmed();

    if (!command.startsWith("todo:", Qt::CaseInsensitive)) {
        return;
    }

    const QString summary = command.mid(5).trimmed();

    if (summary.isEmpty()) {
        return;
    }

    QList<Plasma::QueryMatch> matches;

    Plasma::QueryMatch match(this);
    match.setData(summary);
    match.setType(Plasma::QueryMatch::ExactMatch);
    match.setIcon(KIcon("office-calendar"));
    match.setText(i18n("Add \"%1\" to your todo list", summary));
    match.setRelevance(1.0);

    matches << match;
    context.addMatches(context.query(), matches);
}

void ZanshinRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
{
    Q_UNUSED(context)

    Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(),
                                                                       Akonadi::CollectionFetchJob::Recursive);
    job->fetchScope().setContentMimeTypes(QStringList() << "application/x-vnd.akonadi.calendar.todo");
    job->exec();

    Akonadi::Collection::List cols = job->collections();

    if (cols.isEmpty()) {
        return;
    }

    Akonadi::Collection collection;

    KConfig zanshin("zanshinrc");
    KConfigGroup config(&zanshin, "General");

    qint64 defaultCollectionId = config.readEntry("defaultCollection", -1);

    if (defaultCollectionId > 0) {
        foreach (Akonadi::Collection col, cols) {
            if (col.id() == defaultCollectionId) {
                collection = col;
                break;
            }
        }
    }

    if (!collection.isValid()) {
        collection = cols.first();
    }

    KCalCore::Todo::Ptr todo(new KCalCore::Todo);
    todo->setSummary(match.data().toString());

    Akonadi::Item item;
    item.setMimeType("application/x-vnd.akonadi.calendar.todo");
    item.setPayload<KCalCore::Todo::Ptr>(todo);

    new Akonadi::ItemCreateJob(item, collection);
}

#include "zanshinrunner.moc"
<commit_msg>remove some boilerplate<commit_after>/* This file is part of Zanshin Todo.

   Copyright 2011 Kevin Ottens <ervin@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
   USA.
*/

#include "zanshinrunner.h"

#include <KDE/Akonadi/CollectionFetchJob>
#include <KDE/Akonadi/CollectionFetchScope>
#include <KDE/Akonadi/Item>
#include <KDE/Akonadi/ItemCreateJob>

#include <KDE/KCalCore/Todo>

#include <KDE/KDebug>
#include <KDE/KIcon>
#include <KDE/KLocale>

ZanshinRunner::ZanshinRunner(QObject *parent, const QVariantList &args)
    : Plasma::AbstractRunner(parent, args)
{
    setObjectName(QLatin1String("Zanshin"));
    setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File |
                    Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Help);
}

ZanshinRunner::~ZanshinRunner()
{
}

void ZanshinRunner::match(Plasma::RunnerContext &context)
{
    const QString command = context.query().trimmed();

    if (!command.startsWith("todo:", Qt::CaseInsensitive)) {
        return;
    }

    const QString summary = command.mid(5).trimmed();

    if (summary.isEmpty()) {
        return;
    }

    QList<Plasma::QueryMatch> matches;

    Plasma::QueryMatch match(this);
    match.setData(summary);
    match.setType(Plasma::QueryMatch::ExactMatch);
    match.setIcon(KIcon("office-calendar"));
    match.setText(i18n("Add \"%1\" to your todo list", summary));
    match.setRelevance(1.0);

    matches << match;
    context.addMatches(context.query(), matches);
}

void ZanshinRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
{
    Q_UNUSED(context)

    Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(),
                                                                       Akonadi::CollectionFetchJob::Recursive);
    job->fetchScope().setContentMimeTypes(QStringList() << "application/x-vnd.akonadi.calendar.todo");
    job->exec();

    Akonadi::Collection::List cols = job->collections();

    if (cols.isEmpty()) {
        return;
    }

    Akonadi::Collection collection;

    KConfig zanshin("zanshinrc");
    KConfigGroup config(&zanshin, "General");

    qint64 defaultCollectionId = config.readEntry("defaultCollection", -1);

    if (defaultCollectionId > 0) {
        foreach (Akonadi::Collection col, cols) {
            if (col.id() == defaultCollectionId) {
                collection = col;
                break;
            }
        }
    }

    if (!collection.isValid()) {
        collection = cols.first();
    }

    KCalCore::Todo::Ptr todo(new KCalCore::Todo);
    todo->setSummary(match.data().toString());

    Akonadi::Item item;
    item.setMimeType("application/x-vnd.akonadi.calendar.todo");
    item.setPayload<KCalCore::Todo::Ptr>(todo);

    new Akonadi::ItemCreateJob(item, collection);
}

#include "zanshinrunner.moc"
<|endoftext|>


<commit_before>/** \file
 * Implements a load recorder, useful for simulating loads to test
 * CPU clock daemons and settings.
 */

#include "Options.hpp"

#include "types.hpp"
#include "constants.hpp"
#include "errors.hpp"
#include "utility.hpp"
#include "clas.hpp"
#include "version.hpp"

#include "sys/sysctl.hpp"

#include <iostream>  /* std::cout, std::cerr */
#include <fstream>   /* std::ofstream */
#include <chrono>    /* std::chrono::steady_clock::now() */
#include <thread>    /* std::this_thread::sleep_until() */
#include <memory>    /* std::unique_ptr */

#include <sys/resource.h>  /* CPUSTATES */

/**
 * File local scope.
 */
namespace {

using nih::Option;
using nih::make_Options;

using constants::ACLINE;
using constants::FREQ;
using constants::FREQ_LEVELS;
using constants::CP_TIMES;

using types::ms;
using types::coreid_t;
using types::cptime_t;
using types::mhz_t;

using errors::Exit;
using errors::Exception;
using errors::fail;

using utility::to_value;
using utility::sprintf_safe;
using namespace utility::literals;

using clas::ival;

using sys::ctl::make_Sysctl;
using sys::ctl::make_Once;

using version::LOADREC_FEATURES;
using version::flag_t;
using namespace version::literals;

/**
 * The set of supported features.
 *
 * This value is stored in load recordings to allow loadplay to correctly
 * interpret the data.
 */
constexpr flag_t const FEATURES{
	0_FREQ_TRACKING
};

/**
 * The global state.
 */
struct {
	bool verbose{false};  /**< Verbosity flag. */
	ms duration{30000};   /**< Recording duration in ms. */
	ms interval{25};      /**< Recording sample interval in ms. */

	/**
	 * The output file stream to use if an outfilename is provided
	 * on the CLI.
	 */
	std::ofstream outfile{};

	/**
	 * A pointer to the stream to use for output, either std::cout
	 * or outfile.
	 */
	std::ostream * out = &std::cout;

	/**
	 * The user provided output file name.
	 */
	char const * outfilename{nullptr};

	/**
	 * The number of CPU cores/threads.
	 */
	sys::ctl::SysctlOnce<coreid_t, 2> const ncpu{1U, {CTL_HW, HW_NCPU}};
} g;

/**
 * An enum for command line parsing.
 */
enum class OE {
	USAGE,           /**< Print help */
	IVAL_DURATION,   /**< Set the duration of the recording */
	IVAL_POLL,       /**< Set polling interval */
	FILE_OUTPUT,     /**< Set output file */
	FILE_PID,        /**< Set PID file */
	FLAG_VERBOSE,    /**< Verbose output on stderr */
	OPT_UNKNOWN,     /**< Obligatory */
	OPT_NOOPT,       /**< Obligatory */
	OPT_DASH,        /**< Obligatory */
	OPT_LDASH,       /**< Obligatory */
	OPT_DONE         /**< Obligatory */
};

/**
 * The short usage string.
 */
char const * const USAGE = "[-hv] [-d ival] [-p ival] [-o file]";

/**
 * Definitions of command line options.
 */
Option<OE> const OPTIONS[]{
	{OE::USAGE,         'h', "help",     "",     "Show usage and exit"},
	{OE::FLAG_VERBOSE,  'v', "verbose",  "",     "Be verbose"},
	{OE::IVAL_DURATION, 'd', "duration", "ival", "The duration of the recording"},
	{OE::IVAL_POLL,     'p', "poll",     "ival", "The polling interval"},
	{OE::FILE_OUTPUT,   'o', "output",   "file", "Output to file"},
	{OE::FILE_PID,      'P', "pid",      "file", "Ignored"},
};

/**
 * Outputs the given message on stderr if g.verbose is set.
 *
 * @param msg
 *	The message to output
 */
inline void verbose(std::string const & msg) {
	if (g.verbose) {
		std::cerr << "loadrec: " << msg << '\n';
	}
}

/**
 * Set up output to the given file.
 */
void init() {
	if (g.outfilename) {
		g.outfile.open(g.outfilename);
		if (!g.outfile.good()) {
			fail(Exit::EWOPEN, errno,
			     "could not open file for writing: "_s + g.outfilename);
		}
		g.out = &g.outfile;
	}
}

/**
 * Parse command line arguments.
 *
 * @param argc,argv
 *	The command line arguments
 */
void read_args(int const argc, char const * const argv[]) {
	auto getopt = make_Options(argc, argv, USAGE, OPTIONS);

	while (true) switch (getopt()) {
	case OE::USAGE:
		std::cerr << getopt.usage();
		throw Exception{Exit::OK, 0, ""};
	case OE::FLAG_VERBOSE:
		g.verbose = true;
		break;
	case OE::IVAL_DURATION:
		g.duration = ival(getopt[1]);
		break;
	case OE::IVAL_POLL:
		g.interval = ival(getopt[1]);
		break;
	case OE::FILE_OUTPUT:
		g.outfilename = getopt[1];
		break;
	case OE::FILE_PID:
		break;
	case OE::OPT_UNKNOWN:
	case OE::OPT_NOOPT:
	case OE::OPT_DASH:
	case OE::OPT_LDASH:
		fail(Exit::ECLARG, 0, "unexpected command line argument: "_s +
		                      getopt[0] + "\n\n" + getopt.usage());
	case OE::OPT_DONE:
		return;
	}
}

/**
 * Print the sysctls
 */
void print_sysctls() {
	sys::ctl::Sysctl<> hw_acpi_acline;
	try {
		hw_acpi_acline = {ACLINE};
	} catch (sys::sc_error<sys::ctl::error>) {
		verbose("cannot read "_s + ACLINE);
	}
	*g.out << "%s=%ld\n"_fmt(LOADREC_FEATURES, FEATURES)
	       << "hw.machine=" << make_Sysctl(CTL_HW, HW_MACHINE).get<char>().get() << '\n'
	       << "hw.model=" << make_Sysctl(CTL_HW, HW_MODEL).get<char>().get() << '\n'
	       << "hw.ncpu=" << g.ncpu << '\n'
	       << ACLINE << '=' << make_Once(1U, hw_acpi_acline) << '\n';

	char mibname[40];
	for (coreid_t i = 0; i < g.ncpu; ++i) {
		sprintf_safe(mibname, FREQ, i);
		try {
			sys::ctl::Sysctl<> ctl{mibname};
			*g.out << mibname << '='
			       << make_Once(0, ctl) << '\n';
		} catch (sys::sc_error<sys::ctl::error> e) {
			verbose("cannot access sysctl: "_s + mibname);
			if (i == 0) {
				fail(Exit::ENOFREQ, e,
				     "at least the first CPU core must report its clock frequency");
			}
		}
		sprintf_safe(mibname, FREQ_LEVELS, i);
		try {
			sys::ctl::Sysctl<> ctl{mibname};
			*g.out << mibname << '='
			       << ctl.get<char>().get() << '\n';
		} catch (sys::sc_error<sys::ctl::error>) {
			/* do nada */
		}
	}
}

/**
 * Report the load frames.
 *
 * This prints the time in ms since the last frame and the cp_times
 * growth as a space separated list.
 */
void run() try {
	/*
	 * Setup cptimes buffer for two samples.
	 */
	sys::ctl::Sysctl<> const cp_times_ctl = {CP_TIMES};

	auto const columns = cp_times_ctl.size() / sizeof(cptime_t);
	auto cp_times = std::unique_ptr<cptime_t[]>(
	    new cptime_t[2 * columns]{});

	/*
	 * Setup clock frequency sources for each core.
	 */
	coreid_t const cores = columns / CPUSTATES;
	auto corefreqs = std::unique_ptr<sys::ctl::Sync<mhz_t, sys::ctl::Sysctl<>>[]>(
	    new sys::ctl::Sync<mhz_t, sys::ctl::Sysctl<>>[cores]{});

	for (coreid_t i = 0; i < cores; ++i) {
		char mibname[40];
		sprintf_safe(mibname, FREQ, i);
		try {
			corefreqs[i] = sys::ctl::Sysctl<>{mibname};
		} catch (sys::sc_error<sys::ctl::error> e) {
			if (i == 0) {
				fail(Exit::ENOFREQ, e,
				     "at least the first CPU core must report its clock frequency");
			}
			/* Fall back to previous clock provider. */
			corefreqs[i] = corefreqs[i - 1];
		}
	}

	/*
	 * Record `cptimes * freq` in order to get an absolute measure of
	 * the load.
	 */
	auto time = std::chrono::steady_clock::now();
	auto last = time;
	auto const stop = time + g.duration;
	size_t sample = 0;
	/* Takes a sample and prints it, avoids duplicating code
	 * behind the loop. */
	auto const takeAndPrintSample = [&]() {
		cp_times_ctl.get(&cp_times[sample * columns],
		                 sizeof(cptime_t) * columns);
		*g.out << std::chrono::duration_cast<ms>(time - last).count();
		mhz_t freq = 1;
		for (int i = 0; i < columns; ++i) {
			if (i % CPUSTATES == 0) {
				freq = corefreqs[i / CPUSTATES];
			}
			*g.out << ' '
			       << freq * (cp_times[sample * columns + i] -
			                  cp_times[((sample + 1) % 2) * columns + i]);
		}
	};
	while (time < stop) {
		takeAndPrintSample();
		*g.out << '\n';
		sample = (sample + 1) % 2;
		last = time;
		std::this_thread::sleep_until(time += g.interval);
	}
	takeAndPrintSample();
	*g.out << std::endl;
} catch (sys::sc_error<sys::ctl::error> e) {
	fail(Exit::ESYSCTL, e, "failed to access sysctl: "_s + CP_TIMES);
}

} /* namespace */

/**
 * Main routine, setup and execute daemon, print errors.
 *
 * @param argc,argv
 *	The command line arguments
 * @return
 *	An exit code
 * @see Exit
 */
int main(int argc, char * argv[]) {
	try {
		read_args(argc, argv);
		init();
		print_sysctls();
		run();
	} catch (Exception & e) {
		if (e.msg != "") {
			std::cerr << "loadrec: " << e.msg << '\n';
		}
		return to_value(e.exitcode);
	} catch (sys::sc_error<sys::ctl::error> e) {
		std::cerr << "loadrec: untreated sysctl failure: " << e.c_str() << '\n';
		throw;
	} catch (...) {
		std::cerr << "loadrec: untreated failure\n";
		throw;
	}
}

<commit_msg>Add support for clock frequency recording<commit_after>/** \file
 * Implements a load recorder, useful for simulating loads to test
 * CPU clock daemons and settings.
 */

#include "Options.hpp"

#include "types.hpp"
#include "constants.hpp"
#include "errors.hpp"
#include "utility.hpp"
#include "clas.hpp"
#include "version.hpp"

#include "sys/sysctl.hpp"

#include <iostream>  /* std::cout, std::cerr */
#include <fstream>   /* std::ofstream */
#include <chrono>    /* std::chrono::steady_clock::now() */
#include <thread>    /* std::this_thread::sleep_until() */
#include <memory>    /* std::unique_ptr */

#include <sys/resource.h>  /* CPUSTATES */

/**
 * File local scope.
 */
namespace {

using nih::Option;
using nih::make_Options;

using constants::ACLINE;
using constants::FREQ;
using constants::FREQ_LEVELS;
using constants::CP_TIMES;

using types::ms;
using types::coreid_t;
using types::cptime_t;
using types::mhz_t;

using errors::Exit;
using errors::Exception;
using errors::fail;

using utility::to_value;
using utility::sprintf_safe;
using namespace utility::literals;

using clas::ival;

using sys::ctl::make_Sysctl;
using sys::ctl::make_Once;

using version::LOADREC_FEATURES;
using version::flag_t;
using namespace version::literals;

/**
 * The set of supported features.
 *
 * This value is stored in load recordings to allow loadplay to correctly
 * interpret the data.
 */
constexpr flag_t const FEATURES{
	1_FREQ_TRACKING
};

/**
 * The global state.
 */
struct {
	bool verbose{false};  /**< Verbosity flag. */
	ms duration{30000};   /**< Recording duration in ms. */
	ms interval{25};      /**< Recording sample interval in ms. */

	/**
	 * The output file stream to use if an outfilename is provided
	 * on the CLI.
	 */
	std::ofstream outfile{};

	/**
	 * A pointer to the stream to use for output, either std::cout
	 * or outfile.
	 */
	std::ostream * out = &std::cout;

	/**
	 * The user provided output file name.
	 */
	char const * outfilename{nullptr};

	/**
	 * The number of CPU cores/threads.
	 */
	sys::ctl::SysctlOnce<coreid_t, 2> const ncpu{1U, {CTL_HW, HW_NCPU}};
} g;

/**
 * An enum for command line parsing.
 */
enum class OE {
	USAGE,           /**< Print help */
	IVAL_DURATION,   /**< Set the duration of the recording */
	IVAL_POLL,       /**< Set polling interval */
	FILE_OUTPUT,     /**< Set output file */
	FILE_PID,        /**< Set PID file */
	FLAG_VERBOSE,    /**< Verbose output on stderr */
	OPT_UNKNOWN,     /**< Obligatory */
	OPT_NOOPT,       /**< Obligatory */
	OPT_DASH,        /**< Obligatory */
	OPT_LDASH,       /**< Obligatory */
	OPT_DONE         /**< Obligatory */
};

/**
 * The short usage string.
 */
char const * const USAGE = "[-hv] [-d ival] [-p ival] [-o file]";

/**
 * Definitions of command line options.
 */
Option<OE> const OPTIONS[]{
	{OE::USAGE,         'h', "help",     "",     "Show usage and exit"},
	{OE::FLAG_VERBOSE,  'v', "verbose",  "",     "Be verbose"},
	{OE::IVAL_DURATION, 'd', "duration", "ival", "The duration of the recording"},
	{OE::IVAL_POLL,     'p', "poll",     "ival", "The polling interval"},
	{OE::FILE_OUTPUT,   'o', "output",   "file", "Output to file"},
	{OE::FILE_PID,      'P', "pid",      "file", "Ignored"},
};

/**
 * Outputs the given message on stderr if g.verbose is set.
 *
 * @param msg
 *	The message to output
 */
inline void verbose(std::string const & msg) {
	if (g.verbose) {
		std::cerr << "loadrec: " << msg << '\n';
	}
}

/**
 * Set up output to the given file.
 */
void init() {
	if (g.outfilename) {
		g.outfile.open(g.outfilename);
		if (!g.outfile.good()) {
			fail(Exit::EWOPEN, errno,
			     "could not open file for writing: "_s + g.outfilename);
		}
		g.out = &g.outfile;
	}
}

/**
 * Parse command line arguments.
 *
 * @param argc,argv
 *	The command line arguments
 */
void read_args(int const argc, char const * const argv[]) {
	auto getopt = make_Options(argc, argv, USAGE, OPTIONS);

	while (true) switch (getopt()) {
	case OE::USAGE:
		std::cerr << getopt.usage();
		throw Exception{Exit::OK, 0, ""};
	case OE::FLAG_VERBOSE:
		g.verbose = true;
		break;
	case OE::IVAL_DURATION:
		g.duration = ival(getopt[1]);
		break;
	case OE::IVAL_POLL:
		g.interval = ival(getopt[1]);
		break;
	case OE::FILE_OUTPUT:
		g.outfilename = getopt[1];
		break;
	case OE::FILE_PID:
		break;
	case OE::OPT_UNKNOWN:
	case OE::OPT_NOOPT:
	case OE::OPT_DASH:
	case OE::OPT_LDASH:
		fail(Exit::ECLARG, 0, "unexpected command line argument: "_s +
		                      getopt[0] + "\n\n" + getopt.usage());
	case OE::OPT_DONE:
		return;
	}
}

/**
 * Print the sysctls
 */
void print_sysctls() {
	sys::ctl::Sysctl<> hw_acpi_acline;
	try {
		hw_acpi_acline = {ACLINE};
	} catch (sys::sc_error<sys::ctl::error>) {
		verbose("cannot read "_s + ACLINE);
	}
	*g.out << "%s=%ld\n"_fmt(LOADREC_FEATURES, FEATURES)
	       << "hw.machine=" << make_Sysctl(CTL_HW, HW_MACHINE).get<char>().get() << '\n'
	       << "hw.model=" << make_Sysctl(CTL_HW, HW_MODEL).get<char>().get() << '\n'
	       << "hw.ncpu=" << g.ncpu << '\n'
	       << ACLINE << '=' << make_Once(1U, hw_acpi_acline) << '\n';

	for (coreid_t i = 0; i < g.ncpu; ++i) {
		char mibname[40];
		sprintf_safe(mibname, FREQ, i);
		try {
			sys::ctl::Sysctl<> ctl{mibname};
			*g.out << mibname << '='
			       << make_Once(0, ctl) << '\n';
		} catch (sys::sc_error<sys::ctl::error> e) {
			verbose("cannot access sysctl: "_s + mibname);
			if (i == 0) {
				fail(Exit::ENOFREQ, e,
				     "at least the first CPU core must report its clock frequency");
			}
		}
		sprintf_safe(mibname, FREQ_LEVELS, i);
		try {
			sys::ctl::Sysctl<> ctl{mibname};
			*g.out << mibname << '='
			       << ctl.get<char>().get() << '\n';
		} catch (sys::sc_error<sys::ctl::error>) {
			/* do nada */
		}
	}
}

/**
 * Report the load frames.
 *
 * This prints the time in ms since the last frame and the cp_times
 * growth as a space separated list.
 */
void run() try {
	/*
	 * Setup cptimes buffer for two samples.
	 */
	sys::ctl::Sysctl<> const cp_times_ctl = {CP_TIMES};

	auto const columns = cp_times_ctl.size() / sizeof(cptime_t);
	auto cp_times = std::unique_ptr<cptime_t[]>(
	    new cptime_t[2 * columns]{});

	/*
	 * Setup clock frequency sources for each core.
	 */
	coreid_t const cores = columns / CPUSTATES;
	auto corefreqs = std::unique_ptr<sys::ctl::Sync<mhz_t, sys::ctl::Sysctl<>>[]>(
	    new sys::ctl::Sync<mhz_t, sys::ctl::Sysctl<>>[cores]{});

	for (coreid_t i = 0; i < cores; ++i) {
		char mibname[40];
		sprintf_safe(mibname, FREQ, i);
		try {
			corefreqs[i] = sys::ctl::Sysctl<>{mibname};
		} catch (sys::sc_error<sys::ctl::error> e) {
			if (i == 0) {
				fail(Exit::ENOFREQ, e,
				     "at least the first CPU core must report its clock frequency");
			}
			/* Fall back to previous clock provider. */
			corefreqs[i] = corefreqs[i - 1];
		}
	}

	/*
	 * Record freq and cptimes.
	 */
	auto time = std::chrono::steady_clock::now();
	auto last = time;
	auto const stop = time + g.duration;
	size_t sample = 0;
	/* Takes a sample and prints it, avoids duplicating code
	 * behind the loop. */
	auto const takeAndPrintSample = [&]() {
		cp_times_ctl.get(&cp_times[sample * columns],
		                 sizeof(cptime_t) * columns);
		*g.out << std::chrono::duration_cast<ms>(time - last).count();
		for (coreid_t i = 0; i < cores; ++i) {
			*g.out << ' ' << static_cast<mhz_t>(corefreqs[i]);
		}
		for (int i = 0; i < columns; ++i) {
			*g.out << ' '
			       << cp_times[sample * columns + i] -
			          cp_times[((sample + 1) % 2) * columns + i];
		}
	};
	while (time < stop) {
		takeAndPrintSample();
		*g.out << '\n';
		sample = (sample + 1) % 2;
		last = time;
		std::this_thread::sleep_until(time += g.interval);
	}
	takeAndPrintSample();
	*g.out << std::endl;
} catch (sys::sc_error<sys::ctl::error> e) {
	fail(Exit::ESYSCTL, e, "failed to access sysctl: "_s + CP_TIMES);
}

} /* namespace */

/**
 * Main routine, setup and execute daemon, print errors.
 *
 * @param argc,argv
 *	The command line arguments
 * @return
 *	An exit code
 * @see Exit
 */
int main(int argc, char * argv[]) {
	try {
		read_args(argc, argv);
		init();
		print_sysctls();
		run();
	} catch (Exception & e) {
		if (e.msg != "") {
			std::cerr << "loadrec: " << e.msg << '\n';
		}
		return to_value(e.exitcode);
	} catch (sys::sc_error<sys::ctl::error> e) {
		std::cerr << "loadrec: untreated sysctl failure: " << e.c_str() << '\n';
		throw;
	} catch (...) {
		std::cerr << "loadrec: untreated failure\n";
		throw;
	}
}

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/*
 *
 */

#include <string.h>
#include "common.h"
#include "SceneNode.h"
#include "ZSceneDatabase.h"
#include "SphereSceneNode.h"
#include "Octree.h"
#include "StateDatabase.h"

ZSceneDatabase::ZSceneDatabase() :
				staticCount(0),
				staticSize(0),
				staticList(NULL),
				dynamicCount(0),
				dynamicSize(0),
				dynamicList(NULL)
{
  // do nothing
}

ZSceneDatabase::~ZSceneDatabase()
{
  // free static nodes
  for (int i = 0; i < staticCount; i++) {
    delete staticList[i];
  }

  // free lists
  delete[] staticList;
  delete[] dynamicList;
}

void			ZSceneDatabase::addStaticNode(SceneNode* object)
{
  if (staticCount == staticSize) {
    if (staticSize == 0) staticSize = 15;
    else staticSize += staticSize + 1;
    SceneNode** newStatic = new SceneNode*[staticSize];
    if (staticList)
      ::memcpy(newStatic, staticList, staticCount * sizeof(SceneNode*));
    delete[] staticList;
    staticList = newStatic;
  }
  staticList[staticCount++] = object;
}

void			ZSceneDatabase::addDynamicNode(SceneNode* object)
{
  if (dynamicCount == dynamicSize) {
    if (dynamicSize == 0) dynamicSize = 15;
    else dynamicSize += dynamicSize + 1;
    SceneNode** newDynamic = new SceneNode*[dynamicSize];
    if (dynamicList)
      ::memcpy(newDynamic, dynamicList,  dynamicCount * sizeof(SceneNode*));
    delete[] dynamicList;
    dynamicList = newDynamic;
  }
  dynamicList[dynamicCount++] = object;
}

void			ZSceneDatabase::addDynamicSphere(SphereSceneNode* n)
{
  // just add sphere -- don't need to break it up for hidden surfaces
  addDynamicNode(n);
}

void			ZSceneDatabase::removeDynamicNodes()
{
  dynamicCount = 0;
}

void			ZSceneDatabase::removeAllNodes()
{
  staticCount = 0;
  dynamicCount = 0;
}

bool			ZSceneDatabase::isOrdered()
{
  return false;
}

SceneIterator*		ZSceneDatabase::getRenderIterator()
{
  return new ZSceneIterator(this);
}

//
// ZSceneIterator
//

ZSceneIterator::ZSceneIterator(const ZSceneDatabase* _db) :
				SceneIterator(), db(_db)
{
  cullDepth = BZDB.evalInt(StateDatabase::BZDB_CULLDEPTH);
  cullElements = BZDB.evalInt(StateDatabase::BZDB_CULLELEMENTS);
  octree = NULL;
  culledList = NULL;
  if (cullDepth > 0) {
    makeCuller();
  }
  else {
    culledList = db->staticList;
    culledCount = db->staticCount;
  }
  reset();
}

ZSceneIterator::~ZSceneIterator()
{
  delete octree;
  if (culledList != db->staticList) {
    delete culledList;
  }
}

void			ZSceneIterator::makeCuller()
{
  delete octree;
  octree = new Octree;
  octree->addNodes (db->staticList, db->staticCount, cullDepth, cullElements);
  if (culledList != db->staticList) {
    delete culledList;
  }
  // make scratch pad for the culler
  culledList = new (SceneNode*)[db->staticCount];
}

void			ZSceneIterator::resetFrustum(const ViewFrustum* frustum)
{
  const int currentDepth = BZDB.evalInt(StateDatabase::BZDB_CULLDEPTH);
  const int currentElements = BZDB.evalInt(StateDatabase::BZDB_CULLELEMENTS);

  if ((currentDepth != cullDepth) || (currentElements != cullElements)) {

    cullDepth = currentDepth;
    cullElements = currentElements;

    delete octree;
    octree = NULL;

    if (cullDepth > 0) {
      makeCuller();
    }
    else {
      if (culledList != db->staticList) {
        delete culledList;
      }
      culledList = db->staticList;
      culledCount = db->staticCount;
    }
  }

  // cull if we're supposed to
  if (octree) {
    culledCount = octree->getFrustumList (culledList, db->staticCount,
                                          (const Frustum *) frustum);
  }
}

void			ZSceneIterator::reset()
{
  culledIndex = 0;
  culledDone = (culledCount == culledIndex);
  dynamicIndex = 0;
  dynamicDone = (db->dynamicCount == dynamicIndex);
}

SceneNode*		ZSceneIterator::getNext()
{
  if (!culledDone) {
    SceneNode* node = culledList[culledIndex++];
    culledDone = (culledIndex >= culledCount);
    return node;
  }
  if (!dynamicDone) {
    SceneNode* node = db->dynamicList[dynamicIndex++];
    dynamicDone = (db->dynamicCount == dynamicIndex);
    return node;
  }
  return NULL;
}

// the callback function from the Culler
static void drawLines (int vertices, const float points[][3], bool partial)
{
  GLfloat defaultColor[4] = {1.0f, 0.0f, 0.0f, 0.75f};
  GLfloat partialColor[4] = {0.0f, 0.0f, 1.0f, 0.75f};

  if (partial) {
    glColor4fv (partialColor);
  } else {
    glColor4fv (defaultColor);
  }
  glBegin (GL_LINE_STRIP);
  for (int i = 0; i < vertices; i++) {
    glVertex3fv (points[i]);
  }
  glEnd ();
}

void        		ZSceneIterator::drawCuller()
{
  if (octree) {
    // setup to draw lines
    glDisable (GL_TEXTURE_2D);
    octree->draw (drawLines);
    glEnable (GL_TEXTURE_2D);
  }
  return;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>compile on vc, part 2 - someone make sure that doesn't break gcc<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/*
 *
 */

#include <string.h>
#include "common.h"
#include "SceneNode.h"
#include "ZSceneDatabase.h"
#include "SphereSceneNode.h"
#include "Octree.h"
#include "StateDatabase.h"

ZSceneDatabase::ZSceneDatabase() :
				staticCount(0),
				staticSize(0),
				staticList(NULL),
				dynamicCount(0),
				dynamicSize(0),
				dynamicList(NULL)
{
  // do nothing
}

ZSceneDatabase::~ZSceneDatabase()
{
  // free static nodes
  for (int i = 0; i < staticCount; i++) {
    delete staticList[i];
  }

  // free lists
  delete[] staticList;
  delete[] dynamicList;
}

void			ZSceneDatabase::addStaticNode(SceneNode* object)
{
  if (staticCount == staticSize) {
    if (staticSize == 0) staticSize = 15;
    else staticSize += staticSize + 1;
    SceneNode** newStatic = new SceneNode*[staticSize];
    if (staticList)
      ::memcpy(newStatic, staticList, staticCount * sizeof(SceneNode*));
    delete[] staticList;
    staticList = newStatic;
  }
  staticList[staticCount++] = object;
}

void			ZSceneDatabase::addDynamicNode(SceneNode* object)
{
  if (dynamicCount == dynamicSize) {
    if (dynamicSize == 0) dynamicSize = 15;
    else dynamicSize += dynamicSize + 1;
    SceneNode** newDynamic = new SceneNode*[dynamicSize];
    if (dynamicList)
      ::memcpy(newDynamic, dynamicList,  dynamicCount * sizeof(SceneNode*));
    delete[] dynamicList;
    dynamicList = newDynamic;
  }
  dynamicList[dynamicCount++] = object;
}

void			ZSceneDatabase::addDynamicSphere(SphereSceneNode* n)
{
  // just add sphere -- don't need to break it up for hidden surfaces
  addDynamicNode(n);
}

void			ZSceneDatabase::removeDynamicNodes()
{
  dynamicCount = 0;
}

void			ZSceneDatabase::removeAllNodes()
{
  staticCount = 0;
  dynamicCount = 0;
}

bool			ZSceneDatabase::isOrdered()
{
  return false;
}

SceneIterator*		ZSceneDatabase::getRenderIterator()
{
  return new ZSceneIterator(this);
}

//
// ZSceneIterator
//

ZSceneIterator::ZSceneIterator(const ZSceneDatabase* _db) :
				SceneIterator(), db(_db)
{
  cullDepth = BZDB.evalInt(StateDatabase::BZDB_CULLDEPTH);
  cullElements = BZDB.evalInt(StateDatabase::BZDB_CULLELEMENTS);
  octree = NULL;
  culledList = NULL;
  if (cullDepth > 0) {
    makeCuller();
  }
  else {
    culledList = db->staticList;
    culledCount = db->staticCount;
  }
  reset();
}

ZSceneIterator::~ZSceneIterator()
{
  delete octree;
  if (culledList != db->staticList) {
    delete culledList;
  }
}

void			ZSceneIterator::makeCuller()
{
  delete octree;
  octree = new Octree;
  octree->addNodes (db->staticList, db->staticCount, cullDepth, cullElements);
  if (culledList != db->staticList) {
    delete culledList;
  }
  // make scratch pad for the culler
  culledList = new SceneNode*[db->staticCount];
}

void			ZSceneIterator::resetFrustum(const ViewFrustum* frustum)
{
  const int currentDepth = BZDB.evalInt(StateDatabase::BZDB_CULLDEPTH);
  const int currentElements = BZDB.evalInt(StateDatabase::BZDB_CULLELEMENTS);

  if ((currentDepth != cullDepth) || (currentElements != cullElements)) {

    cullDepth = currentDepth;
    cullElements = currentElements;

    delete octree;
    octree = NULL;

    if (cullDepth > 0) {
      makeCuller();
    }
    else {
      if (culledList != db->staticList) {
        delete culledList;
      }
      culledList = db->staticList;
      culledCount = db->staticCount;
    }
  }

  // cull if we're supposed to
  if (octree) {
    culledCount = octree->getFrustumList (culledList, db->staticCount,
                                          (const Frustum *) frustum);
  }
}

void			ZSceneIterator::reset()
{
  culledIndex = 0;
  culledDone = (culledCount == culledIndex);
  dynamicIndex = 0;
  dynamicDone = (db->dynamicCount == dynamicIndex);
}

SceneNode*		ZSceneIterator::getNext()
{
  if (!culledDone) {
    SceneNode* node = culledList[culledIndex++];
    culledDone = (culledIndex >= culledCount);
    return node;
  }
  if (!dynamicDone) {
    SceneNode* node = db->dynamicList[dynamicIndex++];
    dynamicDone = (db->dynamicCount == dynamicIndex);
    return node;
  }
  return NULL;
}

// the callback function from the Culler
static void drawLines (int vertices, const float points[][3], bool partial)
{
  GLfloat defaultColor[4] = {1.0f, 0.0f, 0.0f, 0.75f};
  GLfloat partialColor[4] = {0.0f, 0.0f, 1.0f, 0.75f};

  if (partial) {
    glColor4fv (partialColor);
  } else {
    glColor4fv (defaultColor);
  }
  glBegin (GL_LINE_STRIP);
  for (int i = 0; i < vertices; i++) {
    glVertex3fv (points[i]);
  }
  glEnd ();
}

void        		ZSceneIterator::drawCuller()
{
  if (octree) {
    // setup to draw lines
    glDisable (GL_TEXTURE_2D);
    octree->draw (drawLines);
    glEnable (GL_TEXTURE_2D);
  }
  return;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#include "test.h"

static_MTX(mtx3, mtxErrorCheck);

static void proc3()
{
	unsigned event;

	event = mtx_take(mtx2);                      assert_timeout(event);
	event = mtx_wait(mtx3);                      assert_success(event);
	event = mtx_take(mtx3);                      assert_failure(event);
	event = mtx_give(mtx3);                      assert_success(event);
	event = mtx_give(mtx3);                      assert_failure(event);
	        tsk_stop();
}

static void proc2()
{
	unsigned event;

	event = mtx_take(mtx1);                      assert_timeout(event);
	event = mtx_wait(mtx2);                      assert_success(event);
	event = mtx_take(mtx2);                      assert_success(event);
	                                             assert_dead(tsk3);
	        tsk_startFrom(tsk3, proc3);          assert_dead(tsk3);
	event = tsk_join(tsk3);                      assert_success(event);
	event = mtx_give(mtx2);                      assert_success(event);
	event = mtx_give(mtx2);                      assert_success(event);
	        tsk_stop();
}

static void proc1()
{
	unsigned event;

	event = mtx_take(&mtx0);                     assert_timeout(event);
	event = mtx_wait(mtx1);                      assert_success(event);
	event = mtx_take(mtx1);                      assert_failure(event);
	                                             assert_dead(tsk2);
	        tsk_startFrom(tsk2, proc2);          assert_dead(tsk2);
	event = tsk_join(tsk2);                      assert_success(event);
	event = mtx_give(mtx1);                      assert_success(event);
	event = mtx_give(mtx1);                      assert_failure(event);
	        tsk_stop();
}

static void proc0()
{
	unsigned event;

	event = mtx_wait(&mtx0);                     assert_success(event);
	event = mtx_take(&mtx0);                     assert_timeout(event);
	                                             assert_dead(tsk1);
	        tsk_startFrom(tsk1, proc1);          assert_dead(tsk1);
	event = tsk_join(tsk1);                      assert_success(event);
	event = mtx_give(&mtx0);                     assert_success(event);
	event = mtx_give(&mtx0);                     assert_success(event);
	        tsk_stop();
}

static void test()
{
	unsigned event;
	                                             assert_dead(&tsk0);
	        tsk_startFrom(&tsk0, proc0);
	event = tsk_join(&tsk0);                     assert_success(event);
}

extern "C"
void test_mutex_4()
{
	TEST_Notify();
	mtx_init(&mtx0, mtxNormal, 0);
	mtx_init(mtx1, mtxErrorCheck, 0);
	mtx_init(mtx2, mtxRecursive, 0);
	TEST_Call();
}
<commit_msg>Update test_mutex_4.cpp<commit_after>#include "test.h"

static_MTX(mtx3, mtxRobust);

static void proc5()
{
	unsigned event;

	event = mtx_wait(mtx3);                      assert_owndead(event);
	event = mtx_give(mtx3);                      assert_success(event);
	        tsk_stop();
}

static void proc4()
{
	unsigned event;

	event = mtx_wait(mtx3);                      assert_success(event);
	                                             assert_dead(tsk5);
	        tsk_startFrom(tsk5, proc5);          assert_ready(tsk5);
	event = mtx_wait(mtx1);                      assert(!"test program cannot be caught here");
}

static void proc3()
{
	unsigned event;

	event = mtx_take(mtx2);                      assert_timeout(event);
	event = mtx_wait(mtx3);                      assert_success(event);
	event = mtx_take(mtx3);                      assert_timeout(event);
	                                             assert_dead(tsk4);
	        tsk_startFrom(tsk4, proc4);          assert_ready(tsk4);
	event = mtx_give(mtx3);                      assert_success(event);
	event = mtx_give(mtx3);                      assert_failure(event);
	event = tsk_kill(tsk4);                      assert_success(event);
	event = tsk_join(tsk5);                      assert_success(event);
	        tsk_stop();
}

static void proc2()
{
	unsigned event;

	event = mtx_take(mtx1);                      assert_timeout(event);
	event = mtx_wait(mtx2);                      assert_success(event);
	event = mtx_take(mtx2);                      assert_success(event);
	                                             assert_dead(tsk3);
	        tsk_startFrom(tsk3, proc3);          assert_dead(tsk3);
	event = tsk_join(tsk3);                      assert_success(event);
	event = mtx_give(mtx2);                      assert_success(event);
	event = mtx_give(mtx2);                      assert_success(event);
	        tsk_stop();
}

static void proc1()
{
	unsigned event;

	event = mtx_take(&mtx0);                     assert_timeout(event);
	event = mtx_wait(mtx1);                      assert_success(event);
	event = mtx_take(mtx1);                      assert_failure(event);
	                                             assert_dead(tsk2);
	        tsk_startFrom(tsk2, proc2);          assert_dead(tsk2);
	event = tsk_join(tsk2);                      assert_success(event);
	event = mtx_give(mtx1);                      assert_success(event);
	event = mtx_give(mtx1);                      assert_failure(event);
	        tsk_stop();
}

static void proc0()
{
	unsigned event;

	event = mtx_wait(&mtx0);                     assert_success(event);
	event = mtx_take(&mtx0);                     assert_timeout(event);
	                                             assert_dead(tsk1);
	        tsk_startFrom(tsk1, proc1);          assert_dead(tsk1);
	event = tsk_join(tsk1);                      assert_success(event);
	event = mtx_give(&mtx0);                     assert_success(event);
	event = mtx_give(&mtx0);                     assert_success(event);
	        tsk_stop();
}

static void test()
{
	unsigned event;
	                                             assert_dead(&tsk0);
	        tsk_startFrom(&tsk0, proc0);
	event = tsk_join(&tsk0);                     assert_success(event);
}

extern "C"
void test_mutex_4()
{
	TEST_Notify();
	mtx_init(&mtx0, mtxNormal, 0);
	mtx_init(mtx1, mtxErrorCheck, 0);
	mtx_init(mtx2, mtxRecursive, 0);
	TEST_Call();
}
<|endoftext|>


<commit_before><commit_msg>D3D10 render system - A small bug fix for the hlsl shader generator – VET_UBYTE4 is float4 and not char4 (no such thing as char4...).<commit_after><|endoftext|>