buffer changes
This commit is contained in:
parent
1d1d440cb9
commit
746fc01323
1 changed files with 39 additions and 119 deletions
156
buffer.hpp
156
buffer.hpp
|
|
@ -1,145 +1,65 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
#include <algorithm>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// Main buffer pool - owns all memory
|
class Buffer;
|
||||||
class BufferPool {
|
|
||||||
|
class SubBuffer {
|
||||||
private:
|
private:
|
||||||
std::vector<Record> storage;
|
Record* data_;
|
||||||
int buffer_capacity;
|
size_t size_;
|
||||||
int num_buffers;
|
|
||||||
|
friend class Buffer;
|
||||||
|
|
||||||
|
SubBuffer(Record* data, size_t size)
|
||||||
|
: data_(data)
|
||||||
|
, size_(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BufferPool(int num_buffers, int buffer_capacity)
|
// for std::sort support
|
||||||
: storage(num_buffers * buffer_capacity)
|
using iterator = Record*;
|
||||||
, buffer_capacity(buffer_capacity)
|
iterator begin() { return data_; }
|
||||||
, num_buffers(num_buffers)
|
iterator end() { return data_ + size_; }
|
||||||
|
|
||||||
|
Record& operator[](size_t index)
|
||||||
{
|
{
|
||||||
|
return data_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Record* get_buffer_ptr(int index)
|
size_t size() const { return size_; }
|
||||||
{
|
|
||||||
return storage.data() + (index * buffer_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_buffer_capacity() const { return buffer_capacity; }
|
|
||||||
int get_num_buffers() const { return num_buffers; }
|
|
||||||
int total_capacity() const { return storage.size(); }
|
|
||||||
|
|
||||||
// Sort entire pool (for stage 1 - creating runs)
|
|
||||||
void sort_all(int count)
|
|
||||||
{
|
|
||||||
std::sort(storage.begin(), storage.begin() + count);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// View into a section of the buffer pool
|
class Buffer {
|
||||||
class BufferView {
|
|
||||||
private:
|
private:
|
||||||
Record* data;
|
std::vector<Record> storage_;
|
||||||
int capacity;
|
|
||||||
int length;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BufferView(Record* ptr, int cap)
|
explicit Buffer(size_t total_size)
|
||||||
: data(ptr)
|
: storage_(total_size)
|
||||||
, capacity(cap)
|
|
||||||
, length(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read up to capacity records from stream
|
std::vector<SubBuffer> divide(size_t n)
|
||||||
int read_from(std::istream& in)
|
|
||||||
{
|
{
|
||||||
length = 0;
|
if (n == 0) {
|
||||||
for (int i = 0; i < capacity; i++) {
|
throw std::invalid_argument("Cannot divide buffer into 0 pieces");
|
||||||
if (!(in >> data[i])) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
length++;
|
|
||||||
}
|
|
||||||
return length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write all current records to stream
|
size_t total_size = storage_.size();
|
||||||
bool write_to(std::ostream& out) const
|
if (total_size % n != 0) {
|
||||||
{
|
throw std::invalid_argument("Size not divisible by n");
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
out << data[i] << '\n';
|
|
||||||
if (!out)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For stage 2: peek at front record without consuming
|
std::vector<SubBuffer> result(n);
|
||||||
const Record& front() const { return data[0]; }
|
size_t piece_size = total_size / n;
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
// For stage 2: consume the front record
|
result[i] = SubBuffer(storage_.data() + i * piece_size, piece_size);
|
||||||
void pop_front()
|
|
||||||
{
|
|
||||||
if (length > 0) {
|
|
||||||
for (int i = 0; i < length - 1; i++) {
|
|
||||||
data[i] = data[i + 1];
|
|
||||||
}
|
|
||||||
length--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refill from stream when buffer becomes empty during merge
|
return result;
|
||||||
bool refill_from(std::istream& in)
|
|
||||||
{
|
|
||||||
return read_from(in) > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int size() const { return length; }
|
|
||||||
int get_capacity() const { return capacity; }
|
|
||||||
bool empty() const { return length == 0; }
|
|
||||||
bool full() const { return length == capacity; }
|
|
||||||
|
|
||||||
Record& operator[](int i) { return data[i]; }
|
|
||||||
const Record& operator[](int i) const { return data[i]; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// For output buffer during merge
|
|
||||||
class OutputBuffer {
|
|
||||||
private:
|
|
||||||
Record* data;
|
|
||||||
int capacity;
|
|
||||||
int length;
|
|
||||||
|
|
||||||
public:
|
|
||||||
OutputBuffer(Record* ptr, int cap)
|
|
||||||
: data(ptr)
|
|
||||||
, capacity(cap)
|
|
||||||
, length(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add record to output buffer
|
|
||||||
bool add(const Record& rec)
|
|
||||||
{
|
|
||||||
if (length >= capacity) {
|
|
||||||
return false; // Buffer full
|
|
||||||
}
|
|
||||||
data[length++] = rec;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush buffer to stream and reset
|
|
||||||
bool flush_to(std::ostream& out)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
out << data[i] << '\n';
|
|
||||||
if (!out)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
length = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool full() const { return length >= capacity; }
|
|
||||||
int size() const { return length; }
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue