diff --git a/luprex/core/badmem.sh b/luprex/core/badmem.sh index e21ba3d2..10964558 100755 --- a/luprex/core/badmem.sh +++ b/luprex/core/badmem.sh @@ -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/* diff --git a/luprex/core/cpp/animqueue.hpp b/luprex/core/cpp/animqueue.hpp index d41499b4..03f4420c 100644 --- a/luprex/core/cpp/animqueue.hpp +++ b/luprex/core/cpp/animqueue.hpp @@ -57,7 +57,7 @@ #include #include -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); diff --git a/luprex/core/cpp/debugcollector.hpp b/luprex/core/cpp/debugcollector.hpp index 8376e394..947f90d6 100644 --- a/luprex/core/cpp/debugcollector.hpp +++ b/luprex/core/cpp/debugcollector.hpp @@ -8,7 +8,7 @@ #include #include -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_; diff --git a/luprex/core/cpp/drivenengine.hpp b/luprex/core/cpp/drivenengine.hpp index d86ef3f1..4cb4d014 100644 --- a/luprex/core/cpp/drivenengine.hpp +++ b/luprex/core/cpp/drivenengine.hpp @@ -106,7 +106,7 @@ class DrivenEngine; using UniqueDrivenEngine = std::unique_ptr; 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; -class DrivenEngine { +class DrivenEngine : public eng::opnew { public: ////////////////////////////////////////////////////////////// // diff --git a/luprex/core/cpp/eng-malloc.hpp b/luprex/core/cpp/eng-malloc.hpp index a622139e..929e1981 100644 --- a/luprex/core/cpp/eng-malloc.hpp +++ b/luprex/core/cpp/eng-malloc.hpp @@ -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 #include +#include 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 inline ::std::shared_ptr make_shared(Args&&... args) { - static eng::allocator alloc; - return std::allocate_shared(alloc, args...); + return std::allocate_shared(eng::allocator(), 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 inline ::std::unique_ptr make_unique(Args&&... args) { diff --git a/luprex/core/cpp/gui.hpp b/luprex/core/cpp/gui.hpp index 103e50b3..85987321 100644 --- a/luprex/core/cpp/gui.hpp +++ b/luprex/core/cpp/gui.hpp @@ -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; private: diff --git a/luprex/core/cpp/idalloc.hpp b/luprex/core/cpp/idalloc.hpp index 2b861e25..ff32a411 100644 --- a/luprex/core/cpp/idalloc.hpp +++ b/luprex/core/cpp/idalloc.hpp @@ -75,7 +75,7 @@ #include #include -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. // diff --git a/luprex/core/cpp/invocation.hpp b/luprex/core/cpp/invocation.hpp index 648561fe..49737950 100644 --- a/luprex/core/cpp/invocation.hpp +++ b/luprex/core/cpp/invocation.hpp @@ -16,7 +16,7 @@ public: void deserialize(StreamBuffer *sb); }; -class Invocation { +class Invocation : public eng::nevernew { public: enum Kind { KIND_INVALID, diff --git a/luprex/core/cpp/luaconsole.hpp b/luprex/core/cpp/luaconsole.hpp index e26004bf..5476684f 100644 --- a/luprex/core/cpp/luaconsole.hpp +++ b/luprex/core/cpp/luaconsole.hpp @@ -47,7 +47,7 @@ #include "luastack.hpp" -class LuaConsole { +class LuaConsole : public eng::nevernew { public: using StringVec = eng::vector; diff --git a/luprex/core/cpp/luasnap.hpp b/luprex/core/cpp/luasnap.hpp index 10592f59..0f152ef3 100644 --- a/luprex/core/cpp/luasnap.hpp +++ b/luprex/core/cpp/luasnap.hpp @@ -17,7 +17,7 @@ #include "streambuffer.hpp" #include "luastack.hpp" -class LuaSnap { +class LuaSnap : public eng::nevernew { private: lua_State *state_; diff --git a/luprex/core/cpp/luastack.hpp b/luprex/core/cpp/luastack.hpp index 49696f8b..ace53ac3 100644 --- a/luprex/core/cpp/luastack.hpp +++ b/luprex/core/cpp/luastack.hpp @@ -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_; diff --git a/luprex/core/cpp/planemap.hpp b/luprex/core/cpp/planemap.hpp index 1573e006..bc7a71d6 100644 --- a/luprex/core/cpp/planemap.hpp +++ b/luprex/core/cpp/planemap.hpp @@ -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; diff --git a/luprex/core/cpp/printbuffer.hpp b/luprex/core/cpp/printbuffer.hpp index a98849e2..3d98634a 100644 --- a/luprex/core/cpp/printbuffer.hpp +++ b/luprex/core/cpp/printbuffer.hpp @@ -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: diff --git a/luprex/core/cpp/sched.hpp b/luprex/core/cpp/sched.hpp index f11aa8a3..9af31c28 100644 --- a/luprex/core/cpp/sched.hpp +++ b/luprex/core/cpp/sched.hpp @@ -7,7 +7,7 @@ #include -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 schedule_; public: diff --git a/luprex/core/cpp/source.hpp b/luprex/core/cpp/source.hpp index 60186ba3..6e1ed175 100644 --- a/luprex/core/cpp/source.hpp +++ b/luprex/core/cpp/source.hpp @@ -127,7 +127,7 @@ #include "streambuffer.hpp" #include "debugcollector.hpp" -class SourceDB { +class SourceDB : public eng::nevernew { private: lua_State *lua_state_; diff --git a/luprex/core/cpp/streambuffer.cpp b/luprex/core/cpp/streambuffer.cpp index bda56942..2019c2d5 100644 --- a/luprex/core/cpp/streambuffer.cpp +++ b/luprex/core/cpp/streambuffer.cpp @@ -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: diff --git a/luprex/core/cpp/streambuffer.hpp b/luprex/core/cpp/streambuffer.hpp index 0238b5fe..378946ee 100644 --- a/luprex/core/cpp/streambuffer.hpp +++ b/luprex/core/cpp/streambuffer.hpp @@ -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(); diff --git a/luprex/core/cpp/world.hpp b/luprex/core/cpp/world.hpp index 75c9b622..2154dbc8 100644 --- a/luprex/core/cpp/world.hpp +++ b/luprex/core/cpp/world.hpp @@ -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; -class World { +class World : public eng::opnew { public: using IdVector = util::IdVector; using TanVector = eng::vector; diff --git a/luprex/core/wrap/wrap-deque.hpp b/luprex/core/wrap/wrap-deque.hpp index 238fc0dd..6648864e 100644 --- a/luprex/core/wrap/wrap-deque.hpp +++ b/luprex/core/wrap/wrap-deque.hpp @@ -6,7 +6,9 @@ namespace eng { template -using deque = std::deque>; +class deque : public std::deque>, public eng::opnew { + using std::deque>::deque; +}; } // namespace eng #endif // WRAP_DEQUE_HPP diff --git a/luprex/core/wrap/wrap-map.hpp b/luprex/core/wrap/wrap-map.hpp index 10905294..0077eca5 100644 --- a/luprex/core/wrap/wrap-map.hpp +++ b/luprex/core/wrap/wrap-map.hpp @@ -6,7 +6,9 @@ namespace eng { template> -using map = std::map>>; +class map : public std::map>>, eng::opnew { + using std::map>>::map; +}; } // namespace eng #endif // WRAP_MAP_HPP diff --git a/luprex/core/wrap/wrap-set.hpp b/luprex/core/wrap/wrap-set.hpp index 8beee51d..dba5a388 100644 --- a/luprex/core/wrap/wrap-set.hpp +++ b/luprex/core/wrap/wrap-set.hpp @@ -6,7 +6,9 @@ namespace eng { template> -using set = std::set>; +class set : public std::set>, public eng::opnew { + using std::set>::set; +}; } // namespace eng #endif // WRAP_SET_HPP diff --git a/luprex/core/wrap/wrap-sstream.hpp b/luprex/core/wrap/wrap-sstream.hpp index 60ed91b5..785dfcbe 100644 --- a/luprex/core/wrap/wrap-sstream.hpp +++ b/luprex/core/wrap/wrap-sstream.hpp @@ -2,11 +2,16 @@ #define WRAP_SSTREAM_HPP #include "eng-malloc.hpp" +#include "wrap-string.hpp" #include +#include namespace eng { template> -using basic_ostringstream = std::basic_ostringstream>; +class basic_ostringstream : public std::basic_ostringstream>, public eng::opnew { + using underlying = std::basic_ostringstream>; + using underlying::basic_ostringstream; +}; using ostringstream = basic_ostringstream; } // namespace eng diff --git a/luprex/core/wrap/wrap-unordered-map.hpp b/luprex/core/wrap/wrap-unordered-map.hpp index 0a3ecd23..5b187f41 100644 --- a/luprex/core/wrap/wrap-unordered-map.hpp +++ b/luprex/core/wrap/wrap-unordered-map.hpp @@ -6,7 +6,9 @@ namespace eng { template, class E=std::equal_to> -using unordered_map = std::unordered_map>>; +class unordered_map : public std::unordered_map>>, public eng::opnew { + using std::unordered_map>>::unordered_map; +}; } // namespace eng #endif // WRAP_UNORDERED_MAP_HPP diff --git a/luprex/core/wrap/wrap-unordered-set.hpp b/luprex/core/wrap/wrap-unordered-set.hpp index 8854b006..08640258 100644 --- a/luprex/core/wrap/wrap-unordered-set.hpp +++ b/luprex/core/wrap/wrap-unordered-set.hpp @@ -6,7 +6,9 @@ namespace eng { template, class E=std::equal_to> -using unordered_set = std::unordered_set>; +class unordered_set : public std::unordered_set>, public eng::opnew { + using std::unordered_set>::unordered_set; +}; } // namespace eng #endif // WRAP_UNORDERED_SET_HPP diff --git a/luprex/core/wrap/wrap-vector.hpp b/luprex/core/wrap/wrap-vector.hpp index a9cb254b..30a273d0 100644 --- a/luprex/core/wrap/wrap-vector.hpp +++ b/luprex/core/wrap/wrap-vector.hpp @@ -6,7 +6,9 @@ namespace eng { template -using vector = std::vector>; +class vector : public std::vector>, public eng::opnew { + using std::vector>::vector; +}; } // namespace eng #endif // WRAP_VECTOR_HPP