<commit_before>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "CppUTest/TestHarness.h"
#include "CppUTest/MemoryLeakDetector.h"
#include "CppUTest/PlatformSpecificFunctions.h"

#define UNKNOWN ((char*)("<unknown>"))

SimpleBuffer::SimpleBuffer() : positions_filled(0)
{
};

void SimpleBuffer::clear()
{
   positions_filled = 0;
   buffer[0] = '\0';
}

void SimpleBuffer::add(const char* format, ...)
{
   int count = 0;
   va_list arguments;
   va_start(arguments, format);
   count = PlatformSpecificVSNprintf(buffer + positions_filled, SIMPLE_BUFFER_LEN - positions_filled, format, arguments);
   if (count > 0)
      positions_filled += count;
   va_end(arguments);
}

char* SimpleBuffer::toString()
{
   return buffer;
}

///////////////////////

void MemoryLeakDetectorList::initNode(MemoryLeakDetectorNode* node, size_t size, char* memory, MemLeakPeriod period, char* file, int line, MemLeakAllocType type)
{
   if (node) {
      node->size = size;
      node->memory = memory;
      node->period = period;
      node->file = file;
      node->line = line;
      node->type = type;
   }
}

bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period)
{

	return period == mem_leak_period_all || node->period == period || (node->period != mem_leak_period_disabled && period == mem_leak_period_enabled);
}

void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period)
{
   MemoryLeakDetectorNode* cur = head;
   MemoryLeakDetectorNode* prev = 0;

   while (cur) {
      if (isInPeriod(cur, period)) {
         if (prev) {
            prev->next = cur->next;
            cur = prev;
         }
         else {
            head = cur->next;
            cur = head;
            continue;
         }
      }
      prev = cur;
      cur = cur->next;
   }
}

void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node)
{
   node->next = head;
   head = node;
}

MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory)
{
   MemoryLeakDetectorNode* cur = head;
   MemoryLeakDetectorNode* prev = 0;
   while (cur) {
      if (cur->memory == memory) {
         if (prev) {
            prev->next = cur->next;
            return cur;
         }
         else {
            head = cur->next;
            return cur;
         }
      }
      prev = cur;
      cur = cur->next;
   }
   return 0;
}

MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period)
{
   for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next)
      if (isInPeriod(cur, period)) return cur;
   return 0;
}

MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period)
{
   return getLeakFrom(head, period);
}

MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period)
{
   return getLeakFrom(node->next, period);
}

int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period)
{
   int total_leaks = 0;
   for (MemoryLeakDetectorNode* node = head; node; node = node->next) {
      if (isInPeriod(node, period)) total_leaks++;
   }
   return total_leaks;
}

bool MemoryLeakDetectorList::hasLeaks(MemLeakPeriod period)
{
   for (MemoryLeakDetectorNode* node = head; node; node = node->next)
      if (isInPeriod(node, period)) return true;
   return false;
}

/////////////////////////////////////////////////////////////

int MemoryLeakDetectorTable::hash(char* memory)
{
   return ((size_t) memory) % hash_prime;
}

void MemoryLeakDetectorTable::clearAllAccounting(MemLeakPeriod period)
{
   for (int i = 0; i < hash_prime; i++)
      table[i].clearAllAccounting(period);
}

void MemoryLeakDetectorTable::addNewNode(MemoryLeakDetectorNode* node)
{
   table[hash(node->memory)].addNewNode(node);
}

MemoryLeakDetectorNode* MemoryLeakDetectorTable::removeNode(char* memory)
{
   return table[hash(memory)].removeNode(memory);
}

bool MemoryLeakDetectorTable::hasLeaks(MemLeakPeriod period)
{
   for (int i = 0; i < hash_prime; i++)
      if (table[i].hasLeaks(period)) return true;
   return false;
}

int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period)
{
   int total_leaks = 0;
   for (int i = 0; i < hash_prime; i++)
      total_leaks += table[i].getTotalLeaks(period);
   return total_leaks;
}

MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod period)
{
   for (int i = 0; i < hash_prime; i++) {
      MemoryLeakDetectorNode* node = table[i].getFirstLeak(period);
      if (node) return node;
   }
   return 0;
}

MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period)
{
   int i = hash(leak->memory);
   MemoryLeakDetectorNode* node = table[i].getNextLeak(leak, period);
   if (node) return node;

   for (++i; i < hash_prime; i++) {
      node = table[i].getFirstLeak(period);
      if (node) return node;
   }
   return 0;
}

/////////////////////////////////////////////////////////////

MemoryLeakDetector::MemoryLeakDetector()
{
}

void MemoryLeakDetector::init(MemoryLeakFailure* report)
{
   current_period = mem_leak_period_disabled;
   reporter = report;
}

void MemoryLeakDetector::clearAllAccounting(MemLeakPeriod period)
{
   memoryTable.clearAllAccounting(period);
}

void MemoryLeakDetector::startChecking()
{
   output_buffer.clear();
   current_period = mem_leak_period_checking;
}

void MemoryLeakDetector::stopChecking()
{
   current_period = mem_leak_period_enabled;
}

void MemoryLeakDetector::enable()
{
   current_period = mem_leak_period_enabled;
}

void MemoryLeakDetector::disable()
{
   current_period = mem_leak_period_disabled;
}

void MemoryLeakDetector::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, MemLeakAllocType allocType, const char* freeFile, int freeLine, MemLeakAllocType freeType)
{
   output_buffer.add(message);
   output_buffer.add(MEM_LEAK_ALLOC_LOCATION, allocFile, allocLine, allocSize, getTypeString(allocType));
   output_buffer.add(MEM_LEAK_DEALLOC_LOCATION, freeFile, freeLine, getTypeString(freeType));
   reporter->fail(output_buffer.toString());
}

void* checkedMalloc(size_t size)
{
  void* mem = PlatformSpecificMalloc(size);
  if (mem == 0)
    FAIL("malloc returned nul pointer");
   return mem;
}

char* MemoryLeakDetector::allocateMemoryAndExtraInfo(size_t size)
{
   return (char*) checkedMalloc(size + memory_corruption_buffer_size + sizeof(MemoryLeakDetectorNode));
}

char* MemoryLeakDetector::reallocateMemoryAndExtraInfo (char* memory, size_t size)
{
   return (char*) PlatformSpecificRealloc(memory, size + memory_corruption_buffer_size + sizeof(MemoryLeakDetectorNode));
}

void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory, size_t size)
{
   memory[size]   = 'B';
   memory[size+1] = 'A';
   memory[size+2] = 'S';
}

void MemoryLeakDetector::checkForAllocMismatchOrCorruption(MemoryLeakDetectorNode* node, const char* file, int line, MemLeakAllocType type)
{
   if (node->type != type)
      reportFailure(MEM_LEAK_ALLOC_DEALLOC_MISMATCH, node->file, node->line, node->size, node->type, file, line, type);
   else if (node->memory[node->size] != 'B' || node->memory[node->size+1] != 'A' || node->memory[node->size+2] != 'S' )
      reportFailure(MEM_LEAK_MEMORY_CORRUPTION, node->file, node->line, node->size, node->type, file, line, type);
}

void MemoryLeakDetector::addMemoryLeakInfoAndCorruptionInfo(char* memory, size_t size, char* file, int line, MemLeakAllocType type)
{
   addMemoryCorruptionInformation(memory, size);
   if (memory) {
      MemoryLeakDetectorNode* node = (MemoryLeakDetectorNode*) (memory + size + memory_corruption_buffer_size);
      MemoryLeakDetectorList::initNode(node, size, memory, current_period, file, line, type);
      memoryTable.addNewNode(node);
   }
}

bool MemoryLeakDetector::removeMemoryLeakInfoAndCheckCorruption(char* memory, const char* file, int line, MemLeakAllocType type)
{
   MemoryLeakDetectorNode* node = memoryTable.removeNode(memory);
   if (node) {
      checkForAllocMismatchOrCorruption(node, file, line, type);
      return true;
   }
   reportFailure(MEM_LEAK_DEALLOC_NON_ALLOCATED, "<unknown>", 0, 0, mem_leak_alloc_unknown, file, line, type);
   return false;
}

char* MemoryLeakDetector::alloc(size_t size, char* file, int line, MemLeakAllocType type)
{
   char* mem = allocateMemoryAndExtraInfo(size);
   addMemoryLeakInfoAndCorruptionInfo(mem, size, file, line, type);
   return mem;
}

void MemoryLeakDetector::dealloc(char* memory, const char* file, int line, MemLeakAllocType type)
{
   if (memory == 0) return;

   if (removeMemoryLeakInfoAndCheckCorruption(memory, file, line, type))
      PlatformSpecificFree(memory);
}

char* MemoryLeakDetector::reallocate(char* memory, size_t size, char* file, int line, MemLeakAllocType type)
{
   if (memory)
      removeMemoryLeakInfoAndCheckCorruption(memory, file, line, type);

   char* mem = reallocateMemoryAndExtraInfo (memory, size);
   addMemoryCorruptionInformation(mem, size);
   addMemoryLeakInfoAndCorruptionInfo(mem, size, file, line, type);
   return mem;
}

void MemoryLeakDetector::ConstructMemoryLeakReport(MemLeakPeriod period)
{
   MemoryLeakDetectorNode* leak = memoryTable.getFirstLeak(period);
   int total_leaks = 0;
   output_buffer.add(MEM_LEAK_HEADER);

   while (leak)
   {
      output_buffer.add(MEM_LEAK_LEAK, leak->size, leak->file, leak->line, getTypeString(leak->type), leak->memory);
      total_leaks++;
      leak = memoryTable.getNextLeak(leak, period);
   }
   output_buffer.add("%s %d", MEM_LEAK_FOOTER, total_leaks);
}

const char* MemoryLeakDetector::report(MemLeakPeriod period)
{
   if (!memoryTable.hasLeaks(period)) return MEM_LEAK_NONE;

   output_buffer.clear();
   ConstructMemoryLeakReport(period);

   return output_buffer.toString();
}

void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod()
{
   MemoryLeakDetectorNode* leak = memoryTable.getFirstLeak(mem_leak_period_checking);
   while (leak) {
      if (leak->period == mem_leak_period_checking) leak->period = mem_leak_period_enabled;
      leak = memoryTable.getNextLeak(leak, mem_leak_period_checking);
   }
  }

int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period)
{
   return memoryTable.getTotalLeaks(period);
}

char* MemoryLeakDetector::allocOperatorNew(size_t size)
{
   return alloc(size, UNKNOWN, 0, mem_leak_alloc_new);
}

char* MemoryLeakDetector::allocOperatorNew(size_t size, const char* file, int line)
{
   return alloc(size, const_cast<char*>(file), line, mem_leak_alloc_new);
}

char* MemoryLeakDetector::allocOperatorNewArray(size_t size)
{
   return alloc(size, UNKNOWN, 0, mem_leak_alloc_new_array);
}

char* MemoryLeakDetector::allocOperatorNewArray(size_t size, const char* file, int line)
{
   return alloc(size, const_cast<char*>(file), line, mem_leak_alloc_new_array);
}

char* MemoryLeakDetector::allocMalloc(size_t size)
{
   return alloc(size, UNKNOWN, 0, mem_leak_alloc_malloc);
}

char* MemoryLeakDetector::allocMalloc(size_t size, const char* file, int line)
{
   return alloc(size, const_cast<char*>(file), line, mem_leak_alloc_malloc);
}

char* MemoryLeakDetector::allocRealloc(char* memory, size_t size, const char* file, int line)
{
   return reallocate(memory, size, const_cast<char*>(file), line, mem_leak_alloc_malloc);
}

void MemoryLeakDetector::freeOperatorDeleteArray(char* memory)
{
   dealloc(memory, UNKNOWN, 0, mem_leak_alloc_new_array);
}

void MemoryLeakDetector::freeOperatorDelete(char* memory)
{
   dealloc(memory, UNKNOWN, 0, mem_leak_alloc_new);
}

void MemoryLeakDetector::freeFree(char* memory)
{
   dealloc(memory, UNKNOWN, 0, mem_leak_alloc_malloc);
}

void MemoryLeakDetector::freeFree(char* memory, const char* file, int line)
{
   dealloc(memory, file, line, mem_leak_alloc_malloc);
}

const char* MemoryLeakDetector::getTypeString(MemLeakAllocType type)
{
   switch (type) {
      case mem_leak_alloc_new: return "new";
      case mem_leak_alloc_new_array: return "new []";
      case mem_leak_alloc_malloc: return "malloc";
      case mem_leak_alloc_unknown: return "unknown";
   }
   return 0;
}
<commit_msg>Fixed the problem with some uninited memory due to a non-constructor call in the MemoryLeakDetector<commit_after>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "CppUTest/TestHarness.h"
#include "CppUTest/MemoryLeakDetector.h"
#include "CppUTest/PlatformSpecificFunctions.h"

#define UNKNOWN ((char*)("<unknown>"))

SimpleBuffer::SimpleBuffer() : positions_filled(0)
{
};

void SimpleBuffer::clear()
{
   positions_filled = 0;
   buffer[0] = '\0';
}

void SimpleBuffer::add(const char* format, ...)
{
   int count = 0;
   va_list arguments;
   va_start(arguments, format);
   count = PlatformSpecificVSNprintf(buffer + positions_filled, SIMPLE_BUFFER_LEN - positions_filled, format, arguments);
   if (count > 0)
      positions_filled += count;
   va_end(arguments);
}

char* SimpleBuffer::toString()
{
   return buffer;
}

///////////////////////

void MemoryLeakDetectorList::initNode(MemoryLeakDetectorNode* node, size_t size, char* memory, MemLeakPeriod period, char* file, int line, MemLeakAllocType type)
{
   if (node) {
      node->size = size;
      node->memory = memory;
      node->period = period;
      node->file = file;
      node->line = line;
      node->type = type;
   }
}

bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period)
{

	return period == mem_leak_period_all || node->period == period || (node->period != mem_leak_period_disabled && period == mem_leak_period_enabled);
}

void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period)
{
   MemoryLeakDetectorNode* cur = head;
   MemoryLeakDetectorNode* prev = 0;

   while (cur) {
      if (isInPeriod(cur, period)) {
         if (prev) {
            prev->next = cur->next;
            cur = prev;
         }
         else {
            head = cur->next;
            cur = head;
            continue;
         }
      }
      prev = cur;
      cur = cur->next;
   }
}

void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node)
{
   node->next = head;
   head = node;
}

MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory)
{
   MemoryLeakDetectorNode* cur = head;
   MemoryLeakDetectorNode* prev = 0;
   while (cur) {
      if (cur->memory == memory) {
         if (prev) {
            prev->next = cur->next;
            return cur;
         }
         else {
            head = cur->next;
            return cur;
         }
      }
      prev = cur;
      cur = cur->next;
   }
   return 0;
}

MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period)
{
   for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next)
      if (isInPeriod(cur, period)) return cur;
   return 0;
}

MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period)
{
   return getLeakFrom(head, period);
}

MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period)
{
   return getLeakFrom(node->next, period);
}

int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period)
{
   int total_leaks = 0;
   for (MemoryLeakDetectorNode* node = head; node; node = node->next) {
      if (isInPeriod(node, period)) total_leaks++;
   }
   return total_leaks;
}

bool MemoryLeakDetectorList::hasLeaks(MemLeakPeriod period)
{
   for (MemoryLeakDetectorNode* node = head; node; node = node->next)
      if (isInPeriod(node, period)) return true;
   return false;
}

/////////////////////////////////////////////////////////////

int MemoryLeakDetectorTable::hash(char* memory)
{
   return ((size_t) memory) % hash_prime;
}

void MemoryLeakDetectorTable::clearAllAccounting(MemLeakPeriod period)
{
   for (int i = 0; i < hash_prime; i++)
      table[i].clearAllAccounting(period);
}

void MemoryLeakDetectorTable::addNewNode(MemoryLeakDetectorNode* node)
{
   table[hash(node->memory)].addNewNode(node);
}

MemoryLeakDetectorNode* MemoryLeakDetectorTable::removeNode(char* memory)
{
   return table[hash(memory)].removeNode(memory);
}

bool MemoryLeakDetectorTable::hasLeaks(MemLeakPeriod period)
{
   for (int i = 0; i < hash_prime; i++)
      if (table[i].hasLeaks(period)) return true;
   return false;
}

int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period)
{
   int total_leaks = 0;
   for (int i = 0; i < hash_prime; i++)
      total_leaks += table[i].getTotalLeaks(period);
   return total_leaks;
}

MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod period)
{
   for (int i = 0; i < hash_prime; i++) {
      MemoryLeakDetectorNode* node = table[i].getFirstLeak(period);
      if (node) return node;
   }
   return 0;
}

MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period)
{
   int i = hash(leak->memory);
   MemoryLeakDetectorNode* node = table[i].getNextLeak(leak, period);
   if (node) return node;

   for (++i; i < hash_prime; i++) {
      node = table[i].getFirstLeak(period);
      if (node) return node;
   }
   return 0;
}

/////////////////////////////////////////////////////////////

MemoryLeakDetector::MemoryLeakDetector()
{
}

void MemoryLeakDetector::init(MemoryLeakFailure* report)
{
   current_period = mem_leak_period_disabled;
   reporter = report;
   output_buffer = SimpleBuffer();
   memoryTable = MemoryLeakDetectorTable();
}

void MemoryLeakDetector::clearAllAccounting(MemLeakPeriod period)
{
   memoryTable.clearAllAccounting(period);
}

void MemoryLeakDetector::startChecking()
{
   output_buffer.clear();
   current_period = mem_leak_period_checking;
}

void MemoryLeakDetector::stopChecking()
{
   current_period = mem_leak_period_enabled;
}

void MemoryLeakDetector::enable()
{
   current_period = mem_leak_period_enabled;
}

void MemoryLeakDetector::disable()
{
   current_period = mem_leak_period_disabled;
}

void MemoryLeakDetector::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, MemLeakAllocType allocType, const char* freeFile, int freeLine, MemLeakAllocType freeType)
{
   output_buffer.add(message);
   output_buffer.add(MEM_LEAK_ALLOC_LOCATION, allocFile, allocLine, allocSize, getTypeString(allocType));
   output_buffer.add(MEM_LEAK_DEALLOC_LOCATION, freeFile, freeLine, getTypeString(freeType));
   reporter->fail(output_buffer.toString());
}

void* checkedMalloc(size_t size)
{
  void* mem = PlatformSpecificMalloc(size);
  if (mem == 0)
    FAIL("malloc returned nul pointer");
   return mem;
}

char* MemoryLeakDetector::allocateMemoryAndExtraInfo(size_t size)
{
   return (char*) checkedMalloc(size + memory_corruption_buffer_size + sizeof(MemoryLeakDetectorNode));
}

char* MemoryLeakDetector::reallocateMemoryAndExtraInfo (char* memory, size_t size)
{
   return (char*) PlatformSpecificRealloc(memory, size + memory_corruption_buffer_size + sizeof(MemoryLeakDetectorNode));
}

void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory, size_t size)
{
   memory[size]   = 'B';
   memory[size+1] = 'A';
   memory[size+2] = 'S';
}

void MemoryLeakDetector::checkForAllocMismatchOrCorruption(MemoryLeakDetectorNode* node, const char* file, int line, MemLeakAllocType type)
{
   if (node->type != type)
      reportFailure(MEM_LEAK_ALLOC_DEALLOC_MISMATCH, node->file, node->line, node->size, node->type, file, line, type);
   else if (node->memory[node->size] != 'B' || node->memory[node->size+1] != 'A' || node->memory[node->size+2] != 'S' )
      reportFailure(MEM_LEAK_MEMORY_CORRUPTION, node->file, node->line, node->size, node->type, file, line, type);
}

void MemoryLeakDetector::addMemoryLeakInfoAndCorruptionInfo(char* memory, size_t size, char* file, int line, MemLeakAllocType type)
{
   addMemoryCorruptionInformation(memory, size);
   if (memory) {
      MemoryLeakDetectorNode* node = (MemoryLeakDetectorNode*) (memory + size + memory_corruption_buffer_size);
      MemoryLeakDetectorList::initNode(node, size, memory, current_period, file, line, type);
      memoryTable.addNewNode(node);
   }
}

bool MemoryLeakDetector::removeMemoryLeakInfoAndCheckCorruption(char* memory, const char* file, int line, MemLeakAllocType type)
{
   MemoryLeakDetectorNode* node = memoryTable.removeNode(memory);
   if (node) {
      checkForAllocMismatchOrCorruption(node, file, line, type);
      return true;
   }
   reportFailure(MEM_LEAK_DEALLOC_NON_ALLOCATED, "<unknown>", 0, 0, mem_leak_alloc_unknown, file, line, type);
   return false;
}

char* MemoryLeakDetector::alloc(size_t size, char* file, int line, MemLeakAllocType type)
{
   char* mem = allocateMemoryAndExtraInfo(size);
   addMemoryLeakInfoAndCorruptionInfo(mem, size, file, line, type);
   return mem;
}

void MemoryLeakDetector::dealloc(char* memory, const char* file, int line, MemLeakAllocType type)
{
   if (memory == 0) return;

   if (removeMemoryLeakInfoAndCheckCorruption(memory, file, line, type))
      PlatformSpecificFree(memory);
}

char* MemoryLeakDetector::reallocate(char* memory, size_t size, char* file, int line, MemLeakAllocType type)
{
   if (memory)
      removeMemoryLeakInfoAndCheckCorruption(memory, file, line, type);

   char* mem = reallocateMemoryAndExtraInfo (memory, size);
   addMemoryCorruptionInformation(mem, size);
   addMemoryLeakInfoAndCorruptionInfo(mem, size, file, line, type);
   return mem;
}

void MemoryLeakDetector::ConstructMemoryLeakReport(MemLeakPeriod period)
{
   MemoryLeakDetectorNode* leak = memoryTable.getFirstLeak(period);
   int total_leaks = 0;
   output_buffer.add(MEM_LEAK_HEADER);

   while (leak)
   {
      output_buffer.add(MEM_LEAK_LEAK, leak->size, leak->file, leak->line, getTypeString(leak->type), leak->memory);
      total_leaks++;
      leak = memoryTable.getNextLeak(leak, period);
   }
   output_buffer.add("%s %d", MEM_LEAK_FOOTER, total_leaks);
}

const char* MemoryLeakDetector::report(MemLeakPeriod period)
{
   if (!memoryTable.hasLeaks(period)) return MEM_LEAK_NONE;

   output_buffer.clear();
   ConstructMemoryLeakReport(period);

   return output_buffer.toString();
}

void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod()
{
   MemoryLeakDetectorNode* leak = memoryTable.getFirstLeak(mem_leak_period_checking);
   while (leak) {
      if (leak->period == mem_leak_period_checking) leak->period = mem_leak_period_enabled;
      leak = memoryTable.getNextLeak(leak, mem_leak_period_checking);
   }
  }

int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period)
{
   return memoryTable.getTotalLeaks(period);
}

char* MemoryLeakDetector::allocOperatorNew(size_t size)
{
   return alloc(size, UNKNOWN, 0, mem_leak_alloc_new);
}

char* MemoryLeakDetector::allocOperatorNew(size_t size, const char* file, int line)
{
   return alloc(size, const_cast<char*>(file), line, mem_leak_alloc_new);
}

char* MemoryLeakDetector::allocOperatorNewArray(size_t size)
{
   return alloc(size, UNKNOWN, 0, mem_leak_alloc_new_array);
}

char* MemoryLeakDetector::allocOperatorNewArray(size_t size, const char* file, int line)
{
   return alloc(size, const_cast<char*>(file), line, mem_leak_alloc_new_array);
}

char* MemoryLeakDetector::allocMalloc(size_t size)
{
   return alloc(size, UNKNOWN, 0, mem_leak_alloc_malloc);
}

char* MemoryLeakDetector::allocMalloc(size_t size, const char* file, int line)
{
   return alloc(size, const_cast<char*>(file), line, mem_leak_alloc_malloc);
}

char* MemoryLeakDetector::allocRealloc(char* memory, size_t size, const char* file, int line)
{
   return reallocate(memory, size, const_cast<char*>(file), line, mem_leak_alloc_malloc);
}

void MemoryLeakDetector::freeOperatorDeleteArray(char* memory)
{
   dealloc(memory, UNKNOWN, 0, mem_leak_alloc_new_array);
}

void MemoryLeakDetector::freeOperatorDelete(char* memory)
{
   dealloc(memory, UNKNOWN, 0, mem_leak_alloc_new);
}

void MemoryLeakDetector::freeFree(char* memory)
{
   dealloc(memory, UNKNOWN, 0, mem_leak_alloc_malloc);
}

void MemoryLeakDetector::freeFree(char* memory, const char* file, int line)
{
   dealloc(memory, file, line, mem_leak_alloc_malloc);
}

const char* MemoryLeakDetector::getTypeString(MemLeakAllocType type)
{
   switch (type) {
      case mem_leak_alloc_new: return "new";
      case mem_leak_alloc_new_array: return "new []";
      case mem_leak_alloc_malloc: return "malloc";
      case mem_leak_alloc_unknown: return "unknown";
   }
   return 0;
}
<|endoftext|>


<commit_before>#include <Common.hpp>
#include <Engine.hpp>
#include <Dispatch.hpp>
#include <MessageProcessor.hpp>

#include <functional>
#include <iostream>
#include <sstream>
#include <fstream>

#include <boost/regex.hpp>
#include <boost/thread/thread.hpp>

namespace K3 {

std::string localhost = "127.0.0.1";
Address peer1;
Address peer2;
Address rendezvous;

int nodeCounter(0);
string message;

using std::cout;
using std::endl;
using std::bind;
using std::string;
using std::shared_ptr;

// "Trigger" Declarations
void join(shared_ptr<Engine> engine, string message_contents) {
  Message m = Message(rendezvous, "register", message);
  engine->send(m);
}

void register2(shared_ptr<Engine> engine, string message_contents) {
  int n = 1;
  nodeCounter += n;
  std::cout << "Length (mB)" << message_contents.length() / (1024*1024.0) << ". Number:" << nodeCounter<< std::endl;
}

// MP setup
TriggerDispatch buildTable(shared_ptr<Engine> engine) {
  TriggerDispatch table = TriggerDispatch();
  table["join"] = bind(&K3::join, engine, std::placeholders::_1);
  table["register"] = bind(&K3::register2, engine, std::placeholders::_1);
  return table;
}

shared_ptr<MessageProcessor> buildMP(shared_ptr<Engine> engine) {
  auto table = buildTable(engine);
  shared_ptr<MessageProcessor> mp = make_shared<DispatchMessageProcessor>(DispatchMessageProcessor(table));
  return mp;
}

// Engine setup
shared_ptr<Engine> buildEngine(bool simulation, SystemEnvironment s_env) {
  // Configure engine components
  shared_ptr<InternalCodec> i_cdec = make_shared<LengthHeaderInternalCodec>(LengthHeaderInternalCodec());

  // Construct an engine
  Engine engine = Engine(simulation, s_env, i_cdec);
  return make_shared<Engine>(engine);
}

}

void runReceiver(int num_messages) {

  K3::peer1 = K3::make_address(K3::localhost, 40000);
  K3::nodeCounter = 0;
  using boost::thread;
  using boost::thread_group;
  using std::shared_ptr;
  // Create engines
  auto engine1 = K3::buildEngine(false, K3::defaultEnvironment(K3::peer1));
  // Create MPs
  auto mp1 = K3::buildMP(engine1);
  // Fork a thread for each engine
  auto service_threads = std::shared_ptr<thread_group>(new thread_group());
  shared_ptr<thread> t1 = engine1->forkEngine(mp1);

  service_threads->add_thread(t1.get());

  int desired = num_messages;
  while ((K3::nodeCounter < desired)) {
   continue;
  }

  engine1->forceTerminateEngine();

  service_threads->join_all();
  service_threads->remove_thread(t1.get());
}

void runSender(int num_messages, int message_len) {
  K3::message = "";
  for (int i=0; i< message_len; i++) {
    K3::message += "a";
  }
  using boost::thread;
  using boost::thread_group;
  using std::shared_ptr;
  // Create peers
  K3::peer1 = K3::make_address(K3::localhost, 40000);
  K3::peer2 = K3::make_address(K3::localhost, 40001);
  K3::rendezvous = K3::peer1;
  // Create engines
  auto engine2 = K3::buildEngine(false, K3::defaultEnvironment(K3::peer2));
  // Create MPs
  auto mp2 = K3::buildMP(engine2);
  // Create initial messages (source)
  K3::Message m2 = K3::Message(K3::peer2, "join", "()");
  for (int i = 0; i < num_messages; i++) {
    engine2->send(m2);
  }
  engine2->runEngine(mp2);

}

int main(int argc, char** argv) {

 if (argc < 3) {
  std::cout << "usage: " << argv[0] << " num_messages" << " sender|receiver" << std::endl;
  return -1;
 }

 int num_messages = std::atoi(argv[1]);
 std::string mode = argv[2];
 if (mode == "receiver") {
   runReceiver(num_messages);
 }
 else {
   runSender(num_messages, 10);
 }

 return 0;
}
<commit_msg>Small changes to test file<commit_after>#include <Common.hpp>
#include <Engine.hpp>
#include <Dispatch.hpp>
#include <MessageProcessor.hpp>

#include <functional>
#include <iostream>
#include <sstream>
#include <fstream>

#include <boost/regex.hpp>
#include <boost/thread/thread.hpp>

namespace K3 {

std::string localhost = "127.0.0.1";
Address peer1;
Address peer2;
Address rendezvous;

int nodeCounter(0);
int numSent(0);
string message;

using std::cout;
using std::endl;
using std::bind;
using std::string;
using std::shared_ptr;

// "Trigger" Declarations
void join(shared_ptr<Engine> engine, string message_contents) {
  Message m = Message(rendezvous, "register", message);
  engine->send(m);
}

void register2(shared_ptr<Engine> engine, string message_contents) {
  int n = 1;
  nodeCounter += n;
  std::cout << "Length (mB)" << message_contents.length() / (1024*1024.0) << ". Number:" << nodeCounter<< std::endl;
}

// MP setup
TriggerDispatch buildTable(shared_ptr<Engine> engine) {
  TriggerDispatch table = TriggerDispatch();
  table["join"] = bind(&K3::join, engine, std::placeholders::_1);
  table["register"] = bind(&K3::register2, engine, std::placeholders::_1);
  return table;
}

shared_ptr<MessageProcessor> buildMP(shared_ptr<Engine> engine) {
  auto table = buildTable(engine);
  shared_ptr<MessageProcessor> mp = make_shared<DispatchMessageProcessor>(DispatchMessageProcessor(table));
  return mp;
}

// Engine setup
shared_ptr<Engine> buildEngine(bool simulation, SystemEnvironment s_env) {
  // Configure engine components
  shared_ptr<InternalCodec> i_cdec = make_shared<LengthHeaderInternalCodec>(LengthHeaderInternalCodec());

  // Construct an engine
  Engine engine = Engine(simulation, s_env, i_cdec);
  return make_shared<Engine>(engine);
}

}

void runReceiver(int num_messages) {

  K3::peer1 = K3::make_address("192.168.0.11", 3000);
  K3::nodeCounter = 0;
  using boost::thread;
  using boost::thread_group;
  using std::shared_ptr;
  // Create engines
  auto engine1 = K3::buildEngine(false, K3::defaultEnvironment(K3::peer1));
  // Create MPs
  auto mp1 = K3::buildMP(engine1);
  // Fork a thread for each engine
  auto service_threads = std::shared_ptr<thread_group>(new thread_group());
  shared_ptr<thread> t1 = engine1->forkEngine(mp1);

  service_threads->add_thread(t1.get());

  int desired = num_messages;
  while ((K3::nodeCounter < desired)) {
   continue;
  }

  engine1->forceTerminateEngine();

  service_threads->join_all();
  service_threads->remove_thread(t1.get());
}

void runSender(int num_messages, int message_len) {
  K3::message = "";
  for (int i=0; i< message_len; i++) {
    K3::message += "a";
  }
  using boost::thread;
  using boost::thread_group;
  using std::shared_ptr;
  // Create peers
  K3::peer1 = K3::make_address("192.168.0.11", 3000);
  K3::peer2 = K3::make_address(K3::localhost, 3000);
  K3::rendezvous = K3::peer1;
  // Create engines
  auto engine2 = K3::buildEngine(false, K3::defaultEnvironment(K3::peer2));
  // Create MPs
  auto mp2 = K3::buildMP(engine2);
  // Create initial messages (source)
  K3::Message m2 = K3::Message(K3::peer2, "join", "()");
  for (int i = 0; i < num_messages; i++) {
    engine2->send(m2);
  }
  engine2->runEngine(mp2);

}

int main(int argc, char** argv) {

 if (argc < 3) {
  std::cout << "usage: " << argv[0] << " num_messages" << " sender|receiver" << std::endl;
  return -1;
 }

 int num_messages = std::atoi(argv[1]);
 std::string mode = argv[2];
 if (mode == "receiver") {
   runReceiver(num_messages);
 }
 else {
   runSender(num_messages, 10);
 }

 return 0;
}
<|endoftext|>


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

#include "space_bitmap-inl.h"

namespace art {
namespace gc {
namespace accounting {

template<size_t kAlignment>
size_t SpaceBitmap<kAlignment>::ComputeBitmapSize(uint64_t capacity) {
  const uint64_t kBytesCoveredPerWord = kAlignment * kBitsPerWord;
  return (RoundUp(capacity, kBytesCoveredPerWord) / kBytesCoveredPerWord) * kWordSize;
}

template<size_t kAlignment>
SpaceBitmap<kAlignment>* SpaceBitmap<kAlignment>::CreateFromMemMap(
    const std::string& name, MemMap* mem_map, byte* heap_begin, size_t heap_capacity) {
  CHECK(mem_map != nullptr);
  uword* bitmap_begin = reinterpret_cast<uword*>(mem_map->Begin());
  const size_t bitmap_size = ComputeBitmapSize(heap_capacity);
  return new SpaceBitmap(name, mem_map, bitmap_begin, bitmap_size, heap_begin);
}

template<size_t kAlignment>
SpaceBitmap<kAlignment>::SpaceBitmap(const std::string& name, MemMap* mem_map, uword* bitmap_begin,
                                     size_t bitmap_size, const void* heap_begin)
    : mem_map_(mem_map), bitmap_begin_(bitmap_begin), bitmap_size_(bitmap_size),
      heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)),
      name_(name) {
  CHECK(bitmap_begin_ != nullptr);
  CHECK_NE(bitmap_size, 0U);
}

template<size_t kAlignment>
SpaceBitmap<kAlignment>* SpaceBitmap<kAlignment>::Create(
    const std::string& name, byte* heap_begin, size_t heap_capacity) {
  // Round up since heap_capacity is not necessarily a multiple of kAlignment * kBitsPerWord.
  const size_t bitmap_size = ComputeBitmapSize(heap_capacity);
  std::string error_msg;
  std::unique_ptr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), nullptr, bitmap_size,
                                                 PROT_READ | PROT_WRITE, false, &error_msg));
  if (UNLIKELY(mem_map.get() == nullptr)) {
    LOG(ERROR) << "Failed to allocate bitmap " << name << ": " << error_msg;
    return nullptr;
  }
  return CreateFromMemMap(name, mem_map.release(), heap_begin, heap_capacity);
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::SetHeapLimit(uintptr_t new_end) {
  DCHECK(IsAligned<kBitsPerWord * kAlignment>(new_end));
  size_t new_size = OffsetToIndex(new_end - heap_begin_) * kWordSize;
  if (new_size < bitmap_size_) {
    bitmap_size_ = new_size;
  }
  // Not sure if doing this trim is necessary, since nothing past the end of the heap capacity
  // should be marked.
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::Clear() {
  if (bitmap_begin_ != NULL) {
    // This returns the memory to the system.  Successive page faults will return zeroed memory.
    int result = madvise(bitmap_begin_, bitmap_size_, MADV_DONTNEED);
    if (result == -1) {
      PLOG(FATAL) << "madvise failed";
    }
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::CopyFrom(SpaceBitmap* source_bitmap) {
  DCHECK_EQ(Size(), source_bitmap->Size());
  std::copy(source_bitmap->Begin(), source_bitmap->Begin() + source_bitmap->Size() / kWordSize, Begin());
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::Walk(ObjectCallback* callback, void* arg) {
  CHECK(bitmap_begin_ != NULL);
  CHECK(callback != NULL);

  uintptr_t end = OffsetToIndex(HeapLimit() - heap_begin_ - 1);
  uword* bitmap_begin = bitmap_begin_;
  for (uintptr_t i = 0; i <= end; ++i) {
    uword w = bitmap_begin[i];
    if (w != 0) {
      uintptr_t ptr_base = IndexToOffset(i) + heap_begin_;
      do {
        const size_t shift = CTZ(w);
        mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
        (*callback)(obj, arg);
        w ^= (static_cast<uword>(1)) << shift;
      } while (w != 0);
    }
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::SweepWalk(const SpaceBitmap<kAlignment>& live_bitmap,
                                        const SpaceBitmap<kAlignment>& mark_bitmap,
                                        uintptr_t sweep_begin, uintptr_t sweep_end,
                                        SpaceBitmap::SweepCallback* callback, void* arg) {
  CHECK(live_bitmap.bitmap_begin_ != nullptr);
  CHECK(mark_bitmap.bitmap_begin_ != nullptr);
  CHECK_EQ(live_bitmap.heap_begin_, mark_bitmap.heap_begin_);
  CHECK_EQ(live_bitmap.bitmap_size_, mark_bitmap.bitmap_size_);
  CHECK(callback != NULL);
  CHECK_LE(sweep_begin, sweep_end);
  CHECK_GE(sweep_begin, live_bitmap.heap_begin_);

  if (sweep_end <= sweep_begin) {
    return;
  }

  // TODO: rewrite the callbacks to accept a std::vector<mirror::Object*> rather than a mirror::Object**?
  const size_t buffer_size = kWordSize * kBitsPerWord;
  mirror::Object* pointer_buf[buffer_size];
  mirror::Object** pb = &pointer_buf[0];
  size_t start = OffsetToIndex(sweep_begin - live_bitmap.heap_begin_);
  size_t end = OffsetToIndex(sweep_end - live_bitmap.heap_begin_ - 1);
  CHECK_LT(end, live_bitmap.Size() / kWordSize);
  uword* live = live_bitmap.bitmap_begin_;
  uword* mark = mark_bitmap.bitmap_begin_;
  for (size_t i = start; i <= end; i++) {
    uword garbage = live[i] & ~mark[i];
    if (UNLIKELY(garbage != 0)) {
      uintptr_t ptr_base = IndexToOffset(i) + live_bitmap.heap_begin_;
      do {
        const size_t shift = CTZ(garbage);
        garbage ^= (static_cast<uword>(1)) << shift;
        *pb++ = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
      } while (garbage != 0);
      // Make sure that there are always enough slots available for an
      // entire word of one bits.
      if (pb >= &pointer_buf[buffer_size - kBitsPerWord]) {
        (*callback)(pb - &pointer_buf[0], &pointer_buf[0], arg);
        pb = &pointer_buf[0];
      }
    }
  }
  if (pb > &pointer_buf[0]) {
    (*callback)(pb - &pointer_buf[0], &pointer_buf[0], arg);
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::WalkInstanceFields(SpaceBitmap<kAlignment>* visited,
                                                 ObjectCallback* callback, mirror::Object* obj,
                                                 mirror::Class* klass, void* arg)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  // Visit fields of parent classes first.
  mirror::Class* super = klass->GetSuperClass();
  if (super != NULL) {
    WalkInstanceFields(visited, callback, obj, super, arg);
  }
  // Walk instance fields
  mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
  if (fields != NULL) {
    for (int32_t i = 0; i < fields->GetLength(); i++) {
      mirror::ArtField* field = fields->Get(i);
      FieldHelper fh(field);
      if (!fh.IsPrimitiveType()) {
        mirror::Object* value = field->GetObj(obj);
        if (value != NULL) {
          WalkFieldsInOrder(visited, callback, value,  arg);
        }
      }
    }
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::WalkFieldsInOrder(SpaceBitmap<kAlignment>* visited,
                                                ObjectCallback* callback, mirror::Object* obj,
                                                void* arg) {
  if (visited->Test(obj)) {
    return;
  }
  // visit the object itself
  (*callback)(obj, arg);
  visited->Set(obj);
  // Walk instance fields of all objects
  mirror::Class* klass = obj->GetClass();
  WalkInstanceFields(visited, callback, obj, klass, arg);
  // Walk static fields of a Class
  if (obj->IsClass()) {
    mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
    if (fields != NULL) {
      for (int32_t i = 0; i < fields->GetLength(); i++) {
        mirror::ArtField* field = fields->Get(i);
        FieldHelper fh(field);
        if (!fh.IsPrimitiveType()) {
          mirror::Object* value = field->GetObj(NULL);
          if (value != NULL) {
            WalkFieldsInOrder(visited, callback, value, arg);
          }
        }
      }
    }
  } else if (obj->IsObjectArray()) {
    // Walk elements of an object array
    mirror::ObjectArray<mirror::Object>* obj_array = obj->AsObjectArray<mirror::Object>();
    int32_t length = obj_array->GetLength();
    for (int32_t i = 0; i < length; i++) {
      mirror::Object* value = obj_array->Get(i);
      if (value != NULL) {
        WalkFieldsInOrder(visited, callback, value, arg);
      }
    }
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::InOrderWalk(ObjectCallback* callback, void* arg) {
  std::unique_ptr<SpaceBitmap<kAlignment>> visited(
      Create("bitmap for in-order walk", reinterpret_cast<byte*>(heap_begin_),
             IndexToOffset(bitmap_size_ / kWordSize)));
  CHECK(bitmap_begin_ != nullptr);
  CHECK(callback != nullptr);
  uintptr_t end = Size() / kWordSize;
  for (uintptr_t i = 0; i < end; ++i) {
    // Need uint for unsigned shift.
    uword w = bitmap_begin_[i];
    if (UNLIKELY(w != 0)) {
      uintptr_t ptr_base = IndexToOffset(i) + heap_begin_;
      while (w != 0) {
        const size_t shift = CTZ(w);
        mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
        WalkFieldsInOrder(visited.get(), callback, obj, arg);
        w ^= (static_cast<uword>(1)) << shift;
      }
    }
  }
}

template class SpaceBitmap<kObjectAlignment>;
template class SpaceBitmap<kPageSize>;

}  // namespace accounting
}  // namespace gc
}  // namespace art
<commit_msg>am 2783521e: am 2bb87ef4: Merge "ART: Heap-allocate buffer in space_bitmap when on 64b arch"<commit_after>/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "space_bitmap-inl.h"

namespace art {
namespace gc {
namespace accounting {

template<size_t kAlignment>
size_t SpaceBitmap<kAlignment>::ComputeBitmapSize(uint64_t capacity) {
  const uint64_t kBytesCoveredPerWord = kAlignment * kBitsPerWord;
  return (RoundUp(capacity, kBytesCoveredPerWord) / kBytesCoveredPerWord) * kWordSize;
}

template<size_t kAlignment>
SpaceBitmap<kAlignment>* SpaceBitmap<kAlignment>::CreateFromMemMap(
    const std::string& name, MemMap* mem_map, byte* heap_begin, size_t heap_capacity) {
  CHECK(mem_map != nullptr);
  uword* bitmap_begin = reinterpret_cast<uword*>(mem_map->Begin());
  const size_t bitmap_size = ComputeBitmapSize(heap_capacity);
  return new SpaceBitmap(name, mem_map, bitmap_begin, bitmap_size, heap_begin);
}

template<size_t kAlignment>
SpaceBitmap<kAlignment>::SpaceBitmap(const std::string& name, MemMap* mem_map, uword* bitmap_begin,
                                     size_t bitmap_size, const void* heap_begin)
    : mem_map_(mem_map), bitmap_begin_(bitmap_begin), bitmap_size_(bitmap_size),
      heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)),
      name_(name) {
  CHECK(bitmap_begin_ != nullptr);
  CHECK_NE(bitmap_size, 0U);
}

template<size_t kAlignment>
SpaceBitmap<kAlignment>* SpaceBitmap<kAlignment>::Create(
    const std::string& name, byte* heap_begin, size_t heap_capacity) {
  // Round up since heap_capacity is not necessarily a multiple of kAlignment * kBitsPerWord.
  const size_t bitmap_size = ComputeBitmapSize(heap_capacity);
  std::string error_msg;
  std::unique_ptr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), nullptr, bitmap_size,
                                                 PROT_READ | PROT_WRITE, false, &error_msg));
  if (UNLIKELY(mem_map.get() == nullptr)) {
    LOG(ERROR) << "Failed to allocate bitmap " << name << ": " << error_msg;
    return nullptr;
  }
  return CreateFromMemMap(name, mem_map.release(), heap_begin, heap_capacity);
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::SetHeapLimit(uintptr_t new_end) {
  DCHECK(IsAligned<kBitsPerWord * kAlignment>(new_end));
  size_t new_size = OffsetToIndex(new_end - heap_begin_) * kWordSize;
  if (new_size < bitmap_size_) {
    bitmap_size_ = new_size;
  }
  // Not sure if doing this trim is necessary, since nothing past the end of the heap capacity
  // should be marked.
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::Clear() {
  if (bitmap_begin_ != NULL) {
    // This returns the memory to the system.  Successive page faults will return zeroed memory.
    int result = madvise(bitmap_begin_, bitmap_size_, MADV_DONTNEED);
    if (result == -1) {
      PLOG(FATAL) << "madvise failed";
    }
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::CopyFrom(SpaceBitmap* source_bitmap) {
  DCHECK_EQ(Size(), source_bitmap->Size());
  std::copy(source_bitmap->Begin(), source_bitmap->Begin() + source_bitmap->Size() / kWordSize, Begin());
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::Walk(ObjectCallback* callback, void* arg) {
  CHECK(bitmap_begin_ != NULL);
  CHECK(callback != NULL);

  uintptr_t end = OffsetToIndex(HeapLimit() - heap_begin_ - 1);
  uword* bitmap_begin = bitmap_begin_;
  for (uintptr_t i = 0; i <= end; ++i) {
    uword w = bitmap_begin[i];
    if (w != 0) {
      uintptr_t ptr_base = IndexToOffset(i) + heap_begin_;
      do {
        const size_t shift = CTZ(w);
        mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
        (*callback)(obj, arg);
        w ^= (static_cast<uword>(1)) << shift;
      } while (w != 0);
    }
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::SweepWalk(const SpaceBitmap<kAlignment>& live_bitmap,
                                        const SpaceBitmap<kAlignment>& mark_bitmap,
                                        uintptr_t sweep_begin, uintptr_t sweep_end,
                                        SpaceBitmap::SweepCallback* callback, void* arg) {
  CHECK(live_bitmap.bitmap_begin_ != nullptr);
  CHECK(mark_bitmap.bitmap_begin_ != nullptr);
  CHECK_EQ(live_bitmap.heap_begin_, mark_bitmap.heap_begin_);
  CHECK_EQ(live_bitmap.bitmap_size_, mark_bitmap.bitmap_size_);
  CHECK(callback != NULL);
  CHECK_LE(sweep_begin, sweep_end);
  CHECK_GE(sweep_begin, live_bitmap.heap_begin_);

  if (sweep_end <= sweep_begin) {
    return;
  }

  // TODO: rewrite the callbacks to accept a std::vector<mirror::Object*> rather than a mirror::Object**?
  constexpr size_t buffer_size = kWordSize * kBitsPerWord;
#ifdef __LP64__
  // Heap-allocate for smaller stack frame.
  std::unique_ptr<mirror::Object*[]> pointer_buf_ptr(new mirror::Object*[buffer_size]);
  mirror::Object** pointer_buf = pointer_buf_ptr.get();
#else
  // Stack-allocate buffer as it's small enough.
  mirror::Object* pointer_buf[buffer_size];
#endif
  mirror::Object** pb = &pointer_buf[0];

  size_t start = OffsetToIndex(sweep_begin - live_bitmap.heap_begin_);
  size_t end = OffsetToIndex(sweep_end - live_bitmap.heap_begin_ - 1);
  CHECK_LT(end, live_bitmap.Size() / kWordSize);
  uword* live = live_bitmap.bitmap_begin_;
  uword* mark = mark_bitmap.bitmap_begin_;
  for (size_t i = start; i <= end; i++) {
    uword garbage = live[i] & ~mark[i];
    if (UNLIKELY(garbage != 0)) {
      uintptr_t ptr_base = IndexToOffset(i) + live_bitmap.heap_begin_;
      do {
        const size_t shift = CTZ(garbage);
        garbage ^= (static_cast<uword>(1)) << shift;
        *pb++ = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
      } while (garbage != 0);
      // Make sure that there are always enough slots available for an
      // entire word of one bits.
      if (pb >= &pointer_buf[buffer_size - kBitsPerWord]) {
        (*callback)(pb - &pointer_buf[0], &pointer_buf[0], arg);
        pb = &pointer_buf[0];
      }
    }
  }
  if (pb > &pointer_buf[0]) {
    (*callback)(pb - &pointer_buf[0], &pointer_buf[0], arg);
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::WalkInstanceFields(SpaceBitmap<kAlignment>* visited,
                                                 ObjectCallback* callback, mirror::Object* obj,
                                                 mirror::Class* klass, void* arg)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  // Visit fields of parent classes first.
  mirror::Class* super = klass->GetSuperClass();
  if (super != NULL) {
    WalkInstanceFields(visited, callback, obj, super, arg);
  }
  // Walk instance fields
  mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
  if (fields != NULL) {
    for (int32_t i = 0; i < fields->GetLength(); i++) {
      mirror::ArtField* field = fields->Get(i);
      FieldHelper fh(field);
      if (!fh.IsPrimitiveType()) {
        mirror::Object* value = field->GetObj(obj);
        if (value != NULL) {
          WalkFieldsInOrder(visited, callback, value,  arg);
        }
      }
    }
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::WalkFieldsInOrder(SpaceBitmap<kAlignment>* visited,
                                                ObjectCallback* callback, mirror::Object* obj,
                                                void* arg) {
  if (visited->Test(obj)) {
    return;
  }
  // visit the object itself
  (*callback)(obj, arg);
  visited->Set(obj);
  // Walk instance fields of all objects
  mirror::Class* klass = obj->GetClass();
  WalkInstanceFields(visited, callback, obj, klass, arg);
  // Walk static fields of a Class
  if (obj->IsClass()) {
    mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
    if (fields != NULL) {
      for (int32_t i = 0; i < fields->GetLength(); i++) {
        mirror::ArtField* field = fields->Get(i);
        FieldHelper fh(field);
        if (!fh.IsPrimitiveType()) {
          mirror::Object* value = field->GetObj(NULL);
          if (value != NULL) {
            WalkFieldsInOrder(visited, callback, value, arg);
          }
        }
      }
    }
  } else if (obj->IsObjectArray()) {
    // Walk elements of an object array
    mirror::ObjectArray<mirror::Object>* obj_array = obj->AsObjectArray<mirror::Object>();
    int32_t length = obj_array->GetLength();
    for (int32_t i = 0; i < length; i++) {
      mirror::Object* value = obj_array->Get(i);
      if (value != NULL) {
        WalkFieldsInOrder(visited, callback, value, arg);
      }
    }
  }
}

template<size_t kAlignment>
void SpaceBitmap<kAlignment>::InOrderWalk(ObjectCallback* callback, void* arg) {
  std::unique_ptr<SpaceBitmap<kAlignment>> visited(
      Create("bitmap for in-order walk", reinterpret_cast<byte*>(heap_begin_),
             IndexToOffset(bitmap_size_ / kWordSize)));
  CHECK(bitmap_begin_ != nullptr);
  CHECK(callback != nullptr);
  uintptr_t end = Size() / kWordSize;
  for (uintptr_t i = 0; i < end; ++i) {
    // Need uint for unsigned shift.
    uword w = bitmap_begin_[i];
    if (UNLIKELY(w != 0)) {
      uintptr_t ptr_base = IndexToOffset(i) + heap_begin_;
      while (w != 0) {
        const size_t shift = CTZ(w);
        mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
        WalkFieldsInOrder(visited.get(), callback, obj, arg);
        w ^= (static_cast<uword>(1)) << shift;
      }
    }
  }
}

template class SpaceBitmap<kObjectAlignment>;
template class SpaceBitmap<kPageSize>;

}  // namespace accounting
}  // namespace gc
}  // namespace art
<|endoftext|>


<commit_before>// Geo demo written by Geoff Michel, November 2002.

#include <stdio.h>
#include <osg/GL>
#include <osgGLUT/glut>
#include <osgGLUT/Viewer>

#include <osg/Node>
#include <osg/Notify>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/AnimationPathManipulator>

#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>

// currently not a satisfactory solution, but this is early days for the
// geo loader and having direct links with it.
#include "../../osgPlugins/geo/osgGeoAnimation.h"

void write_usage(std::ostream& out,const std::string& name)
{
    out << std::endl;
    out <<"usage:"<< std::endl;
    out <<"    "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
    out << std::endl;
    out <<"options:"<< std::endl;
    out <<"    -l libraryName      - load plugin of name libraryName"<< std::endl;
    out <<"                          i.e. -l osgdb_pfb"<< std::endl;
    out <<"                          Useful for loading reader/writers which can load"<< std::endl;
    out <<"                          other file formats in addition to its extension."<< std::endl;
    out <<"    -e extensionName    - load reader/wrter plugin for file extension"<< std::endl;
    out <<"                          i.e. -e pfb"<< std::endl;
    out <<"                          Useful short hand for specifying full library name as"<< std::endl;
    out <<"                          done with -l above, as it automatically expands to"<< std::endl;
    out <<"                          the full library name appropriate for each platform."<< std::endl;
    out <<std::endl;
    out <<"    -stereo             - switch on stereo rendering, using the default of,"<< std::endl;
    out <<"                          ANAGLYPHIC or the value set in the OSG_STEREO_MODE "<< std::endl;
    out <<"                          environmental variable. See doc/stereo.html for "<< std::endl;
    out <<"                          further details on setting up accurate stereo "<< std::endl;
    out <<"                          for your system. "<< std::endl;
    out <<"    -stereo ANAGLYPHIC  - switch on anaglyphic(red/cyan) stereo rendering."<< std::endl;
    out <<"    -stereo QUAD_BUFFER - switch on quad buffered stereo rendering."<< std::endl;
    out <<std::endl;
    out <<"    -stencil            - use a visual with stencil buffer enabled, this "<< std::endl;
    out <<"                          also allows the depth complexity statistics mode"<< std::endl;
    out <<"                          to be used (press 'p' three times to cycle to it)."<< std::endl;
    out <<"    -f                  - start with a full screen, borderless window." << std::endl;
    out <<"    -p  pathfile        - Use the AnimationPathManipulator (key binding '4') and use\n"
      "                          pathfile to define the animation path.  pathfile is an ascii\n"
      "                          file containing lines of eight floating point numbers representing\n"
      "                          time, position (x,y,z) and attitude (x,y,z,w as a quaternion)." << std::endl;
    out << std::endl;
}

//== event trapper gets events

class geodemoEventHandler : public osgGA::GUIEventHandler
{
public:

    geodemoEventHandler( )     { mouse_x=mouse_y=0;}
    virtual ~geodemoEventHandler( ) {}

    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
    {
        mouse_x=ea.getX();
        mouse_y=ea.getY();
        return false;

    }

    virtual void accept(osgGA::GUIEventHandlerVisitor& v)
    {
        v.visit(*this);
    }
    inline int getMouseX(void) {return mouse_x;};
    inline int getMouseY(void) {return mouse_y;};

private:
    int    mouse_x, mouse_y;
};

static geodemoEventHandler *ghand=NULL;
inline double DEG2RAD(const double val) { return val*0.0174532925199432957692369076848861;}
inline double RAD2DEG(const double val) { return val*57.2957795130823208767981548141052;}

double dodynamics(const double time, const double val, const std::string name)
{ // Each local variable named 'name' declared in the geo modeller is passed into here.
    // its current value is val; returns new value.  Time - elapsed time
    static double heading,speed; // these are only required for my 'dynamics'
    if (name == "xpos") {
        return (val+speed*sin(heading));
        //    std::cout << " nx " << (*itr->getValue()) ;
    } else if (name == "ypos") {
        return (val+speed*cos(heading));
        //    std::cout << " ny " << (*itr->getValue()) ;
    } else if (name == "sped") {
        speed=(0.00025*(ghand->getMouseY()-300)); // (*itr->getValue());
        return (speed);
    } else if (name == "heading") {
        heading-= 0.01*DEG2RAD(ghand->getMouseX()-400); // =DEG2RAD(*itr->getValue());
        return (RAD2DEG(heading));
    } else if (name == "conerot") {
        return ((ghand->getMouseX()-400));
    } else if (name == "planrot") {
        return ((ghand->getMouseY()-300)/200.0);
    } else if (name == "secint" || name == "minutehand"|| name == "hourhand") {
    //    std::cout << " updating " << name << " " << val << std::endl;
    }
    return val;
}

int main( int argc, char **argv )
{
    std::string pathfile;
    float camera_fov=-1;

    // initialize the GLUT
    glutInit( &argc, argv );

    if (argc<2)
    {
        write_usage(std::cout,argv[0]);
        return 1;
    }

    // create the commandline args.
    std::vector<std::string> commandLine;
    for(int i=1;i<argc;++i) {
    if( std::string(argv[i]) == "-p" ) {
        if( (i+1) >= argc ) {
        write_usage( std::cout, argv[0]);
            return 1;
        }
        else
        pathfile = std::string(argv[++i]);
    } else if( std::string(argv[i]) == "-fov" ) {
        camera_fov=atof(argv[i+1]);
        ++i; // skip the value
    }
    else
        commandLine.push_back(argv[i]);
    }

    // initialize the viewer.
    osgGLUT::Viewer viewer;
    viewer.setWindowTitle(argv[0]);

    // geoff's path code.. needs replacing as it isn't cross platform.
//     {
//         char *gdpath=getenv("PATH");
//         int lenpath=(gdpath ? strlen(gdpath):1) + strlen(argv[0]);
//         char *nupath=new char[lenpath+20];
//
//         strcpy(nupath,"PATH=");
//         strcat(nupath,argv[0]);
//         // strip the executable name (xxx.exe)
//         char *epath=strrchr(nupath, '\\');
//         if (epath) *epath='\0'; // remove executable
//         else {
//             epath=strrchr(nupath, '/');
//             if (epath) *epath='\0'; // remove executable, UNIX style path
//         }
//         strcat(nupath,";");
//         strcat(nupath,gdpath);
//         _putenv(nupath);
//         delete [] nupath;
//     }
//     std::cout << "Path " << getenv("PATH") << std::endl;

    // configure the viewer from the commandline arguments, and eat any
    // parameters that have been matched.
    viewer.readCommandLine(commandLine);

    // configure the plugin registry from the commandline arguments, and
    // eat any parameters that have been matched.
    osgDB::readCommandLine(commandLine);

    // load the nodes from the commandline arguments.
    osg::Node* rootnode = osgDB::readNodeFiles(commandLine);
    if (!rootnode)
    {
        write_usage(osg::notify(osg::NOTICE),argv[0]);
        return 1;
    }

    // run optimization over the scene graph
    osgUtil::Optimizer optimzer;
    optimzer.optimize(rootnode);

    // add a viewport to the viewer and attach the scene graph.
    viewer.addViewport( rootnode );

    // register trackball, flight and drive.
    viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
    viewer.registerCameraManipulator(new osgGA::FlightManipulator);
    viewer.registerCameraManipulator(new osgGA::DriveManipulator);

    if( !pathfile.empty() ) {
    osgGA::AnimationPathManipulator *apm = new osgGA::AnimationPathManipulator(pathfile);
    if( apm->valid() )
            viewer.registerCameraManipulator(apm);
    else
        delete apm;
    }

    geoHeader *gh = dynamic_cast<geoHeader *>(rootnode);
    if (gh) { // it is a geo file, so set function to update its animation variables.
        ghand=new geodemoEventHandler();
        gh->setUserUpdate(dodynamics);
        viewer.prependEventHandler(ghand);
    } else { // maybe a group with geo models below.
        osg::Group *gpall=dynamic_cast<osg::Group *>(rootnode);
        if (gpall) {
            int nchild=gpall->getNumChildren();
            for (int i=0; i<nchild; i++) {
                osg::Node *nod=gpall->getChild(i);
                gh = dynamic_cast<geoHeader *>(nod);
                if (gh)
                {
                    ghand=new geodemoEventHandler();
                    gh->setUserUpdate(dodynamics);
                    viewer.prependEventHandler(ghand);
                }
            }
        }
    }
    osgUtil::SceneView *sc=viewer.getViewportSceneView(0);
    if (sc && camera_fov>0) {
        osg::Camera *cm=sc->getCamera();
        if (cm) cm->setFOV(camera_fov,camera_fov*(600.0f/800.0f),1.0f,1000.0f);
    }
        // open the viewer window.
    viewer.open();

    // fire up the event loop.
    viewer.run();

    return 0;
}
<commit_msg>Added code to the path to the executable, adding it into the libary and data file paths.<commit_after>// Geo demo written by Geoff Michel, November 2002.

#include <stdio.h>
#include <osg/GL>
#include <osgGLUT/glut>
#include <osgGLUT/Viewer>

#include <osg/Node>
#include <osg/Notify>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/AnimationPathManipulator>

#include <osgDB/WriteFile>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>

#include <osgUtil/Optimizer>

// currently not a satisfactory solution, but this is early days for the
// geo loader and having direct links with it.
#include "../../osgPlugins/geo/osgGeoAnimation.h"

void write_usage(std::ostream& out,const std::string& name)
{
    out << std::endl;
    out <<"usage:"<< std::endl;
    out <<"    "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
    out << std::endl;
    out <<"options:"<< std::endl;
    out <<"    -l libraryName      - load plugin of name libraryName"<< std::endl;
    out <<"                          i.e. -l osgdb_pfb"<< std::endl;
    out <<"                          Useful for loading reader/writers which can load"<< std::endl;
    out <<"                          other file formats in addition to its extension."<< std::endl;
    out <<"    -e extensionName    - load reader/wrter plugin for file extension"<< std::endl;
    out <<"                          i.e. -e pfb"<< std::endl;
    out <<"                          Useful short hand for specifying full library name as"<< std::endl;
    out <<"                          done with -l above, as it automatically expands to"<< std::endl;
    out <<"                          the full library name appropriate for each platform."<< std::endl;
    out <<std::endl;
    out <<"    -stereo             - switch on stereo rendering, using the default of,"<< std::endl;
    out <<"                          ANAGLYPHIC or the value set in the OSG_STEREO_MODE "<< std::endl;
    out <<"                          environmental variable. See doc/stereo.html for "<< std::endl;
    out <<"                          further details on setting up accurate stereo "<< std::endl;
    out <<"                          for your system. "<< std::endl;
    out <<"    -stereo ANAGLYPHIC  - switch on anaglyphic(red/cyan) stereo rendering."<< std::endl;
    out <<"    -stereo QUAD_BUFFER - switch on quad buffered stereo rendering."<< std::endl;
    out <<std::endl;
    out <<"    -stencil            - use a visual with stencil buffer enabled, this "<< std::endl;
    out <<"                          also allows the depth complexity statistics mode"<< std::endl;
    out <<"                          to be used (press 'p' three times to cycle to it)."<< std::endl;
    out <<"    -f                  - start with a full screen, borderless window." << std::endl;
    out <<"    -p  pathfile        - Use the AnimationPathManipulator (key binding '4') and use\n"
      "                          pathfile to define the animation path.  pathfile is an ascii\n"
      "                          file containing lines of eight floating point numbers representing\n"
      "                          time, position (x,y,z) and attitude (x,y,z,w as a quaternion)." << std::endl;
    out << std::endl;
}

//== event trapper gets events

class geodemoEventHandler : public osgGA::GUIEventHandler
{
public:

    geodemoEventHandler( )     { mouse_x=mouse_y=0;}
    virtual ~geodemoEventHandler( ) {}

    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
    {
        mouse_x=ea.getX();
        mouse_y=ea.getY();
        return false;

    }

    virtual void accept(osgGA::GUIEventHandlerVisitor& v)
    {
        v.visit(*this);
    }
    inline int getMouseX(void) {return mouse_x;};
    inline int getMouseY(void) {return mouse_y;};

private:
    int    mouse_x, mouse_y;
};

static geodemoEventHandler *ghand=NULL;
inline double DEG2RAD(const double val) { return val*0.0174532925199432957692369076848861;}
inline double RAD2DEG(const double val) { return val*57.2957795130823208767981548141052;}

double dodynamics(const double time, const double val, const std::string name)
{ // Each local variable named 'name' declared in the geo modeller is passed into here.
    // its current value is val; returns new value.  Time - elapsed time
    static double heading,speed; // these are only required for my 'dynamics'
    if (name == "xpos") {
        return (val+speed*sin(heading));
        //    std::cout << " nx " << (*itr->getValue()) ;
    } else if (name == "ypos") {
        return (val+speed*cos(heading));
        //    std::cout << " ny " << (*itr->getValue()) ;
    } else if (name == "sped") {
        speed=(0.00025*(ghand->getMouseY()-300)); // (*itr->getValue());
        return (speed);
    } else if (name == "heading") {
        heading-= 0.01*DEG2RAD(ghand->getMouseX()-400); // =DEG2RAD(*itr->getValue());
        return (RAD2DEG(heading));
    } else if (name == "conerot") {
        return ((ghand->getMouseX()-400));
    } else if (name == "planrot") {
        return ((ghand->getMouseY()-300)/200.0);
    } else if (name == "secint" || name == "minutehand"|| name == "hourhand") {
    //    std::cout << " updating " << name << " " << val << std::endl;
    }
    return val;
}

int main( int argc, char **argv )
{
    std::string pathfile;
    float camera_fov=-1;

    // initialize the GLUT
    glutInit( &argc, argv );

    if (argc<2)
    {
        write_usage(std::cout,argv[0]);
        return 1;
    }

    // create the commandline args.
    std::vector<std::string> commandLine;
    for(int i=1;i<argc;++i) {
    if( std::string(argv[i]) == "-p" ) {
        if( (i+1) >= argc ) {
        write_usage( std::cout, argv[0]);
            return 1;
        }
        else
        pathfile = std::string(argv[++i]);
    } else if( std::string(argv[i]) == "-fov" ) {
        camera_fov=atof(argv[i+1]);
        ++i; // skip the value
    }
    else
        commandLine.push_back(argv[i]);
    }

    // initialize the viewer.
    osgGLUT::Viewer viewer;
    viewer.setWindowTitle(argv[0]);

    // get the path of the executable and use it to set internal data and library paths.
    std::string executablePath = osgDB::getFilePath(argv[0]);
    if (!executablePath.empty())
    {
        std::osg::notify(osg::NOTICE) << "Adding executable path '"<<executablePath<<"' to OpenSceneGraph data and library file paths."<<std::endl;
        osgDB::getDataFilePathList().push_front(executablePath);
        osgDB::getLibraryFilePathList().push_front(executablePath);
    }

    // configure the viewer from the commandline arguments, and eat any
    // parameters that have been matched.
    viewer.readCommandLine(commandLine);

    // configure the plugin registry from the commandline arguments, and
    // eat any parameters that have been matched.
    osgDB::readCommandLine(commandLine);

    // load the nodes from the commandline arguments.
    osg::Node* rootnode = osgDB::readNodeFiles(commandLine);
    if (!rootnode)
    {
        write_usage(osg::notify(osg::NOTICE),argv[0]);
        return 1;
    }

    // run optimization over the scene graph
    osgUtil::Optimizer optimzer;
    optimzer.optimize(rootnode);

    // add a viewport to the viewer and attach the scene graph.
    viewer.addViewport( rootnode );

    // register trackball, flight and drive.
    viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
    viewer.registerCameraManipulator(new osgGA::FlightManipulator);
    viewer.registerCameraManipulator(new osgGA::DriveManipulator);

    if( !pathfile.empty() ) {
    osgGA::AnimationPathManipulator *apm = new osgGA::AnimationPathManipulator(pathfile);
    if( apm->valid() )
            viewer.registerCameraManipulator(apm);
    else
        delete apm;
    }

    geoHeader *gh = dynamic_cast<geoHeader *>(rootnode);
    if (gh) { // it is a geo file, so set function to update its animation variables.
        ghand=new geodemoEventHandler();
        gh->setUserUpdate(dodynamics);
        viewer.prependEventHandler(ghand);
    } else { // maybe a group with geo models below.
        osg::Group *gpall=dynamic_cast<osg::Group *>(rootnode);
        if (gpall) {
            int nchild=gpall->getNumChildren();
            for (int i=0; i<nchild; i++) {
                osg::Node *nod=gpall->getChild(i);
                gh = dynamic_cast<geoHeader *>(nod);
                if (gh)
                {
                    ghand=new geodemoEventHandler();
                    gh->setUserUpdate(dodynamics);
                    viewer.prependEventHandler(ghand);
                }
            }
        }
    }
    osgUtil::SceneView *sc=viewer.getViewportSceneView(0);
    if (sc && camera_fov>0) {
        osg::Camera *cm=sc->getCamera();
        if (cm) cm->setFOV(camera_fov,camera_fov*(600.0f/800.0f),1.0f,1000.0f);
    }
        // open the viewer window.
    viewer.open();

    // fire up the event loop.
    viewer.run();

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Generated with the GUSIConfig application and then hand-modified by jack.
 */

#define GUSI_SOURCE
#include <GUSIConfig.h>
#include <sys/cdefs.h>
#include <Resources.h>

#include "Python.h"
#include "macglue.h"
#include "pythonresources.h"

static void
PyMac_GUSISpin(bool wait)
{
	static Boolean	inForeground = true;
	int		maxsleep = 6;	/* 6 ticks is "normal" sleeptime */

	if (PyMac_ConsoleIsDead) return;

	if ( !wait )
		maxsleep = 0;

	PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
}

/* Declarations of Socket Factories */

__BEGIN_DECLS
void GUSIwithInetSockets();
void GUSIwithLocalSockets();
void GUSIwithMTInetSockets();
void GUSIwithMTTcpSockets();
void GUSIwithMTUdpSockets();
void GUSIwithOTInetSockets();
void GUSIwithOTTcpSockets();
void GUSIwithOTUdpSockets();
void GUSIwithPPCSockets();
void GUSISetupFactories();
__END_DECLS

/* Configure Socket Factories */

void GUSISetupFactories()
{
#ifdef GUSISetupFactories_BeginHook
	GUSISetupFactories_BeginHook
#endif
#if 1 || TARGET_API_MAC_CARBON
	GUSIwithInetSockets();
#else
	GUSIwithMTInetSockets();
#endif
#ifdef GUSISetupFactories_EndHook
	GUSISetupFactories_EndHook
#endif
}

/* Declarations of File Devices */

__BEGIN_DECLS
void GUSIwithDConSockets();
void GUSIwithNullSockets();
void GUSISetupDevices();
__END_DECLS

/* Configure File Devices */

void GUSISetupDevices()
{
#ifdef GUSISetupDevices_BeginHook
	GUSISetupDevices_BeginHook
#endif
#ifdef GUSISetupDevices_EndHook
	GUSISetupDevices_EndHook
#endif
}

#ifndef __cplusplus
#error GUSISetupConfig() needs to be written in C++
#endif

GUSIConfiguration::FileSuffix	sSuffices[] = {
	"", '????', '????'
};
extern "C" void GUSISetupConfig()
{
	Handle h;
	short oldrh, prefrh = -1;
	short resource_id = GUSIConfiguration::kNoResource;

	oldrh = CurResFile();

	/* Try override from the application resource fork */
	UseResFile(PyMac_AppRefNum);
	h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID);
	if ( h ) {
		resource_id = GUSIOPTIONSOVERRIDE_ID;
	} else {
		/* Next try normal resource from preference file */
		prefrh = PyMac_OpenPrefFile();
		h = Get1Resource('GU\267I', GUSIOPTIONS_ID);
		if ( h ) {
			resource_id = GUSIOPTIONS_ID;
		} else {
			/* Finally try normal resource from application */
			if ( prefrh != -1 ) {
				CloseResFile(prefrh);
				prefrh = -1;
			}
			resource_id = GUSIOPTIONS_ID;
		}
	}

	/* Now we have the right resource file topmost and the id. Init GUSI. */
	GUSIConfiguration * config =
		GUSIConfiguration::CreateInstance(resource_id);

	/* Finally restore the old resource file */
   	if ( prefrh != -1) CloseResFile(prefrh);
	UseResFile(oldrh);

	config->ConfigureDefaultTypeCreator('TEXT', 'R*ch');
#if 0
	config->ConfigureSuffices(
		sizeof(sSuffices)/sizeof(GUSIConfiguration::FileSuffix)-1, sSuffices);
#endif
	config->ConfigureAutoInitGraf(false);
	config->ConfigureAutoSpin(false);
	config->ConfigureHandleAppleEvents(false);
	config->ConfigureSigInt(false);
	config->ConfigureSigPipe(true);

	GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);

}

/**************** END GUSI CONFIGURATION *************************/
<commit_msg>Got rid of ifdefs to enable MacTCP GUSI support, Open Transport always works fine nowadays.<commit_after>/*
 * Generated with the GUSIConfig application and then hand-modified by jack.
 */

#define GUSI_SOURCE
#include <GUSIConfig.h>
#include <sys/cdefs.h>
#include <Resources.h>

#include "Python.h"
#include "macglue.h"
#include "pythonresources.h"

static void
PyMac_GUSISpin(bool wait)
{
	static Boolean	inForeground = true;
	int		maxsleep = 6;	/* 6 ticks is "normal" sleeptime */

	if (PyMac_ConsoleIsDead) return;

	if ( !wait )
		maxsleep = 0;

	PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
}

/* Declarations of Socket Factories */

__BEGIN_DECLS
void GUSIwithInetSockets();
void GUSIwithLocalSockets();
void GUSIwithMTInetSockets();
void GUSIwithMTTcpSockets();
void GUSIwithMTUdpSockets();
void GUSIwithOTInetSockets();
void GUSIwithOTTcpSockets();
void GUSIwithOTUdpSockets();
void GUSIwithPPCSockets();
void GUSISetupFactories();
__END_DECLS

/* Configure Socket Factories */

void GUSISetupFactories()
{
#ifdef GUSISetupFactories_BeginHook
	GUSISetupFactories_BeginHook
#endif
	GUSIwithInetSockets();
#ifdef GUSISetupFactories_EndHook
	GUSISetupFactories_EndHook
#endif
}

/* Declarations of File Devices */

__BEGIN_DECLS
void GUSIwithDConSockets();
void GUSIwithNullSockets();
void GUSISetupDevices();
__END_DECLS

/* Configure File Devices */

void GUSISetupDevices()
{
#ifdef GUSISetupDevices_BeginHook
	GUSISetupDevices_BeginHook
#endif
#ifdef GUSISetupDevices_EndHook
	GUSISetupDevices_EndHook
#endif
}

#ifndef __cplusplus
#error GUSISetupConfig() needs to be written in C++
#endif

GUSIConfiguration::FileSuffix	sSuffices[] = {
	"", '????', '????'
};
extern "C" void GUSISetupConfig()
{
	Handle h;
	short oldrh, prefrh = -1;
	short resource_id = GUSIConfiguration::kNoResource;

	oldrh = CurResFile();

	/* Try override from the application resource fork */
	UseResFile(PyMac_AppRefNum);
	h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID);
	if ( h ) {
		resource_id = GUSIOPTIONSOVERRIDE_ID;
	} else {
		/* Next try normal resource from preference file */
		prefrh = PyMac_OpenPrefFile();
		h = Get1Resource('GU\267I', GUSIOPTIONS_ID);
		if ( h ) {
			resource_id = GUSIOPTIONS_ID;
		} else {
			/* Finally try normal resource from application */
			if ( prefrh != -1 ) {
				CloseResFile(prefrh);
				prefrh = -1;
			}
			resource_id = GUSIOPTIONS_ID;
		}
	}

	/* Now we have the right resource file topmost and the id. Init GUSI. */
	GUSIConfiguration * config =
		GUSIConfiguration::CreateInstance(resource_id);

	/* Finally restore the old resource file */
   	if ( prefrh != -1) CloseResFile(prefrh);
	UseResFile(oldrh);

	config->ConfigureDefaultTypeCreator('TEXT', 'R*ch');
#if 0
	config->ConfigureSuffices(
		sizeof(sSuffices)/sizeof(GUSIConfiguration::FileSuffix)-1, sSuffices);
#endif
	config->ConfigureAutoInitGraf(false);
	config->ConfigureAutoSpin(false);
	config->ConfigureHandleAppleEvents(false);
	config->ConfigureSigInt(false);
	config->ConfigureSigPipe(true);

	GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);

}

/**************** END GUSI CONFIGURATION *************************/
<|endoftext|>