Yet more work on eng::malloc

This commit is contained in:
2022-03-02 14:52:51 -05:00
parent 7cd8eb0a43
commit cf102a6250
25 changed files with 114 additions and 59 deletions

View File

@@ -9,8 +9,6 @@ grep std::unordered_set cpp/*
grep std::deque cpp/*
grep std::ostringstream cpp/*
grep std::ostream cpp/*
grep std::unique_ptr cpp/*
grep std::shared_ptr cpp/*
grep std::cerr cpp/*
grep std::cout cpp/*

View File

@@ -57,7 +57,7 @@
#include <cassert>
#include <ostream>
class AnimStep {
class AnimStep : public eng::nevernew {
friend class AnimQueue;
public:
enum {
@@ -166,7 +166,7 @@ private:
};
class AnimQueue {
class AnimQueue : public eng::nevernew {
public:
// World type determines whether versions increment or autozero
AnimQueue(util::WorldType wt);

View File

@@ -8,7 +8,7 @@
#include <ostream>
#include <memory>
class DebugCollector {
class DebugCollector : public eng::nevernew {
private:
// At any given time, the stringstream may contain one
// extra line that hasn't yet been appended to the list of lines.
@@ -33,7 +33,7 @@ public:
friend class DebugBlock;
};
class DebugBlock {
class DebugBlock : public eng::nevernew {
private:
DebugCollector *dbc_;
int n_regular_;

View File

@@ -106,7 +106,7 @@ class DrivenEngine;
using UniqueDrivenEngine = std::unique_ptr<DrivenEngine>;
using DrivenEngineMaker = UniqueDrivenEngine (*)();
class Channel {
class Channel : public eng::opnew {
public:
// Get the buffers associated with this channel.
//
@@ -190,7 +190,7 @@ private:
using SharedChannel = std::shared_ptr<Channel>;
class DrivenEngine {
class DrivenEngine : public eng::opnew {
public:
//////////////////////////////////////////////////////////////
//

View File

@@ -13,27 +13,27 @@
// In order to get all engine data structures into the eng::malloc heap, you
// need to jump through quite a few hoops:
//
// * When using STL classes, you need to use the 'eng' variant of those classes:
// * When writing a class, always derive from eng::opnew. This adds a
// custom operator new to your class, which causes your class to be
// allocated using eng::malloc.
//
// - eng::string instead of std::string (include "wrap-string.hpp")
// - eng::vector instead of std::vector (include "wrap-vector.hpp")
// - eng::map instead of std::map (include "wrap-map.hpp")
// - etc.
// * When using STL containers, you need to use the eng variant:
// eng::map, eng::set, eng::vector, eng::unordered_map, eng::unordered_set,
// and eng::deque. These classes derive from eng::opnew, and they also
// use eng::malloc for their internal nodes.
//
// These eng classes allocate memory using eng::malloc instead of malloc.
//
// * All your classes must derive from eng::opnew. This adds a custom operator
// new and operator delete to your class, which allocate using eng::malloc.
//
// * Use eng::make_shared and eng::make_unique instead of std::make_shared and
// std::make_unique.
// * Use eng::string instead of std::string. Use eng::ostringstream
// instead of std::ostringstream.
//
// * Simple classes like std::pair, std::string_view, std::less, std::hash, and
// so forth don't allocate memory. Those classes are not wrapped. There is
// no eng::pair, eng::less, etc.
// so forth are not wrapped. Do not use operator new or delete on
// these classes.
//
// * Instead of std::make_shared, use eng::make_shared. You need this
// because std::make_shared doesn't respect your custom operator new.
//
// * Be aware that most C++ streams use the system malloc heap, and there's no
// way to change that. Fortunately, eng::ostringstream uses the dlmalloc
// way to change that. Fortunately, eng::ostringstream uses the eng::malloc
// heap.
//
// * Failing to jump through all these hoops won't break your code in any
@@ -46,6 +46,7 @@
#include <cstddef>
#include <memory>
#include <cassert>
namespace eng {
#ifdef __linux__
@@ -126,21 +127,60 @@ namespace eng {
{
return ::eng::free(p);
}
void *operator new[](size_t size)
{
return ::eng::malloc(size);
}
void operator delete[](void *p, size_t size)
{
return ::eng::free(p);
}
};
} // namespace eng
// eng::nevernew. A class containing private operator new and
// operator delete, making it impossible to 'new' the class.
namespace eng {
class nevernew {
private:
void *operator new(size_t size)
{
assert(false && "not supposed to 'new' this class");
return NULL;
}
void operator delete(void *p, size_t size)
{
assert(false && "not supposed to 'delete' this class");
}
void *operator new[](size_t size)
{
assert(false && "not supposed to 'new' this class");
return NULL;
}
void operator delete[](void *p, size_t size)
{
assert(false && "not supposed to 'delete' this class");
}
};
} // namespace eng
// eng::make_shared allocates shared objects using eng::malloc.
namespace eng {
template<class T, class... Args>
inline ::std::shared_ptr<T> make_shared(Args&&... args) {
static eng::allocator<T> alloc;
return std::allocate_shared<T>(alloc, args...);
return std::allocate_shared<T>(eng::allocator<T>(), args...);
}
}
} // namespace eng
// eng::make_unique doesn't do anything different than std::make_unique:
// they both use operator new and delete. You must
// derive from eng::opnew to change operator new and delete.
// eng::make_unique doesn't do anything different than std::make_unique: they
// both use operator new and delete. You must derive from eng::opnew to change
// operator new and delete.
namespace eng {
template<class T, class... Args>
inline ::std::unique_ptr<T> make_unique(Args&&... args) {

View File

@@ -8,7 +8,7 @@
#include "luastack.hpp"
#include "streambuffer.hpp"
class GuiElt {
class GuiElt : public eng::nevernew {
friend class Gui;
public:
enum Type {
@@ -27,7 +27,7 @@ public:
const eng::string &label() const { return label_; }
};
class Gui {
class Gui : public eng::nevernew {
public:
using EltVec = eng::vector<GuiElt>;
private:

View File

@@ -75,7 +75,7 @@
#include <cstdint>
#include <ostream>
class IdGlobalPool {
class IdGlobalPool : public eng::nevernew {
public:
// Construct and destroy global pools. Note that after constructing
// a global pool, it is generally also necessary to initialize it
@@ -119,7 +119,7 @@ private:
friend int unittests_idalloc(lua_State *L);
};
class IdPlayerPool {
class IdPlayerPool : public eng::nevernew {
public:
// Construct a player pool.
//

View File

@@ -16,7 +16,7 @@ public:
void deserialize(StreamBuffer *sb);
};
class Invocation {
class Invocation : public eng::nevernew {
public:
enum Kind {
KIND_INVALID,

View File

@@ -47,7 +47,7 @@
#include "luastack.hpp"
class LuaConsole {
class LuaConsole : public eng::nevernew {
public:
using StringVec = eng::vector<eng::string>;

View File

@@ -17,7 +17,7 @@
#include "streambuffer.hpp"
#include "luastack.hpp"
class LuaSnap {
class LuaSnap : public eng::nevernew {
private:
lua_State *state_;

View File

@@ -163,7 +163,7 @@ extern "C" {
#include "eris.h"
}
class LuaSlot {
class LuaSlot : public eng::nevernew {
protected:
int index_;
private:
@@ -226,7 +226,7 @@ int LuaTypeTagValue(lua_State *L) { return 0; }
#define LUA_TT_GLOBALDB 22
#define LUA_TT_CLASS 23
class LuaStack {
class LuaStack : public eng::nevernew {
private:
int narg_;
int ngap_;
@@ -470,7 +470,7 @@ public:
};
class LuaFunctionReg {
class LuaFunctionReg : public eng::nevernew {
private:
const char *name_;
const char *args_;

View File

@@ -83,7 +83,7 @@
class PlaneMap;
class PlaneItem {
class PlaneItem : public eng::nevernew {
friend class PlaneMap;
private:
@@ -112,7 +112,7 @@ public:
void set_xyz(float x, float y, float z) { set_pos(plane_, x, y, z); }
};
class PlaneMap {
class PlaneMap : public eng::nevernew {
friend class PlaneItem;
private:
using EltVec = eng::vector<PlaneItem *>;

View File

@@ -89,7 +89,7 @@
struct PrintBufferCore;
class PrintBuffer : public eng::opnew {
class PrintBuffer : public eng::nevernew {
private:
PrintBufferCore *core_;
@@ -138,7 +138,7 @@ public:
};
class PrintChanneler : public eng::opnew {
class PrintChanneler : public eng::nevernew {
private:
int64_t line_;
public:

View File

@@ -7,7 +7,7 @@
#include <cstdint>
class SchedEntry {
class SchedEntry : public eng::nevernew {
private:
friend class Schedule;
int64_t clock_;
@@ -30,7 +30,7 @@ public:
eng::string debug_string() const;
};
class Schedule {
class Schedule : public eng::nevernew {
private:
eng::set<SchedEntry> schedule_;
public:

View File

@@ -127,7 +127,7 @@
#include "streambuffer.hpp"
#include "debugcollector.hpp"
class SourceDB {
class SourceDB : public eng::nevernew {
private:
lua_State *lua_state_;

View File

@@ -490,7 +490,7 @@ void *StreamBuffer::lua_reader_ud(int64_t size) {
return this;
}
class StreamBufferWriter : public std::streambuf {
class StreamBufferWriter : public std::streambuf, public eng::opnew {
private:
StreamBuffer *target_;
public:
@@ -504,7 +504,7 @@ public:
}
};
class StreamBufferOStream : public std::ostream {
class StreamBufferOStream : public std::ostream, public eng::opnew {
private:
StreamBufferWriter writer_;
public:

View File

@@ -222,7 +222,7 @@
#include "luastack.hpp"
#include "util.hpp"
class StreamException
class StreamException : public eng::nevernew
{
public:
virtual char const *what() const { return "General stream exception"; }
@@ -240,7 +240,7 @@ public:
virtual char const *what() const { return "Stream contained invalid data"; }
};
class StreamBuffer {
class StreamBuffer : public eng::nevernew {
public:
// Construct an empty buffer.
StreamBuffer();

View File

@@ -24,7 +24,7 @@
class World;
class Tangible {
class Tangible : public eng::opnew {
private:
friend class World;
@@ -90,7 +90,7 @@ public:
using UniqueTangible = std::unique_ptr<Tangible>;
class World {
class World : public eng::opnew {
public:
using IdVector = util::IdVector;
using TanVector = eng::vector<const Tangible*>;

View File

@@ -6,7 +6,9 @@
namespace eng {
template<class T>
using deque = std::deque<T, eng::allocator<T>>;
class deque : public std::deque<T, eng::allocator<T>>, public eng::opnew {
using std::deque<T, eng::allocator<T>>::deque;
};
} // namespace eng
#endif // WRAP_DEQUE_HPP

View File

@@ -6,7 +6,9 @@
namespace eng {
template<class K, class V, class C=std::less<K>>
using map = std::map<K, V, C, eng::allocator<std::pair<const K, V>>>;
class map : public std::map<K, V, C, eng::allocator<std::pair<const K, V>>>, eng::opnew {
using std::map<K, V, C, eng::allocator<std::pair<const K, V>>>::map;
};
} // namespace eng
#endif // WRAP_MAP_HPP

View File

@@ -6,7 +6,9 @@
namespace eng {
template<class K, class C=std::less<K>>
using set = std::set<K, C, eng::allocator<K>>;
class set : public std::set<K, C, eng::allocator<K>>, public eng::opnew {
using std::set<K, C, eng::allocator<K>>::set;
};
} // namespace eng
#endif // WRAP_SET_HPP

View File

@@ -2,11 +2,16 @@
#define WRAP_SSTREAM_HPP
#include "eng-malloc.hpp"
#include "wrap-string.hpp"
#include <sstream>
#include <string_view>
namespace eng {
template<class C, class T=std::char_traits<C>>
using basic_ostringstream = std::basic_ostringstream<C, T, eng::allocator<C>>;
class basic_ostringstream : public std::basic_ostringstream<C, T, eng::allocator<C>>, public eng::opnew {
using underlying = std::basic_ostringstream<C, T, eng::allocator<C>>;
using underlying::basic_ostringstream;
};
using ostringstream = basic_ostringstream<char>;
} // namespace eng

View File

@@ -6,7 +6,9 @@
namespace eng {
template<class K, class V, class H=std::hash<K>, class E=std::equal_to<K>>
using unordered_map = std::unordered_map<K, V, H, E, eng::allocator<std::pair<const K, V>>>;
class unordered_map : public std::unordered_map<K, V, H, E, eng::allocator<std::pair<const K, V>>>, public eng::opnew {
using std::unordered_map<K, V, H, E, eng::allocator<std::pair<const K, V>>>::unordered_map;
};
} // namespace eng
#endif // WRAP_UNORDERED_MAP_HPP

View File

@@ -6,7 +6,9 @@
namespace eng {
template<class K, class H=std::hash<K>, class E=std::equal_to<K>>
using unordered_set = std::unordered_set<K, H, E, eng::allocator<K>>;
class unordered_set : public std::unordered_set<K, H, E, eng::allocator<K>>, public eng::opnew {
using std::unordered_set<K, H, E, eng::allocator<K>>::unordered_set;
};
} // namespace eng
#endif // WRAP_UNORDERED_SET_HPP

View File

@@ -6,7 +6,9 @@
namespace eng {
template<class T>
using vector = std::vector<T, eng::allocator<T>>;
class vector : public std::vector<T, eng::allocator<T>>, public eng::opnew {
using std::vector<T, eng::allocator<T>>::vector;
};
} // namespace eng
#endif // WRAP_VECTOR_HPP