2012-11-15 16:51:55 +00:00
|
|
|
/* FasTC
|
|
|
|
* Copyright (c) 2012 University of North Carolina at Chapel Hill. All rights reserved.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software and its documentation for educational,
|
|
|
|
* research, and non-profit purposes, without fee, and without a written agreement is hereby granted,
|
|
|
|
* provided that the above copyright notice, this paragraph, and the following four paragraphs appear
|
|
|
|
* in all copies.
|
|
|
|
*
|
|
|
|
* Permission to incorporate this software into commercial products may be obtained by contacting the
|
|
|
|
* authors or the Office of Technology Development at the University of North Carolina at Chapel Hill <otd@unc.edu>.
|
|
|
|
*
|
|
|
|
* This software program and documentation are copyrighted by the University of North Carolina at Chapel Hill.
|
|
|
|
* The software program and documentation are supplied "as is," without any accompanying services from the
|
|
|
|
* University of North Carolina at Chapel Hill or the authors. The University of North Carolina at Chapel Hill
|
|
|
|
* and the authors do not warrant that the operation of the program will be uninterrupted or error-free. The
|
|
|
|
* end-user understands that the program was developed for research purposes and is advised not to rely
|
|
|
|
* exclusively on the program for any reason.
|
|
|
|
*
|
|
|
|
* IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE AUTHORS BE LIABLE TO ANY PARTY FOR
|
|
|
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE
|
|
|
|
* USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE
|
|
|
|
* AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
|
|
|
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
|
|
|
|
* STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY
|
|
|
|
* OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
|
|
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
|
|
|
*
|
|
|
|
* Please send all BUG REPORTS to <pavel@cs.unc.edu>.
|
|
|
|
*
|
|
|
|
* The authors may be contacted via:
|
|
|
|
*
|
|
|
|
* Pavel Krajcevski
|
|
|
|
* Dept of Computer Science
|
|
|
|
* 201 S Columbia St
|
|
|
|
* Frederick P. Brooks, Jr. Computer Science Bldg
|
|
|
|
* Chapel Hill, NC 27599-3175
|
|
|
|
* USA
|
|
|
|
*
|
|
|
|
* <http://gamma.cs.unc.edu/FasTC/>
|
|
|
|
*/
|
|
|
|
|
2012-10-06 21:52:26 +00:00
|
|
|
#include "BlockStats.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
2013-03-21 03:40:35 +00:00
|
|
|
#include <algorithm>
|
2012-10-06 21:52:26 +00:00
|
|
|
|
2012-10-07 04:34:06 +00:00
|
|
|
#include "FileStream.h"
|
2013-01-27 19:36:19 +00:00
|
|
|
#include "Thread.h"
|
2012-10-07 04:34:06 +00:00
|
|
|
|
2012-10-06 21:52:26 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// BlockStat implementation
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-10-08 17:16:41 +00:00
|
|
|
BlockStat::BlockStat(const CHAR *statName, int stat)
|
2013-01-28 21:57:15 +00:00
|
|
|
: m_Type(eType_Int)
|
|
|
|
, m_IntStat(stat)
|
2012-10-07 02:25:49 +00:00
|
|
|
{
|
2012-11-07 21:52:06 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
strncpy_s(m_StatName, statName, kStatNameSz);
|
|
|
|
#else
|
2012-10-07 02:25:49 +00:00
|
|
|
strncpy(m_StatName, statName, kStatNameSz);
|
2012-11-07 21:52:06 +00:00
|
|
|
#endif
|
2012-10-07 02:25:49 +00:00
|
|
|
}
|
|
|
|
|
2012-10-08 17:16:41 +00:00
|
|
|
BlockStat::BlockStat(const CHAR *statName, double stat)
|
2013-01-28 21:57:15 +00:00
|
|
|
: m_Type(eType_Float)
|
|
|
|
, m_FloatStat(stat)
|
2012-10-06 21:52:26 +00:00
|
|
|
{
|
2012-11-07 21:52:06 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
strncpy_s(m_StatName, statName, kStatNameSz);
|
|
|
|
#else
|
2012-10-06 21:52:26 +00:00
|
|
|
strncpy(m_StatName, statName, kStatNameSz);
|
2012-11-07 21:52:06 +00:00
|
|
|
#endif
|
2012-10-06 21:52:26 +00:00
|
|
|
}
|
|
|
|
|
2012-10-08 17:16:41 +00:00
|
|
|
BlockStat::BlockStat(const BlockStat &other) : m_Type(other.m_Type) {
|
2012-10-06 21:52:26 +00:00
|
|
|
memcpy(this, &other, sizeof(*this));
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockStat &BlockStat::operator=(const BlockStat &other) {
|
|
|
|
memcpy(this, &other, sizeof(*this));
|
2012-11-07 21:52:06 +00:00
|
|
|
return *this;
|
2012-10-06 21:52:26 +00:00
|
|
|
}
|
|
|
|
|
2012-11-07 21:52:06 +00:00
|
|
|
void BlockStat::ToString(CHAR *buf, int bufSz) const {
|
2012-11-01 22:56:13 +00:00
|
|
|
switch(m_Type) {
|
|
|
|
case BlockStat::eType_Float:
|
2012-11-07 21:52:06 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
_sntprintf_s(buf, bufSz, _TRUNCATE, "%s,%f", m_StatName, m_FloatStat);
|
|
|
|
#else
|
2012-11-01 22:56:13 +00:00
|
|
|
snprintf(buf, bufSz, "%s,%f", m_StatName, m_FloatStat);
|
2012-11-07 21:52:06 +00:00
|
|
|
#endif
|
2012-11-01 22:56:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BlockStat::eType_Int:
|
2012-11-07 21:52:06 +00:00
|
|
|
#ifdef _MSC_VER
|
2013-01-28 22:49:57 +00:00
|
|
|
_sntprintf_s(buf, bufSz, _TRUNCATE, "%s,%lu", m_StatName, (unsigned long)m_IntStat);
|
2012-11-07 21:52:06 +00:00
|
|
|
#else
|
2013-01-28 22:49:57 +00:00
|
|
|
snprintf(buf, bufSz, "%s,%lu", m_StatName, (unsigned long)m_IntStat);
|
2012-11-07 21:52:06 +00:00
|
|
|
#endif
|
2012-11-01 22:56:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(!"Unknown stat type!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-06 21:52:26 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// BlockStat Manager Implementation
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2013-01-27 19:36:19 +00:00
|
|
|
void BlockStatManager::Copy(const BlockStatManager &other) {
|
2013-01-28 21:57:15 +00:00
|
|
|
// This is a bug. If we copy the manager then all of the lists and pointers
|
|
|
|
// become shared and can cause dereferencing issues. Check to see where you're
|
|
|
|
// copying this class and make sure to actually create a new instance.
|
|
|
|
assert(!"We shouldn't be copying these in this manner!");
|
|
|
|
|
|
|
|
m_BlockStatList = new BlockStatList(*other.m_BlockStatList);
|
|
|
|
m_BlockStatListSz = other.m_BlockStatListSz;
|
|
|
|
m_NextBlock = other.m_NextBlock;
|
|
|
|
|
|
|
|
// If we do copy them, then make sure that we are actually using the exact same
|
|
|
|
// pointers for our synchronization primitives... otherwise we could run into
|
|
|
|
// deadlock issues.
|
|
|
|
m_Mutex = other.m_Mutex;
|
2013-01-27 19:36:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BlockStatManager::BlockStatManager(const BlockStatManager &other) {
|
|
|
|
Copy(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockStatManager &BlockStatManager::operator=(const BlockStatManager &other) {
|
|
|
|
m_Counter = other.m_Counter;
|
|
|
|
Copy(other);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2012-10-06 21:52:26 +00:00
|
|
|
BlockStatManager::BlockStatManager(int nBlocks)
|
2013-03-21 03:40:35 +00:00
|
|
|
: m_BlockStatListSz(std::max(nBlocks, 0))
|
2012-10-06 21:52:26 +00:00
|
|
|
, m_NextBlock(0)
|
2013-01-27 19:36:19 +00:00
|
|
|
, m_Mutex(new TCMutex)
|
2012-10-06 21:52:26 +00:00
|
|
|
{
|
|
|
|
m_BlockStatList = new BlockStatList[m_BlockStatListSz];
|
|
|
|
if(!m_BlockStatList) {
|
|
|
|
fprintf(stderr, "Out of memory!\n");
|
|
|
|
assert(false);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockStatManager::~BlockStatManager() {
|
|
|
|
if(m_Counter.GetRefCount() == 0) {
|
|
|
|
delete [] m_BlockStatList;
|
|
|
|
}
|
2013-01-27 19:36:19 +00:00
|
|
|
|
|
|
|
if(m_Mutex)
|
|
|
|
{
|
|
|
|
delete m_Mutex;
|
|
|
|
m_Mutex = 0;
|
|
|
|
}
|
2012-10-06 21:52:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 BlockStatManager::BeginBlock() {
|
2012-10-07 04:34:06 +00:00
|
|
|
if(m_NextBlock == m_BlockStatListSz) {
|
2012-10-06 21:52:26 +00:00
|
|
|
fprintf(stderr, "WARNING -- BlockStatManager::BeginBlock(), reached end of block list.\n");
|
|
|
|
assert(false);
|
2012-10-07 04:34:06 +00:00
|
|
|
return m_NextBlock-1;
|
2012-10-06 21:52:26 +00:00
|
|
|
}
|
|
|
|
|
2013-01-27 19:36:19 +00:00
|
|
|
TCLock lock (*m_Mutex);
|
2012-10-06 21:52:26 +00:00
|
|
|
return m_NextBlock++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlockStatManager::AddStat(uint32 blockIdx, const BlockStat &stat) {
|
|
|
|
if(blockIdx >= m_BlockStatListSz) {
|
|
|
|
fprintf(stderr, "WARNING -- BlockStatManager::AddStat(), block index out of bounds!\n");
|
|
|
|
assert(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-27 19:36:19 +00:00
|
|
|
TCLock lock (*m_Mutex);
|
2012-10-06 21:52:26 +00:00
|
|
|
m_BlockStatList[blockIdx].AddStat(stat);
|
|
|
|
}
|
|
|
|
|
2012-11-01 22:56:13 +00:00
|
|
|
void BlockStatManager::ToFile(const CHAR *filename) {
|
|
|
|
|
|
|
|
FileStream fstr (filename, eFileMode_Write);
|
|
|
|
|
2012-11-07 21:52:06 +00:00
|
|
|
for(uint32 i = 0; i < m_BlockStatListSz; i++) {
|
2012-11-01 22:56:13 +00:00
|
|
|
const BlockStatList *head = &(m_BlockStatList[i]);
|
|
|
|
while(head) {
|
|
|
|
BlockStat s = head->GetStat();
|
|
|
|
|
|
|
|
CHAR statStr[256];
|
|
|
|
s.ToString(statStr, 256);
|
|
|
|
|
|
|
|
CHAR str[256];
|
2012-11-07 21:52:06 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
_sntprintf_s(str, 256, _TRUNCATE, "%d,%s\n", i, statStr);
|
|
|
|
#else
|
2012-11-01 22:56:13 +00:00
|
|
|
snprintf(str, 256, "%d,%s\n", i, statStr);
|
2012-11-07 21:52:06 +00:00
|
|
|
#endif
|
2012-11-01 22:56:13 +00:00
|
|
|
|
2012-11-07 21:52:06 +00:00
|
|
|
uint32 strLen = uint32(strlen(str));
|
2012-11-01 22:56:13 +00:00
|
|
|
if(strLen > 255) {
|
2012-11-07 21:52:06 +00:00
|
|
|
str[255] = '\n';
|
|
|
|
strLen = 256;
|
2012-11-01 22:56:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fstr.Write((uint8 *)str, strLen);
|
|
|
|
|
|
|
|
head = head->GetTail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-06 21:52:26 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// BlockStat List Implementation
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const CHAR *kNullBlockString = "NULL_BLOCK_STAT";
|
2012-11-07 21:52:06 +00:00
|
|
|
static const uint32 kNullBlockStringLength = uint32(strlen(kNullBlockString));
|
2012-10-06 21:52:26 +00:00
|
|
|
|
|
|
|
BlockStatManager::BlockStatList::BlockStatList()
|
|
|
|
: m_Tail(0)
|
|
|
|
, m_Stat(kNullBlockString, 0.0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
BlockStatManager::BlockStatList::BlockStatList(const BlockStat &stat)
|
|
|
|
: m_Tail(0)
|
|
|
|
, m_Stat(stat)
|
|
|
|
{
|
2013-01-27 19:36:19 +00:00
|
|
|
assert(!"If you're copying a block stat list then you're probably not using them properly.");
|
2012-10-06 21:52:26 +00:00
|
|
|
}
|
|
|
|
|
2013-01-27 19:36:19 +00:00
|
|
|
BlockStatManager::BlockStatList::BlockStatList(const BlockStatList &other)
|
|
|
|
: m_Tail(new BlockStatList(*other.m_Tail))
|
|
|
|
, m_Stat(other.m_Stat)
|
|
|
|
{}
|
|
|
|
|
2012-10-06 21:52:26 +00:00
|
|
|
BlockStatManager::BlockStatList::~BlockStatList() {
|
|
|
|
if(m_Counter.GetRefCount() == 0 && m_Tail) {
|
|
|
|
delete m_Tail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlockStatManager::BlockStatList::AddStat(const BlockStat &stat) {
|
2012-11-01 22:56:13 +00:00
|
|
|
|
2012-10-07 02:25:49 +00:00
|
|
|
if(strncmp(stat.m_StatName, m_Stat.m_StatName, BlockStat::kStatNameSz) == 0) {
|
|
|
|
m_Stat = stat;
|
|
|
|
}
|
2012-10-07 04:34:06 +00:00
|
|
|
else if(m_Tail) {
|
2012-10-06 21:52:26 +00:00
|
|
|
m_Tail->AddStat(stat);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(strncmp(m_Stat.m_StatName, kNullBlockString, kNullBlockStringLength) == 0) {
|
|
|
|
m_Stat = stat;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_Tail = new BlockStatList(stat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|