Moving some util types into poly.
This commit is contained in:
103
src/poly/arena.cc
Normal file
103
src/poly/arena.cc
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "poly/arena.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "poly/assert.h"
|
||||
|
||||
namespace poly {
|
||||
|
||||
Arena::Arena(size_t chunk_size)
|
||||
: chunk_size_(chunk_size), head_chunk_(nullptr), active_chunk_(nullptr) {}
|
||||
|
||||
Arena::~Arena() {
|
||||
Reset();
|
||||
Chunk* chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
Chunk* next = chunk->next;
|
||||
delete chunk;
|
||||
chunk = next;
|
||||
}
|
||||
head_chunk_ = nullptr;
|
||||
}
|
||||
|
||||
void Arena::Reset() {
|
||||
active_chunk_ = head_chunk_;
|
||||
if (active_chunk_) {
|
||||
active_chunk_->offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Arena::DebugFill() {
|
||||
auto chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
std::memset(chunk->buffer, 0xCD, chunk->capacity);
|
||||
chunk = chunk->next;
|
||||
}
|
||||
}
|
||||
|
||||
void* Arena::Alloc(size_t size) {
|
||||
if (active_chunk_) {
|
||||
if (active_chunk_->capacity - active_chunk_->offset < size + 4096) {
|
||||
Chunk* next = active_chunk_->next;
|
||||
if (!next) {
|
||||
assert_true(size < chunk_size_, "need to support larger chunks");
|
||||
next = new Chunk(chunk_size_);
|
||||
active_chunk_->next = next;
|
||||
}
|
||||
next->offset = 0;
|
||||
active_chunk_ = next;
|
||||
}
|
||||
} else {
|
||||
head_chunk_ = active_chunk_ = new Chunk(chunk_size_);
|
||||
}
|
||||
|
||||
uint8_t* p = active_chunk_->buffer + active_chunk_->offset;
|
||||
active_chunk_->offset += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
void* Arena::CloneContents() {
|
||||
size_t total_length = 0;
|
||||
Chunk* chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
total_length += chunk->offset;
|
||||
if (chunk == active_chunk_) {
|
||||
break;
|
||||
}
|
||||
chunk = chunk->next;
|
||||
}
|
||||
void* result = malloc(total_length);
|
||||
uint8_t* p = (uint8_t*)result;
|
||||
chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
std::memcpy(p, chunk->buffer, chunk->offset);
|
||||
p += chunk->offset;
|
||||
if (chunk == active_chunk_) {
|
||||
break;
|
||||
}
|
||||
chunk = chunk->next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Arena::Chunk::Chunk(size_t chunk_size)
|
||||
: next(nullptr), capacity(chunk_size), buffer(0), offset(0) {
|
||||
buffer = reinterpret_cast<uint8_t*>(malloc(capacity));
|
||||
}
|
||||
|
||||
Arena::Chunk::~Chunk() {
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace poly
|
||||
55
src/poly/arena.h
Normal file
55
src/poly/arena.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_ARENA_H_
|
||||
#define POLY_ARENA_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace poly {
|
||||
|
||||
class Arena {
|
||||
public:
|
||||
Arena(size_t chunk_size = 4 * 1024 * 1024);
|
||||
~Arena();
|
||||
|
||||
void Reset();
|
||||
void DebugFill();
|
||||
|
||||
void* Alloc(size_t size);
|
||||
template <typename T>
|
||||
T* Alloc() {
|
||||
return reinterpret_cast<T*>(Alloc(sizeof(T)));
|
||||
}
|
||||
|
||||
void* CloneContents();
|
||||
|
||||
private:
|
||||
class Chunk {
|
||||
public:
|
||||
Chunk(size_t chunk_size);
|
||||
~Chunk();
|
||||
|
||||
Chunk* next;
|
||||
|
||||
size_t capacity;
|
||||
uint8_t* buffer;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
private:
|
||||
size_t chunk_size_;
|
||||
Chunk* head_chunk_;
|
||||
Chunk* active_chunk_;
|
||||
};
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_ARENA_H_
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "poly/platform.h"
|
||||
#include "poly/string.h"
|
||||
#include "poly/threading.h"
|
||||
#include "poly/vec128.h"
|
||||
|
||||
namespace poly {} // namespace poly
|
||||
|
||||
|
||||
43
src/poly/reset_scope.h
Normal file
43
src/poly/reset_scope.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_RESET_SCOPE_H_
|
||||
#define POLY_RESET_SCOPE_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace poly {
|
||||
|
||||
template <typename T>
|
||||
class ResetScope {
|
||||
public:
|
||||
ResetScope(T* value) : value_(value) {}
|
||||
~ResetScope() {
|
||||
if (value_) {
|
||||
value_->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T* value_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline ResetScope<T> make_reset_scope(T* value) {
|
||||
return ResetScope<T>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline ResetScope<T> make_reset_scope(const std::unique_ptr<T>& value) {
|
||||
return ResetScope<T>(value.get());
|
||||
}
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_RESET_SCOPE_H_
|
||||
@@ -1,6 +1,8 @@
|
||||
# Copyright 2014 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'arena.cc',
|
||||
'arena.h',
|
||||
'assert.h',
|
||||
'atomic.h',
|
||||
'byte_order.h',
|
||||
@@ -20,10 +22,15 @@
|
||||
'memory.h',
|
||||
'platform.h',
|
||||
'poly.h',
|
||||
'reset_scope.h',
|
||||
'string.cc',
|
||||
'string.h',
|
||||
'string_buffer.cc',
|
||||
'string_buffer.h',
|
||||
'threading.cc',
|
||||
'threading.h',
|
||||
'type_pool.h',
|
||||
'vec128.h',
|
||||
],
|
||||
|
||||
'conditions': [
|
||||
|
||||
71
src/poly/string_buffer.cc
Normal file
71
src/poly/string_buffer.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "poly/string_buffer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace poly {
|
||||
|
||||
StringBuffer::StringBuffer(size_t initial_capacity) {
|
||||
buffer_.reserve(std::max(initial_capacity, static_cast<size_t>(1024)));
|
||||
}
|
||||
|
||||
StringBuffer::~StringBuffer() = default;
|
||||
|
||||
void StringBuffer::Reset() { buffer_.resize(0); }
|
||||
|
||||
void StringBuffer::Grow(size_t additional_length) {
|
||||
size_t old_capacity = buffer_.capacity();
|
||||
if (buffer_.size() + additional_length <= old_capacity) {
|
||||
return;
|
||||
}
|
||||
size_t new_capacity =
|
||||
std::max(buffer_.size() + additional_length, old_capacity * 2);
|
||||
buffer_.reserve(new_capacity);
|
||||
}
|
||||
|
||||
void StringBuffer::Append(const std::string& value) {
|
||||
AppendBytes(reinterpret_cast<const uint8_t*>(value.data()), value.size());
|
||||
}
|
||||
|
||||
void StringBuffer::Append(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
AppendVarargs(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void StringBuffer::AppendVarargs(const char* format, va_list args) {
|
||||
int length = vsnprintf(nullptr, 0, format, args);
|
||||
auto offset = buffer_.size();
|
||||
Grow(length + 1);
|
||||
buffer_.resize(buffer_.size() + length);
|
||||
vsnprintf(buffer_.data() + offset, buffer_.capacity(), format, args);
|
||||
buffer_[buffer_.size()] = 0;
|
||||
}
|
||||
|
||||
void StringBuffer::AppendBytes(const uint8_t* buffer, size_t length) {
|
||||
auto offset = buffer_.size();
|
||||
Grow(length + 1);
|
||||
buffer_.resize(buffer_.size() + length);
|
||||
memcpy(buffer_.data() + offset, buffer, length);
|
||||
buffer_[buffer_.size()] = 0;
|
||||
}
|
||||
|
||||
const char* StringBuffer::GetString() const { return buffer_.data(); }
|
||||
|
||||
std::string StringBuffer::to_string() {
|
||||
return std::string(buffer_.data(), buffer_.size());
|
||||
}
|
||||
|
||||
char* StringBuffer::ToString() { return strdup(buffer_.data()); }
|
||||
|
||||
} // namespace poly
|
||||
46
src/poly/string_buffer.h
Normal file
46
src/poly/string_buffer.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_STRING_BUFFER_H_
|
||||
#define POLY_STRING_BUFFER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace poly {
|
||||
|
||||
class StringBuffer {
|
||||
public:
|
||||
StringBuffer(size_t initial_capacity = 0);
|
||||
~StringBuffer();
|
||||
|
||||
size_t length() const { return buffer_.size(); }
|
||||
|
||||
void Reset();
|
||||
|
||||
void Append(const std::string& value);
|
||||
void Append(const char* format, ...);
|
||||
void AppendVarargs(const char* format, va_list args);
|
||||
void AppendBytes(const uint8_t* buffer, size_t length);
|
||||
|
||||
const char* GetString() const;
|
||||
std::string to_string();
|
||||
char* ToString();
|
||||
char* EncodeBase64();
|
||||
|
||||
private:
|
||||
void Grow(size_t additional_length);
|
||||
|
||||
std::vector<char> buffer_;
|
||||
};
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_STRING_BUFFER_H_
|
||||
59
src/poly/type_pool.h
Normal file
59
src/poly/type_pool.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_TYPE_POOL_H_
|
||||
#define POLY_TYPE_POOL_H_
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace poly {
|
||||
|
||||
template <class T, typename A>
|
||||
class TypePool {
|
||||
public:
|
||||
~TypePool() { Reset(); }
|
||||
|
||||
void Reset() {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
for (auto it = list_.begin(); it != list_.end(); ++it) {
|
||||
T* value = *it;
|
||||
delete value;
|
||||
}
|
||||
list_.clear();
|
||||
}
|
||||
|
||||
T* Allocate(A arg0) {
|
||||
T* result = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
if (list_.size()) {
|
||||
result = list_.back();
|
||||
list_.pop_back();
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
result = new T(arg0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Release(T* value) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
list_.push_back(value);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex lock_;
|
||||
std::vector<T*> list_;
|
||||
};
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_TYPE_POOL_H_
|
||||
196
src/poly/vec128.h
Normal file
196
src/poly/vec128.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_VEC128_H_
|
||||
#define POLY_VEC128_H_
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace poly {
|
||||
|
||||
// The first rule of vector programming is to only rely on exact positions
|
||||
// when absolutely required - prefer dumb loops to exact offsets.
|
||||
// Vectors in memory are laid out as in AVX registers on little endian
|
||||
// machines. Note that little endian is dumb, so the byte at index 0 in
|
||||
// the vector is is really byte 15 (or the high byte of short 7 or int 3).
|
||||
// Because of this, all byte access should be via the accessors instead of
|
||||
// the direct array.
|
||||
|
||||
// Altivec big endian layout: AVX little endian layout:
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 0 | int16 0 | int8 0 | | int32 3 | int16 7 | int8 15 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 1 | | | | int8 14 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 1 | int8 2 | | | int16 6 | int8 13 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 3 | | | | int8 12 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 1 | int16 2 | int8 4 | | int32 2 | int16 5 | int8 11 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 5 | | | | int8 10 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 3 | int8 6 | | | int16 4 | int8 9 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 7 | | | | int8 8 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 2 | int16 4 | int8 8 | | int32 1 | int16 3 | int8 7 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 9 | | | | int8 6 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 5 | int8 10 | | | int16 2 | int8 5 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 11 | | | | int8 4 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 3 | int16 6 | int8 12 | | int32 0 | int16 1 | int8 3 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 13 | | | | int8 2 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 7 | int8 14 | | | int16 0 | int8 1 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 15 | | | | int8 0 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
//
|
||||
// Logical order:
|
||||
// +-----+-----+-----+-----+ +-----+-----+-----+-----+
|
||||
// | X | Y | Z | W | | W | Z | Y | X |
|
||||
// +-----+-----+-----+-----+ +-----+-----+-----+-----+
|
||||
//
|
||||
// Mapping indices is easy:
|
||||
// int32[i ^ 0x3]
|
||||
// int16[i ^ 0x7]
|
||||
// int8[i ^ 0xF]
|
||||
typedef struct alignas(16) vec128_s {
|
||||
union {
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
struct {
|
||||
int32_t ix;
|
||||
int32_t iy;
|
||||
int32_t iz;
|
||||
int32_t iw;
|
||||
};
|
||||
struct {
|
||||
uint32_t ux;
|
||||
uint32_t uy;
|
||||
uint32_t uz;
|
||||
uint32_t uw;
|
||||
};
|
||||
float f32[4];
|
||||
int8_t i8[16];
|
||||
uint8_t u8[16];
|
||||
int16_t i16[8];
|
||||
uint16_t u16[8];
|
||||
int32_t i32[4];
|
||||
uint32_t u32[4];
|
||||
int64_t i64[2];
|
||||
uint64_t u64[2];
|
||||
struct {
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
};
|
||||
};
|
||||
|
||||
bool operator==(const vec128_s& b) const {
|
||||
return low == b.low && high == b.high;
|
||||
}
|
||||
bool operator!=(const vec128_s& b) const {
|
||||
return low != b.low || high != b.high;
|
||||
}
|
||||
} vec128_t;
|
||||
|
||||
static inline vec128_t vec128i(uint32_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 4; ++i) {
|
||||
v.u32[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128i(uint32_t x, uint32_t y, uint32_t z, uint32_t w) {
|
||||
vec128_t v;
|
||||
v.u32[0] = x;
|
||||
v.u32[1] = y;
|
||||
v.u32[2] = z;
|
||||
v.u32[3] = w;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128f(float src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 4; ++i) {
|
||||
v.f32[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128f(float x, float y, float z, float w) {
|
||||
vec128_t v;
|
||||
v.f32[0] = x;
|
||||
v.f32[1] = y;
|
||||
v.f32[2] = z;
|
||||
v.f32[3] = w;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128s(uint16_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 8; ++i) {
|
||||
v.u16[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128s(uint16_t x0, uint16_t x1, uint16_t y0,
|
||||
uint16_t y1, uint16_t z0, uint16_t z1,
|
||||
uint16_t w0, uint16_t w1) {
|
||||
vec128_t v;
|
||||
v.u16[0] = x1;
|
||||
v.u16[1] = x0;
|
||||
v.u16[2] = y1;
|
||||
v.u16[3] = y0;
|
||||
v.u16[4] = z1;
|
||||
v.u16[5] = z0;
|
||||
v.u16[6] = w1;
|
||||
v.u16[7] = w0;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128b(uint8_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 16; ++i) {
|
||||
v.u8[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128b(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3,
|
||||
uint8_t y0, uint8_t y1, uint8_t y2, uint8_t y3,
|
||||
uint8_t z0, uint8_t z1, uint8_t z2, uint8_t z3,
|
||||
uint8_t w0, uint8_t w1, uint8_t w2, uint8_t w3) {
|
||||
vec128_t v;
|
||||
v.u8[0] = x3;
|
||||
v.u8[1] = x2;
|
||||
v.u8[2] = x1;
|
||||
v.u8[3] = x0;
|
||||
v.u8[4] = y3;
|
||||
v.u8[5] = y2;
|
||||
v.u8[6] = y1;
|
||||
v.u8[7] = y0;
|
||||
v.u8[8] = z3;
|
||||
v.u8[9] = z2;
|
||||
v.u8[10] = z1;
|
||||
v.u8[11] = z0;
|
||||
v.u8[12] = w3;
|
||||
v.u8[13] = w2;
|
||||
v.u8[14] = w1;
|
||||
v.u8[15] = w0;
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_VEC128_H_
|
||||
Reference in New Issue
Block a user