Remove BlockStatManager in favor of ostreams

This commit is contained in:
Pavel Krajcevski 2013-09-28 21:42:24 -04:00
parent 7bd54105e4
commit 13af957ab9
9 changed files with 35 additions and 459 deletions

View File

@ -52,13 +52,11 @@
SET( SOURCES
"src/TexComp.cpp"
"src/CompressedImage.cpp"
"src/BlockStats.cpp"
)
SET( HEADERS
"include/TexComp.h"
"include/CompressedImage.h"
"include/BlockStats.h"
"src/CompressionFuncs.h"
)

View File

@ -1,148 +0,0 @@
/* FasTC
* Copyright (c) 2013 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/>
*/
#ifndef __BLOCK_STATS_H__
#define __BLOCK_STATS_H__
#include "TexCompTypes.h"
#include "ReferenceCounter.h"
///////////////////////////////////////////////////////////////////////////////
//
// Forward declarations
//
///////////////////////////////////////////////////////////////////////////////
class TCMutex;
///////////////////////////////////////////////////////////////////////////////
//
// class BlockStat
//
///////////////////////////////////////////////////////////////////////////////
struct BlockStat {
friend class BlockStatManager;
public:
BlockStat(const CHAR *statName, int);
BlockStat(const CHAR *statName, double stat);
BlockStat(const BlockStat &);
BlockStat &operator=(const BlockStat &);
void ToString(CHAR *buf, int bufSz) const;
private:
const enum Type {
eType_Float,
eType_Int,
kNumTypes
} m_Type;
static const int kStatNameSz = 32;
CHAR m_StatName[kStatNameSz];
union {
uint64 m_IntStat;
double m_FloatStat;
};
};
class BlockStatManager {
public:
BlockStatManager(int nBlocks);
BlockStatManager(const BlockStatManager &);
BlockStatManager &operator=(const BlockStatManager &);
~BlockStatManager();
// A thread-safe version that returns a list index for recording
// block statistics.
uint32 BeginBlock();
// Add a stat for a given block. This is thread-safe
void AddStat(uint32 blockIdx, const BlockStat &stat);
// Write the statistics to a file.
void ToFile(const CHAR *filename);
private:
class BlockStatList {
public:
BlockStatList();
BlockStatList(const BlockStatList &other);
~BlockStatList();
void AddStat(const BlockStat &stat);
BlockStat GetStat() const { return m_Stat; }
const BlockStatList *GetTail() const { return m_Tail; }
private:
BlockStatList(const BlockStat &stat);
BlockStatList *m_Tail;
BlockStat m_Stat;
ReferenceCounter m_Counter;
} *m_BlockStatList;
uint32 m_BlockStatListSz;
uint32 m_NextBlock;
ReferenceCounter m_Counter;
TCMutex *m_Mutex;
// Note: we probably shouldn't call this...
void Copy(const BlockStatManager &);
};
#endif // __BLOCK_STATS_H__

View File

@ -47,10 +47,11 @@
#include "CompressedImage.h"
#include "CompressionJob.h"
#include <iosfwd>
// Forward declarations
class Image;
class ImageFile;
class BlockStatManager;
struct SCompressionSettings {
SCompressionSettings(); // defaults
@ -85,11 +86,9 @@ struct SCompressionSettings {
// in the platform and compiler will provide synchronization.
bool bUseAtomics;
// This is an optinal pointer to a stat manager class. If
// instantiated and the proper function pointer is defined
// then the compression routine that collects the stats will
// be called.
BlockStatManager *pStatManager;
// This is the output stream with which we should output the logs for the
// compression functions.
std::ostream *logStream;
};
extern CompressedImage *CompressImage(Image *img, const SCompressionSettings &settings);

View File

@ -1,273 +0,0 @@
/* 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/>
*/
#include "BlockStats.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <algorithm>
#include "FileStream.h"
#include "Thread.h"
////////////////////////////////////////////////////////////////////////////////
//
// BlockStat implementation
//
////////////////////////////////////////////////////////////////////////////////
BlockStat::BlockStat(const CHAR *statName, int stat)
: m_Type(eType_Int)
, m_IntStat(stat)
{
#ifdef _MSC_VER
strncpy_s(m_StatName, statName, kStatNameSz);
#else
strncpy(m_StatName, statName, kStatNameSz);
#endif
}
BlockStat::BlockStat(const CHAR *statName, double stat)
: m_Type(eType_Float)
, m_FloatStat(stat)
{
#ifdef _MSC_VER
strncpy_s(m_StatName, statName, kStatNameSz);
#else
strncpy(m_StatName, statName, kStatNameSz);
#endif
}
BlockStat::BlockStat(const BlockStat &other) : m_Type(other.m_Type) {
memcpy(this, &other, sizeof(*this));
}
BlockStat &BlockStat::operator=(const BlockStat &other) {
memcpy(this, &other, sizeof(*this));
return *this;
}
void BlockStat::ToString(CHAR *buf, int bufSz) const {
switch(m_Type) {
case BlockStat::eType_Float:
#ifdef _MSC_VER
_sntprintf_s(buf, bufSz, _TRUNCATE, "%s,%f", m_StatName, m_FloatStat);
#else
snprintf(buf, bufSz, "%s,%f", m_StatName, m_FloatStat);
#endif
break;
case BlockStat::eType_Int:
#ifdef _MSC_VER
_sntprintf_s(buf, bufSz, _TRUNCATE, "%s,%lu", m_StatName, (unsigned long)m_IntStat);
#else
snprintf(buf, bufSz, "%s,%lu", m_StatName, (unsigned long)m_IntStat);
#endif
break;
default:
assert(!"Unknown stat type!");
break;
}
}
////////////////////////////////////////////////////////////////////////////////
//
// BlockStat Manager Implementation
//
////////////////////////////////////////////////////////////////////////////////
void BlockStatManager::Copy(const BlockStatManager &other) {
// 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;
}
BlockStatManager::BlockStatManager(const BlockStatManager &other) {
Copy(other);
}
BlockStatManager &BlockStatManager::operator=(const BlockStatManager &other) {
m_Counter = other.m_Counter;
Copy(other);
return *this;
}
BlockStatManager::BlockStatManager(int nBlocks)
: m_BlockStatListSz(std::max(nBlocks, 0))
, m_NextBlock(0)
, m_Mutex(new TCMutex)
{
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;
}
if(m_Mutex)
{
delete m_Mutex;
m_Mutex = 0;
}
}
uint32 BlockStatManager::BeginBlock() {
if(m_NextBlock == m_BlockStatListSz) {
fprintf(stderr, "WARNING -- BlockStatManager::BeginBlock(), reached end of block list.\n");
assert(false);
return m_NextBlock-1;
}
TCLock lock (*m_Mutex);
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;
}
TCLock lock (*m_Mutex);
m_BlockStatList[blockIdx].AddStat(stat);
}
void BlockStatManager::ToFile(const CHAR *filename) {
FileStream fstr (filename, eFileMode_Write);
for(uint32 i = 0; i < m_BlockStatListSz; i++) {
const BlockStatList *head = &(m_BlockStatList[i]);
while(head) {
BlockStat s = head->GetStat();
CHAR statStr[256];
s.ToString(statStr, 256);
CHAR str[256];
#ifdef _MSC_VER
_sntprintf_s(str, 256, _TRUNCATE, "%d,%s\n", i, statStr);
#else
snprintf(str, 256, "%d,%s\n", i, statStr);
#endif
uint32 strLen = uint32(strlen(str));
if(strLen > 255) {
str[255] = '\n';
strLen = 256;
}
fstr.Write((uint8 *)str, strLen);
head = head->GetTail();
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// BlockStat List Implementation
//
////////////////////////////////////////////////////////////////////////////////
static const CHAR *kNullBlockString = "NULL_BLOCK_STAT";
static const uint32 kNullBlockStringLength = uint32(strlen(kNullBlockString));
BlockStatManager::BlockStatList::BlockStatList()
: m_Tail(0)
, m_Stat(kNullBlockString, 0.0)
{ }
BlockStatManager::BlockStatList::BlockStatList(const BlockStat &stat)
: m_Tail(0)
, m_Stat(stat)
{
assert(!"If you're copying a block stat list then you're probably not using them properly.");
}
BlockStatManager::BlockStatList::BlockStatList(const BlockStatList &other)
: m_Tail(new BlockStatList(*other.m_Tail))
, m_Stat(other.m_Stat)
{}
BlockStatManager::BlockStatList::~BlockStatList() {
if(m_Counter.GetRefCount() == 0 && m_Tail) {
delete m_Tail;
}
}
void BlockStatManager::BlockStatList::AddStat(const BlockStat &stat) {
if(strncmp(stat.m_StatName, m_Stat.m_StatName, BlockStat::kStatNameSz) == 0) {
m_Stat = stat;
}
else if(m_Tail) {
m_Tail->AddStat(stat);
}
else {
if(strncmp(m_Stat.m_StatName, kNullBlockString, kNullBlockStringLength) == 0) {
m_Stat = stat;
}
else {
m_Tail = new BlockStatList(stat);
}
}
}

View File

@ -158,10 +158,10 @@ static double CompressImageInSerial(
// !FIXME! We're assuming that we have 4x4 blocks here...
CompressionJob cj (imgData, outBuf, imgWidth, imgHeight);
if(fStats && settings.pStatManager) {
if(fStats && settings.logStream) {
// !FIXME! Actually use the stat manager...
//(*fStats)(cj, *(settings.pStatManager));
(*fStats)(cj, &std::cout);
(*fStats)(cj, settings.logStream);
}
else {
(*f)(cj);
@ -293,8 +293,8 @@ static double CompressImageWithThreads(
CompressionFuncWithStats fStats = ChooseFuncFromSettingsWithStats(settings);
double cmpTimeTotal = 0.0;
if(fStats && settings.pStatManager) {
ThreadGroup tgrp (settings.iNumThreads, imgData, imgDataSz, fStats, *(settings.pStatManager), outBuf);
if(fStats && settings.logStream) {
ThreadGroup tgrp (settings.iNumThreads, imgData, imgDataSz, fStats, settings.logStream, outBuf);
cmpTimeTotal = CompressThreadGroup(tgrp, settings);
}
else {
@ -316,7 +316,7 @@ static double CompressImageWithWorkerQueue(
CompressionFuncWithStats fStats = ChooseFuncFromSettingsWithStats(settings);
double cmpTimeTotal = 0.0;
if(fStats && settings.pStatManager) {
if(fStats && settings.logStream) {
WorkerQueue wq (
settings.iNumCompressions,
settings.iNumThreads,
@ -324,7 +324,7 @@ static double CompressImageWithWorkerQueue(
imgData,
imgDataSz,
fStats,
*(settings.pStatManager),
settings.logStream,
outBuf
);
@ -405,13 +405,13 @@ bool CompressImageData(
uint32 numThreads = settings.iNumThreads;
if(settings.format == eCompressionFormat_PVRTC &&
(settings.iNumThreads > 1 || settings.pStatManager)) {
(settings.iNumThreads > 1 || settings.logStream)) {
if(settings.iNumThreads > 1) {
ReportError("WARNING - PVRTC compressor does not support multithreading.");
numThreads = 1;
}
if(settings.pStatManager) {
if(settings.logStream) {
ReportError("WARNING - PVRTC compressor does not support stat collection.");
}
}

View File

@ -58,7 +58,7 @@ CmpThread::CmpThread()
, m_Height(0)
, m_CmpFunc(NULL)
, m_CmpFuncWithStats(NULL)
, m_StatManager(NULL)
, m_LogStream(NULL)
, m_OutBuf(NULL)
, m_InBuf(NULL)
, m_ParentExitFlag(NULL)
@ -74,7 +74,7 @@ void CmpThread::operator()() {
return;
}
if(!(m_CmpFunc || (m_CmpFuncWithStats && m_StatManager))) {
if(!(m_CmpFunc || (m_CmpFuncWithStats && m_LogStream))) {
fprintf(stderr, "Incorrect thread function pointer.\n");
return;
}
@ -91,9 +91,7 @@ void CmpThread::operator()() {
if(m_CmpFunc)
(*m_CmpFunc)(cj);
else
// !FIXME! Actually use the block stat manager...
// (*m_CmpFuncWithStats)(cj, *m_StatManager);
(*m_CmpFuncWithStats)(cj, &std::cout);
(*m_CmpFuncWithStats)(cj, m_LogStream);
{
TCLock lock(*m_ParentCounterLock);
@ -152,7 +150,7 @@ ThreadGroup::ThreadGroup(
const unsigned char *inBuf,
unsigned int inBufSz,
CompressionFuncWithStats func,
BlockStatManager &statManager,
std::ostream *logStream,
unsigned char *outBuf
)
: m_StartBarrier(new TCBarrier(numThreads + 1))
@ -186,7 +184,7 @@ ThreadGroup::ThreadGroup(
m_Threads[i].m_StartBarrier = m_StartBarrier;
m_Threads[i].m_ParentExitFlag = &m_ExitFlag;
m_Threads[i].m_CmpFuncWithStats = func;
m_Threads[i].m_StatManager = &statManager;
m_Threads[i].m_LogStream = logStream;
}
}

View File

@ -47,7 +47,8 @@
#include "CompressionFuncs.h"
#include "Thread.h"
#include "StopWatch.h"
#include "BlockStats.h"
#include <iosfwd>
struct CmpThread : public TCCallable {
friend class ThreadGroup;
@ -66,7 +67,7 @@ private:
CompressionFunc m_CmpFunc;
CompressionFuncWithStats m_CmpFuncWithStats;
BlockStatManager *m_StatManager;
std::ostream *m_LogStream;
unsigned char *m_OutBuf;
const unsigned char *m_InBuf;
@ -95,7 +96,7 @@ class ThreadGroup {
const unsigned char *inBuf,
unsigned int inBufSz,
CompressionFuncWithStats func,
BlockStatManager &statManager,
std::ostream *logStream,
unsigned char *outBuf
);
@ -139,6 +140,8 @@ class ThreadGroup {
EThreadState m_ThreadState;
bool m_ExitFlag;
std::ostream *m_LogStream;
const unsigned int m_CompressedBlockSize;
const unsigned int m_UncompressedBlockSize;
};

View File

@ -72,9 +72,9 @@ void WorkerThread::operator()() {
CompressionFunc f = m_Parent->GetCompressionFunc();
CompressionFuncWithStats fStat = m_Parent->GetCompressionFuncWithStats();
BlockStatManager *statManager = m_Parent->GetBlockStatManager();
std::ostream *logStream = m_Parent->GetLogStream();
if(!(f || (fStat && statManager))) {
if(!(f || (fStat && logStream))) {
fprintf(stderr, "%s\n", "Illegal worker queue initialization -- compression func is NULL.");
return;
}
@ -105,9 +105,7 @@ void WorkerThread::operator()() {
if(f)
(*f)(cj);
else
// !FIXME! Actually use stat manager...
// (*fStat)(cj, *statManager);
(*fStat)(cj, &std::cout);
(*fStat)(cj, logStream);
break;
}
@ -147,7 +145,7 @@ WorkerQueue::WorkerQueue(
, m_NextBlock(0)
, m_CompressionFunc(func)
, m_CompressionFuncWithStats(NULL)
, m_BlockStatManager(NULL)
, m_LogStream(NULL)
{
clamp(m_NumThreads, uint32(1), uint32(kMaxNumWorkerThreads));
@ -165,7 +163,7 @@ WorkerQueue::WorkerQueue(
const uint8 *inBuf,
uint32 inBufSz,
CompressionFuncWithStats func,
BlockStatManager &blockStatManager,
std::ostream *logStream,
uint8 *outBuf
)
: m_NumCompressions(0)
@ -180,7 +178,7 @@ WorkerQueue::WorkerQueue(
, m_NextBlock(0)
, m_CompressionFunc(NULL)
, m_CompressionFuncWithStats(func)
, m_BlockStatManager(&blockStatManager)
, m_LogStream(logStream)
{
clamp(m_NumThreads, uint32(1), uint32(kMaxNumWorkerThreads));

View File

@ -46,7 +46,6 @@
// Forward declare...
class WorkerQueue;
class BlockStatManager;
// Necessary includes...
#include "TexCompTypes.h"
@ -54,6 +53,8 @@ class BlockStatManager;
#include "StopWatch.h"
#include "CompressionFuncs.h"
#include <iosfwd>
class WorkerThread : public TCCallable {
friend class WorkerQueue;
public:
@ -95,7 +96,7 @@ class WorkerQueue {
const uint8 *inBuf,
uint32 inBufSz,
CompressionFuncWithStats func,
BlockStatManager &blockStatManager,
std::ostream *logStream,
uint8 *outBuf
);
@ -138,8 +139,8 @@ class WorkerQueue {
const CompressionFuncWithStats m_CompressionFuncWithStats;
CompressionFuncWithStats GetCompressionFuncWithStats() const { return m_CompressionFuncWithStats; }
BlockStatManager *m_BlockStatManager;
BlockStatManager *GetBlockStatManager() const { return m_BlockStatManager; }
std::ostream *m_LogStream;
std::ostream *GetLogStream() const { return m_LogStream; }
StopWatch m_StopWatch;