Files
mlpack/fastlib/u/nvasil/tpie/bte_stream_cache.h
T

234 lines
5.9 KiB
C++

//
// File: bte_stream_cache.h (formerly bte_cache.h)
// Author: Darren Erik Vengroff <darrenv@eecs.umich.edu>
// Created: 9/19/94
//
// $Id: bte_stream_cache.h,v 1.4 2004/08/12 12:35:31 jan Exp $
//
// BTE streams for main memory caches.
//
#ifndef _BTE_STREAM_CACHE_H
#define _BTE_STREAM_CACHE_H
// Get definitions for working with Unix and Windows
#include "u/nvasil/tpie/portability.h"
// Include the registration based memory manager.
#define MM_IMP_REGISTER
#include "u/nvasil/tpie/mm.h"
#include "u/nvasil/tpie/bte_stream_base.h"
// This code makes assertions and logs errors.
#include "u/nvasil/tpie/tpie_assert.h"
#include "u/nvasil/tpie/tpie_log.h"
#define BTE_STREAM_CACHE_DEFAULT_MAX_LEN (1024 * 256)
#ifndef BTE_STREAM_CACHE_LINE_SIZE
#define BTE_STREAM_CACHE_LINE_SIZE 64
#endif // BTE_STREAM_CACHE_LINE_SIZE
//
// The cache stream class.
//
template <class T>
class BTE_stream_cache : public BTE_stream_base<T> {
private:
T *data;
T *current;
T *data_max;
T *data_hard_end;
unsigned int substream_level;
unsigned int valid;
unsigned int r_only;
BTE_stream_cache(void);
public:
// Constructors
BTE_stream_cache(const char *path, BTE_stream_type st, TPIE_OS_OFFSET max_len);
// A psuedo-constructor for substreams.
BTE_err new_substream(BTE_stream_type st, TPIE_OS_OFFSET sub_begin,
TPIE_OS_OFFSET sub_end, BTE_stream_base<T> **sub_stream);
// Query memory usage
BTE_err main_memory_usage(size_t *usage,
MM_stream_usage usage_type);
// Return the number of items in the stream.
TPIE_OS_OFFSET stream_len(void);
// Move to a specific position in the stream.
BTE_err seek(TPIE_OS_OFFSET offset);
// Destructor
~BTE_stream_cache(void);
BTE_err read_item(T **elt);
BTE_err write_item(const T &elt);
int read_only(void) { return r_only; };
int available_streams(void) { return -1; };
TPIE_OS_OFFSET chunk_size(void);
};
template<class T>
BTE_stream_cache<T>::BTE_stream_cache(void)
{
};
template<class T>
BTE_stream_cache<T>::BTE_stream_cache(const char *path, BTE_stream_type st,
TPIE_OS_OFFSET max_len) {
// A stream being created out of the blue must be writable, so we
// return an error if it is not.
switch (st) {
case BTE_READ_STREAM:
case BTE_APPEND_STREAM:
valid = 0;
break;
case BTE_WRITE_STREAM:
r_only = 0;
if (!max_len) {
max_len = BTE_STREAM_CACHE_DEFAULT_MAX_LEN;
}
// Use malloc() directly rather than new becasue this is
// in "secondary memory" and will not necessarily go into
// the cache.
data = (T*)malloc(max_len*sizeof(T));
if (data == NULL) {
valid = 0;
TP_LOG_FATAL_ID("Out of \"secondary memory.\"");
return;
}
current = data_max = data;
data_hard_end = data + max_len;
valid = 1;
}
};
template<class T>
BTE_err BTE_stream_cache<T>::new_substream(BTE_stream_type st, TPIE_OS_OFFSET sub_begin,
TPIE_OS_OFFSET sub_end,
BTE_stream_base<T> **sub_stream)
{
BTE_stream_cache *ss;
if (st == BTE_APPEND_STREAM) {
return BTE_ERROR_PERMISSION_DENIED;
} else {
if ((sub_begin >= data_hard_end - data) ||
(sub_end >= data_hard_end - data) ||
(sub_begin >= data_max - data) ||
(sub_end >= data_max - data) ||
(sub_end < sub_begin)) {
return BTE_ERROR_OFFSET_OUT_OF_RANGE;
}
ss = new BTE_stream_cache;
ss->r_only = (st == BTE_READ_STREAM);
ss->substream_level = substream_level + 1;
ss->current = ss->data = data + sub_begin;
ss->data_max = ss->data_hard_end = data + sub_end + 1;
*sub_stream = (BTE_stream_base<T> *)ss;
return BTE_ERROR_NO_ERROR;
}
};
template<class T>
BTE_err BTE_stream_cache<T>::main_memory_usage(size_t *usage,
MM_stream_usage usage_type)
{
switch (usage_type) {
case MM_STREAM_USAGE_CURRENT:
case MM_STREAM_USAGE_MAXIMUM:
case MM_STREAM_USAGE_SUBSTREAM:
*usage = sizeof(*this) + BTE_STREAM_CACHE_LINE_SIZE;
break;
case MM_STREAM_USAGE_BUFFER:
*usage = BTE_STREAM_CACHE_LINE_SIZE;
break;
case MM_STREAM_USAGE_OVERHEAD:
*usage = sizeof(this);
break;
}
return BTE_ERROR_NO_ERROR;
};
template<class T>
TPIE_OS_OFFSET BTE_stream_cache<T>::stream_len(void)
{
return data_max - data;
};
template<class T>
BTE_err BTE_stream_cache<T>::seek(TPIE_OS_OFFSET offset)
{
if (offset > data_hard_end - data) {
return BTE_ERROR_OFFSET_OUT_OF_RANGE;
} else {
current = data + offset;
return BTE_ERROR_NO_ERROR;
}
};
template<class T>
BTE_stream_cache<T>::~BTE_stream_cache(void)
{
if (!substream_level) {
delete data;
}
};
template<class T>
BTE_err BTE_stream_cache<T>::read_item(T **elt)
{
if (current >= data_max) {
return BTE_ERROR_END_OF_STREAM;
} else {
*elt = current++;
return BTE_ERROR_NO_ERROR;
}
};
template<class T>
BTE_err BTE_stream_cache<T>::write_item(const T &elt)
{
if (r_only) {
return BTE_ERROR_PERMISSION_DENIED;
}
if (current >= data_hard_end) {
return BTE_ERROR_OUT_OF_SPACE;
} else {
*current++ = elt;
if (current > data_max) {
data_max = current;
}
return BTE_ERROR_NO_ERROR;
}
};
template<class T>
TPIE_OS_OFFSET BTE_stream_cache<T>::chunk_size(void)
{
return BTE_STREAM_CACHE_LINE_SIZE / sizeof(T);
}
#endif // _BTE_STREAM_CACHE_H