Merge branch 'main' of https://github.com/jyelon/luprex into main
This commit is contained in:
@@ -65,7 +65,7 @@ LUA_OBJ_FILES=\
|
|||||||
CORE_OBJ_FILES=\
|
CORE_OBJ_FILES=\
|
||||||
obj/invocation.o\
|
obj/invocation.o\
|
||||||
obj/spookyv2.o\
|
obj/spookyv2.o\
|
||||||
obj/two-mallocs.o\
|
obj/eng-malloc.o\
|
||||||
obj/debugcollector.o\
|
obj/debugcollector.o\
|
||||||
obj/drivenengine.o\
|
obj/drivenengine.o\
|
||||||
obj/dummycert.o\
|
obj/dummycert.o\
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ grep std::unordered_set cpp/*
|
|||||||
grep std::deque cpp/*
|
grep std::deque cpp/*
|
||||||
grep std::ostringstream cpp/*
|
grep std::ostringstream cpp/*
|
||||||
grep std::ostream cpp/*
|
grep std::ostream cpp/*
|
||||||
grep std::unique_ptr cpp/*
|
|
||||||
grep std::shared_ptr cpp/*
|
|
||||||
|
|
||||||
grep std::cerr cpp/*
|
grep std::cerr cpp/*
|
||||||
grep std::cout cpp/*
|
grep std::cout cpp/*
|
||||||
|
|||||||
@@ -49,15 +49,15 @@
|
|||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-deque.hpp"
|
#include "wrap-deque.hpp"
|
||||||
#include "wrap-unordered-map.hpp"
|
#include "wrap-unordered-map.hpp"
|
||||||
#include "wrap-ostream.hpp"
|
|
||||||
|
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "debugcollector.hpp"
|
#include "debugcollector.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
class AnimStep {
|
class AnimStep : public eng::nevernew {
|
||||||
friend class AnimQueue;
|
friend class AnimQueue;
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
@@ -166,7 +166,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class AnimQueue {
|
class AnimQueue : public eng::nevernew {
|
||||||
public:
|
public:
|
||||||
// World type determines whether versions increment or autozero
|
// World type determines whether versions increment or autozero
|
||||||
AnimQueue(util::WorldType wt);
|
AnimQueue(util::WorldType wt);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#include "wrap-algorithm.hpp"
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "debugcollector.hpp"
|
#include "debugcollector.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
@@ -56,7 +56,7 @@ bool DebugCollector::do_header() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugCollector::dump(eng::ostream &os) {
|
void DebugCollector::dump(std::ostream &os) {
|
||||||
flush();
|
flush();
|
||||||
for (const eng::string &line : lines_) {
|
for (const eng::string &line : lines_) {
|
||||||
os << line << std::endl;
|
os << line << std::endl;
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-memory.hpp"
|
|
||||||
#include "wrap-sstream.hpp"
|
#include "wrap-sstream.hpp"
|
||||||
#include "wrap-ostream.hpp"
|
|
||||||
|
|
||||||
class DebugCollector {
|
#include <ostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class DebugCollector : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
// At any given time, the stringstream may contain one
|
// At any given time, the stringstream may contain one
|
||||||
// extra line that hasn't yet been appended to the list of lines.
|
// extra line that hasn't yet been appended to the list of lines.
|
||||||
@@ -28,11 +29,11 @@ public:
|
|||||||
DebugCollector(const eng::string &targets);
|
DebugCollector(const eng::string &targets);
|
||||||
bool do_header();
|
bool do_header();
|
||||||
bool do_line();
|
bool do_line();
|
||||||
void dump(eng::ostream &os);
|
void dump(std::ostream &os);
|
||||||
friend class DebugBlock;
|
friend class DebugBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DebugBlock {
|
class DebugBlock : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
DebugCollector *dbc_;
|
DebugCollector *dbc_;
|
||||||
int n_regular_;
|
int n_regular_;
|
||||||
|
|||||||
@@ -1,30 +1,32 @@
|
|||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
#include "wrap-utility.hpp"
|
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "drivenengine.hpp"
|
#include "drivenengine.hpp"
|
||||||
|
|
||||||
static eng::vector<eng::pair<eng::string, DrivenEngineMaker>> makers;
|
DrivenEngineReg *DrivenEngineReg::All;
|
||||||
|
|
||||||
void DrivenEngine::register_maker(const char *kind, DrivenEngineMaker maker) {
|
DrivenEngineReg::DrivenEngineReg(const char *n, DrivenEngineMaker fn) {
|
||||||
eng::string skind(kind);
|
name = n;
|
||||||
makers.push_back(std::make_pair(skind, maker));
|
maker = fn;
|
||||||
|
next = All;
|
||||||
|
All = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrivenEngine::print_usage(eng::ostream &strm, const char *progname) {
|
void DrivenEngine::print_usage(std::ostream &strm, const char *progname) {
|
||||||
strm << "Usage: " << progname << " <mode>" << std::endl;
|
strm << "Usage: " << progname << " <mode>" << std::endl;
|
||||||
for (const auto &mpair : makers) {
|
for (auto reg = DrivenEngineReg::All; reg != nullptr; reg=reg->next) {
|
||||||
strm << " Mode can be: " << mpair.first << std::endl;
|
strm << " Mode can be: " << reg->name << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UniqueDrivenEngine DrivenEngine::make(const char *kind) {
|
UniqueDrivenEngine DrivenEngine::make(const char *kind) {
|
||||||
for (const auto &mpair : makers) {
|
for (auto reg = DrivenEngineReg::All; reg != nullptr; reg=reg->next) {
|
||||||
if (strcmp(mpair.first.c_str(), kind) == 0) {
|
if (strcmp(reg->name, kind) == 0) {
|
||||||
return mpair.second();
|
return reg->maker();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -38,8 +40,8 @@ Channel::Channel(DrivenEngine *de, int chid, int port, const eng::string &target
|
|||||||
readline_lastc_ = 0;
|
readline_lastc_ = 0;
|
||||||
desired_prompt_ = "";
|
desired_prompt_ = "";
|
||||||
stop_driver_ = stop;
|
stop_driver_ = stop;
|
||||||
sb_in_ = std::make_shared<StreamBuffer>();
|
sb_in_ = eng::make_shared<StreamBuffer>();
|
||||||
sb_out_ = std::make_shared<StreamBuffer>();
|
sb_out_ = eng::make_shared<StreamBuffer>();
|
||||||
sb_drvout_ = sb_out_;
|
sb_drvout_ = sb_out_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +162,7 @@ double DrivenEngine::get_clock() {
|
|||||||
SharedChannel DrivenEngine::new_outgoing_channel(const eng::string &target) {
|
SharedChannel DrivenEngine::new_outgoing_channel(const eng::string &target) {
|
||||||
int chid = find_unused_chid();
|
int chid = find_unused_chid();
|
||||||
new_outgoing_.push_back(chid);
|
new_outgoing_.push_back(chid);
|
||||||
SharedChannel result = std::make_shared<Channel>(this, chid, 0, target, stop_driver_);
|
SharedChannel result = eng::make_shared<Channel>(this, chid, 0, target, stop_driver_);
|
||||||
channels_[chid] = result;
|
channels_[chid] = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -250,7 +252,7 @@ void DrivenEngine::drv_notify_close(int chid, std::string_view err) {
|
|||||||
|
|
||||||
int DrivenEngine::drv_notify_accept(int port) {
|
int DrivenEngine::drv_notify_accept(int port) {
|
||||||
int chid = find_unused_chid();
|
int chid = find_unused_chid();
|
||||||
channels_[chid] = std::make_shared<Channel>(this, chid, port, "", stop_driver_);
|
channels_[chid] = eng::make_shared<Channel>(this, chid, port, "", stop_driver_);
|
||||||
accepted_channels_.push_back(channels_[chid]);
|
accepted_channels_.push_back(channels_[chid]);
|
||||||
return chid;
|
return chid;
|
||||||
}
|
}
|
||||||
@@ -288,8 +290,8 @@ bool DrivenEngine::drv_get_stop_driver() const {
|
|||||||
|
|
||||||
DrivenEngine::DrivenEngine() {
|
DrivenEngine::DrivenEngine() {
|
||||||
next_unused_chid_ = 1;
|
next_unused_chid_ = 1;
|
||||||
stdio_channel_ = std::make_shared<Channel>(this, 0, 0, "", false);
|
stdio_channel_ = eng::make_shared<Channel>(this, 0, 0, "", false);
|
||||||
stdio_channel_->sb_drvout_ = std::make_shared<StreamBuffer>();
|
stdio_channel_->sb_drvout_ = eng::make_shared<StreamBuffer>();
|
||||||
channels_[0] = stdio_channel_;
|
channels_[0] = stdio_channel_;
|
||||||
rescan_lua_source_ = true;
|
rescan_lua_source_ = true;
|
||||||
clock_ = 0.0;
|
clock_ = 0.0;
|
||||||
|
|||||||
@@ -92,19 +92,21 @@
|
|||||||
#ifndef DRIVENENGINE_HPP
|
#ifndef DRIVENENGINE_HPP
|
||||||
#define DRIVENENGINE_HPP
|
#define DRIVENENGINE_HPP
|
||||||
|
|
||||||
#include "wrap-memory.hpp"
|
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
#include "wrap-ostream.hpp"
|
|
||||||
|
#include <ostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
|
|
||||||
class DrivenEngine;
|
class DrivenEngine;
|
||||||
using UniqueDrivenEngine = eng::unique_ptr<DrivenEngine>;
|
using UniqueDrivenEngine = std::unique_ptr<DrivenEngine>;
|
||||||
using DrivenEngineMaker = UniqueDrivenEngine (*)();
|
using DrivenEngineMaker = UniqueDrivenEngine (*)();
|
||||||
|
|
||||||
class Channel {
|
class Channel : public eng::opnew {
|
||||||
public:
|
public:
|
||||||
// Get the buffers associated with this channel.
|
// Get the buffers associated with this channel.
|
||||||
//
|
//
|
||||||
@@ -162,13 +164,13 @@ private:
|
|||||||
int chid_;
|
int chid_;
|
||||||
|
|
||||||
// These are the in/out buffers presented to the user.
|
// These are the in/out buffers presented to the user.
|
||||||
eng::shared_ptr<StreamBuffer> sb_in_;
|
std::shared_ptr<StreamBuffer> sb_in_;
|
||||||
eng::shared_ptr<StreamBuffer> sb_out_;
|
std::shared_ptr<StreamBuffer> sb_out_;
|
||||||
|
|
||||||
// If this is stdio, we inject tty echoes into the output stream.
|
// If this is stdio, we inject tty echoes into the output stream.
|
||||||
// This buffer holds the users output interleaved with the tty echoes.
|
// This buffer holds the users output interleaved with the tty echoes.
|
||||||
// In any other channel, this is just another pointer to sb_out.
|
// In any other channel, this is just another pointer to sb_out.
|
||||||
eng::shared_ptr<StreamBuffer> sb_drvout_;
|
std::shared_ptr<StreamBuffer> sb_drvout_;
|
||||||
|
|
||||||
int port_;
|
int port_;
|
||||||
bool closed_;
|
bool closed_;
|
||||||
@@ -186,10 +188,20 @@ private:
|
|||||||
friend class DrivenEngine;
|
friend class DrivenEngine;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SharedChannel = eng::shared_ptr<Channel>;
|
using SharedChannel = std::shared_ptr<Channel>;
|
||||||
|
|
||||||
class DrivenEngine {
|
class DrivenEngine : public eng::opnew {
|
||||||
public:
|
public:
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Build the named engine
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static UniqueDrivenEngine make(const char *name);
|
||||||
|
|
||||||
|
static void print_usage(std::ostream &strm, const char *progname);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// The following methods are the 'engine' side of the pipe.
|
// The following methods are the 'engine' side of the pipe.
|
||||||
@@ -254,7 +266,7 @@ public:
|
|||||||
|
|
||||||
// Obtain the output buffer of the stdio channel as an ostream.
|
// Obtain the output buffer of the stdio channel as an ostream.
|
||||||
//
|
//
|
||||||
eng::ostream &stdostream() { return get_stdio_channel()->out()->ostream(); }
|
std::ostream &stdostream() { return get_stdio_channel()->out()->ostream(); }
|
||||||
|
|
||||||
// Fetches the lua source, and takes ownership of it. The DrivenEngine
|
// Fetches the lua source, and takes ownership of it. The DrivenEngine
|
||||||
// no longer contains the source after calling this.
|
// no longer contains the source after calling this.
|
||||||
@@ -408,19 +420,6 @@ public:
|
|||||||
static void set(DrivenEngine *de);
|
static void set(DrivenEngine *de);
|
||||||
static DrivenEngine *get();
|
static DrivenEngine *get();
|
||||||
|
|
||||||
public:
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// The Registry of DrivenEngineMakers.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static void register_maker(const char *kind, DrivenEngineMaker maker);
|
|
||||||
|
|
||||||
static void print_usage(eng::ostream &strm, const char *progname);
|
|
||||||
|
|
||||||
static UniqueDrivenEngine make(const char *kind);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Find a currently-unused channel ID. Channel IDs
|
// Find a currently-unused channel ID. Channel IDs
|
||||||
// are small integers that are reused.
|
// are small integers that are reused.
|
||||||
@@ -443,4 +442,19 @@ private:
|
|||||||
friend class Channel;
|
friend class Channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DrivenEngineReg {
|
||||||
|
const char *name;
|
||||||
|
DrivenEngineMaker maker;
|
||||||
|
DrivenEngineReg *next;
|
||||||
|
static DrivenEngineReg *All;
|
||||||
|
DrivenEngineReg(const char *name, DrivenEngineMaker f);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DrivenEngineDefine(name, cname) \
|
||||||
|
UniqueDrivenEngine dengmake_##cname() { \
|
||||||
|
return UniqueDrivenEngine(new cname); \
|
||||||
|
} \
|
||||||
|
DrivenEngineReg dengreg_##cname(name, dengmake_##cname);
|
||||||
|
|
||||||
|
|
||||||
#endif // DRIVENENGINE_HPP
|
#endif // DRIVENENGINE_HPP
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
#define CHBUF_SIZE (256*1024)
|
#define CHBUF_SIZE (256*1024)
|
||||||
#define POLLVEC_SIZE (DrivenEngine::MAX_CHAN+1)
|
#define POLLVEC_SIZE (DrivenEngine::MAX_CHAN+1)
|
||||||
|
|
||||||
static drv::unique_ptr<char[]> chbuf;
|
static std::unique_ptr<char[]> chbuf;
|
||||||
static drv::unique_ptr<struct pollfd[]> pollvec;
|
static std::unique_ptr<struct pollfd[]> pollvec;
|
||||||
|
|
||||||
static MonoClock monoclock;
|
static MonoClock monoclock;
|
||||||
|
|
||||||
@@ -13,45 +13,33 @@ namespace util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initialize_engine() {
|
|
||||||
SourceDB::register_lua_builtins();
|
|
||||||
DrivenEngine::register_maker("textgame", make_TextGame);
|
|
||||||
DrivenEngine::register_maker("lpxclient", make_LpxClient);
|
|
||||||
DrivenEngine::register_maker("lpxserver", make_LpxServer);
|
|
||||||
DrivenEngine::register_maker("driverstubtest", make_DriverStubTest);
|
|
||||||
DrivenEngine::register_maker("driverwebservertest", make_DriverWebServerTest);
|
|
||||||
DrivenEngine::register_maker("driverdnsfailtest", make_DriverDNSFailTest);
|
|
||||||
DrivenEngine::register_maker("driverprintclocktest", make_DriverPrintClockTest);
|
|
||||||
DrivenEngine::register_maker("unittest", make_RunUnitTests);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void allocate_buffers() {
|
static void allocate_buffers() {
|
||||||
chbuf.reset(new char[CHBUF_SIZE]);
|
chbuf.reset(new char[CHBUF_SIZE]);
|
||||||
pollvec.reset(new struct pollfd[POLLVEC_SIZE]);
|
pollvec.reset(new struct pollfd[POLLVEC_SIZE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void if_error_print_and_exit(const drv::string &str) {
|
static void if_error_print_and_exit(const std::string &str) {
|
||||||
if (!str.empty()) {
|
if (!str.empty()) {
|
||||||
std::cerr << std::endl << "error: " << str << std::endl;
|
std::cerr << std::endl << "error: " << str << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string_view read_file(const char *fn, char *buf, int bufsize, drv::string &err) {
|
static std::string_view read_file(const char *fn, char *buf, int bufsize, std::string &err) {
|
||||||
FILE *f = fopen(fn, "r");
|
FILE *f = fopen(fn, "r");
|
||||||
if (f == 0) {
|
if (f == 0) {
|
||||||
err = drv::string("cannot read file") + fn;
|
err = std::string("cannot read file") + fn;
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
return std::string_view(buf, 0);
|
return std::string_view(buf, 0);
|
||||||
}
|
}
|
||||||
int nread = fread(buf, 1, bufsize, f);
|
int nread = fread(buf, 1, bufsize, f);
|
||||||
if (nread < 0) {
|
if (nread < 0) {
|
||||||
err = drv::string("cannot read file: ") + fn;
|
err = std::string("cannot read file: ") + fn;
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
return std::string_view(buf, 0);
|
return std::string_view(buf, 0);
|
||||||
}
|
}
|
||||||
if (nread == bufsize) {
|
if (nread == bufsize) {
|
||||||
err = drv::string("file too large: ") + fn;
|
err = std::string("file too large: ") + fn;
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
return std::string_view(buf, 0);
|
return std::string_view(buf, 0);
|
||||||
}
|
}
|
||||||
@@ -74,12 +62,12 @@ static SSL_CTX *new_ssl_context(bool server_cert, bool root_certs, std::string_v
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static drv::string err_print_errors_str() {
|
static std::string err_print_errors_str() {
|
||||||
BIO *bio = BIO_new(BIO_s_mem());
|
BIO *bio = BIO_new(BIO_s_mem());
|
||||||
ERR_print_errors(bio);
|
ERR_print_errors(bio);
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t len = BIO_get_mem_data(bio, &buf);
|
size_t len = BIO_get_mem_data(bio, &buf);
|
||||||
drv::string ret(buf, len);
|
std::string ret(buf, len);
|
||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -133,8 +121,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DrivenEngine *driven_;
|
DrivenEngine *driven_;
|
||||||
drv::vector<ChanInfo> chans_;
|
std::vector<ChanInfo> chans_;
|
||||||
drv::map<int, SOCKET> listen_sockets_;
|
std::map<int, SOCKET> listen_sockets_;
|
||||||
bool read_console_recently_;
|
bool read_console_recently_;
|
||||||
|
|
||||||
SSL_CTX *ssl_ctx_with_root_certs_;
|
SSL_CTX *ssl_ctx_with_root_certs_;
|
||||||
@@ -146,7 +134,7 @@ public:
|
|||||||
const auto &listenports = driven_->drv_get_listen_ports();
|
const auto &listenports = driven_->drv_get_listen_ports();
|
||||||
for (int port : listenports) {
|
for (int port : listenports) {
|
||||||
if (listen_sockets_.find(port) == listen_sockets_.end()) {
|
if (listen_sockets_.find(port) == listen_sockets_.end()) {
|
||||||
drv::string err;
|
std::string err;
|
||||||
SOCKET sock = listen_on_port(port, err);
|
SOCKET sock = listen_on_port(port, err);
|
||||||
if_error_print_and_exit(err);
|
if_error_print_and_exit(err);
|
||||||
assert(sock != INVALID_SOCKET);
|
assert(sock != INVALID_SOCKET);
|
||||||
@@ -157,13 +145,13 @@ public:
|
|||||||
|
|
||||||
void handle_lua_source() {
|
void handle_lua_source() {
|
||||||
if (driven_->drv_get_rescan_lua_source()) {
|
if (driven_->drv_get_rescan_lua_source()) {
|
||||||
drv::string err;
|
std::string err;
|
||||||
std::string_view ctrl = read_file("lua/control.lst", chbuf.get(), CHBUF_SIZE, err);
|
std::string_view ctrl = read_file("lua/control.lst", chbuf.get(), CHBUF_SIZE, err);
|
||||||
if_error_print_and_exit(err);
|
if_error_print_and_exit(err);
|
||||||
drv::vector<drv::string> names = drv::parse_control_lst(ctrl);
|
std::vector<std::string> names = drv::parse_control_lst(ctrl);
|
||||||
driven_->drv_clear_lua_source();
|
driven_->drv_clear_lua_source();
|
||||||
for (const drv::string &str : names) {
|
for (const std::string &str : names) {
|
||||||
drv::string lfn = drv::string("lua/") + str;
|
std::string lfn = std::string("lua/") + str;
|
||||||
std::string_view data = read_file(lfn.c_str(), chbuf.get(), CHBUF_SIZE, err);
|
std::string_view data = read_file(lfn.c_str(), chbuf.get(), CHBUF_SIZE, err);
|
||||||
if_error_print_and_exit(err);
|
if_error_print_and_exit(err);
|
||||||
driven_->drv_add_lua_source(str, data);
|
driven_->drv_add_lua_source(str, data);
|
||||||
@@ -255,7 +243,7 @@ public:
|
|||||||
void handle_new_outgoing_sockets() {
|
void handle_new_outgoing_sockets() {
|
||||||
const auto &chans = driven_->drv_get_new_outgoing();
|
const auto &chans = driven_->drv_get_new_outgoing();
|
||||||
for (int chid : chans) {
|
for (int chid : chans) {
|
||||||
drv::string err;
|
std::string err;
|
||||||
SOCKET sock = open_connection(driven_->drv_get_target(chid), err);
|
SOCKET sock = open_connection(driven_->drv_get_target(chid), err);
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
driven_->drv_notify_close(chid, err);
|
driven_->drv_notify_close(chid, err);
|
||||||
@@ -270,7 +258,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void accept_connection(int port, SOCKET sock) {
|
void accept_connection(int port, SOCKET sock) {
|
||||||
drv::string err;
|
std::string err;
|
||||||
SOCKET socket = accept_on_socket(sock, err);
|
SOCKET socket = accept_on_socket(sock, err);
|
||||||
if_error_print_and_exit(err);
|
if_error_print_and_exit(err);
|
||||||
if (socket != INVALID_SOCKET) {
|
if (socket != INVALID_SOCKET) {
|
||||||
@@ -281,7 +269,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void advance_plaintext(ChanInfo &chan) {
|
void advance_plaintext(ChanInfo &chan) {
|
||||||
drv::string err;
|
std::string err;
|
||||||
|
|
||||||
// If the channel has no outgoing bytes and has been released,
|
// If the channel has no outgoing bytes and has been released,
|
||||||
// just close it.
|
// just close it.
|
||||||
@@ -418,7 +406,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
void handle_socket_input_output() {
|
void handle_socket_input_output() {
|
||||||
drv::string err;
|
std::string err;
|
||||||
int mstimeout = read_console_recently_ ? 100 : 1000;
|
int mstimeout = read_console_recently_ ? 100 : 1000;
|
||||||
|
|
||||||
// Peek output buffers and determine channel release flags.
|
// Peek output buffers and determine channel release flags.
|
||||||
|
|||||||
@@ -6,10 +6,6 @@
|
|||||||
#include "drivenengine.hpp"
|
#include "drivenengine.hpp"
|
||||||
#include "dummycert.hpp"
|
#include "dummycert.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "textgame.hpp"
|
|
||||||
#include "lpxclient.hpp"
|
|
||||||
#include "lpxserver.hpp"
|
|
||||||
#include "eng-tests.hpp"
|
|
||||||
#include "source.hpp"
|
#include "source.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -43,7 +39,7 @@ const int INVALID_SOCKET = -1;
|
|||||||
|
|
||||||
struct termios orig_termios;
|
struct termios orig_termios;
|
||||||
|
|
||||||
static drv::string strerror_str(int err) {
|
static std::string strerror_str(int err) {
|
||||||
char errbuf[256];
|
char errbuf[256];
|
||||||
return strerror_r(errno, errbuf, 256);
|
return strerror_r(errno, errbuf, 256);
|
||||||
}
|
}
|
||||||
@@ -73,7 +69,7 @@ static void enable_tty_raw() {
|
|||||||
assert(status >= 0);
|
assert(status >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SOCKET open_connection(std::string_view target, drv::string &err) {
|
static SOCKET open_connection(std::string_view target, std::string &err) {
|
||||||
struct addrinfo *addrs = nullptr;
|
struct addrinfo *addrs = nullptr;
|
||||||
struct addrinfo *goodaddr = nullptr;
|
struct addrinfo *goodaddr = nullptr;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
@@ -86,7 +82,7 @@ static SOCKET open_connection(std::string_view target, drv::string &err) {
|
|||||||
hints.ai_flags = AI_NUMERICSERV;
|
hints.ai_flags = AI_NUMERICSERV;
|
||||||
|
|
||||||
err.clear();
|
err.clear();
|
||||||
drv::string host, port;
|
std::string host, port;
|
||||||
drv::split_host_port(target, host, port);
|
drv::split_host_port(target, host, port);
|
||||||
int status = getaddrinfo(host.c_str(), port.c_str(), &hints, &addrs);
|
int status = getaddrinfo(host.c_str(), port.c_str(), &hints, &addrs);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
@@ -119,7 +115,7 @@ error_general:
|
|||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SOCKET listen_on_port(int port, drv::string &err) {
|
static SOCKET listen_on_port(int port, std::string &err) {
|
||||||
int status, enable;
|
int status, enable;
|
||||||
err.clear();
|
err.clear();
|
||||||
|
|
||||||
@@ -150,7 +146,7 @@ error_errno:
|
|||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SOCKET accept_on_socket(SOCKET listen_socket, drv::string &err) {
|
static SOCKET accept_on_socket(SOCKET listen_socket, std::string &err) {
|
||||||
err.clear();
|
err.clear();
|
||||||
SOCKET chsock = accept(listen_socket, nullptr, nullptr);
|
SOCKET chsock = accept(listen_socket, nullptr, nullptr);
|
||||||
if (chsock >= 0) {
|
if (chsock >= 0) {
|
||||||
@@ -170,7 +166,7 @@ static SOCKET accept_on_socket(SOCKET listen_socket, drv::string &err) {
|
|||||||
// zero: would block
|
// zero: would block
|
||||||
// negative: channel closed, possibly cleanly or possibly with error
|
// negative: channel closed, possibly cleanly or possibly with error
|
||||||
//
|
//
|
||||||
static int socket_send(SOCKET socket, const char *bytes, int nbytes, drv::string &err) {
|
static int socket_send(SOCKET socket, const char *bytes, int nbytes, std::string &err) {
|
||||||
err.clear();
|
err.clear();
|
||||||
int wbytes = send(socket, bytes, nbytes, 0);
|
int wbytes = send(socket, bytes, nbytes, 0);
|
||||||
if (wbytes < 0) {
|
if (wbytes < 0) {
|
||||||
@@ -185,7 +181,7 @@ static int socket_send(SOCKET socket, const char *bytes, int nbytes, drv::string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_recv(SOCKET socket, char *bytes, int nbytes, drv::string &err) {
|
static int socket_recv(SOCKET socket, char *bytes, int nbytes, std::string &err) {
|
||||||
err.clear();
|
err.clear();
|
||||||
int nrecv = recv(socket, bytes, nbytes, 0);
|
int nrecv = recv(socket, bytes, nbytes, 0);
|
||||||
if (nrecv < 0) {
|
if (nrecv < 0) {
|
||||||
@@ -206,7 +202,7 @@ static int socket_close(SOCKET socket) {
|
|||||||
return close(socket);
|
return close(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_poll(struct pollfd *pollvec, int pollcount, int mstimeout, drv::string &err) {
|
static int socket_poll(struct pollfd *pollvec, int pollcount, int mstimeout, std::string &err) {
|
||||||
// socket_poll is implicitly expected to also poll stdin,
|
// socket_poll is implicitly expected to also poll stdin,
|
||||||
// if the OS allows that. Linux does, so we add stdin to the
|
// if the OS allows that. Linux does, so we add stdin to the
|
||||||
// poll vector. The poll vector is required to have at
|
// poll vector. The poll vector is required to have at
|
||||||
@@ -267,12 +263,11 @@ public:
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
mallopt(M_MMAP_MAX, 0); // Keep malloc in the 'brk' area.
|
|
||||||
disable_randomization(argc, argv);
|
disable_randomization(argc, argv);
|
||||||
allocate_buffers();
|
allocate_buffers();
|
||||||
enable_tty_raw();
|
enable_tty_raw();
|
||||||
OPENSSL_init_ssl(0, NULL);
|
OPENSSL_init_ssl(0, NULL);
|
||||||
initialize_engine();
|
SourceDB::register_lua_builtins();
|
||||||
driver_drive(argc, argv);
|
driver_drive(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,6 @@
|
|||||||
#include "drivenengine.hpp"
|
#include "drivenengine.hpp"
|
||||||
#include "dummycert.hpp"
|
#include "dummycert.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "textgame.hpp"
|
|
||||||
#include "lpxclient.hpp"
|
|
||||||
#include "lpxserver.hpp"
|
|
||||||
#include "eng-tests.hpp"
|
|
||||||
#include "source.hpp"
|
#include "source.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -35,8 +31,8 @@
|
|||||||
#define CHBUF_SIZE (256*1024)
|
#define CHBUF_SIZE (256*1024)
|
||||||
#define POLLVEC_SIZE (DrivenEngine::MAX_CHAN+1)
|
#define POLLVEC_SIZE (DrivenEngine::MAX_CHAN+1)
|
||||||
|
|
||||||
static drv::unique_ptr<char[]> chbuf;
|
static std::unique_ptr<char[]> chbuf;
|
||||||
static drv::unique_ptr<struct pollfd[]> pollvec;
|
static std::unique_ptr<struct pollfd[]> pollvec;
|
||||||
|
|
||||||
static void set_nonblocking(SOCKET sock) {
|
static void set_nonblocking(SOCKET sock) {
|
||||||
u_long mode = 1; // 1 to enable non-blocking socket
|
u_long mode = 1; // 1 to enable non-blocking socket
|
||||||
@@ -44,7 +40,7 @@ static void set_nonblocking(SOCKET sock) {
|
|||||||
assert(status == 0);
|
assert(status == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static drv::string winsock_error_string(int errcode) {
|
static std::string winsock_error_string(int errcode) {
|
||||||
drv::ostringstream oss;
|
drv::ostringstream oss;
|
||||||
oss << "error " << errcode;
|
oss << "error " << errcode;
|
||||||
return oss.str();
|
return oss.str();
|
||||||
@@ -55,11 +51,11 @@ static PADDRINFOA find_good_addr(PADDRINFOA addrinfo) {
|
|||||||
if (addr->ai_family == AF_INET) {
|
if (addr->ai_family == AF_INET) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
}drv::string
|
}std::string
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SOCKET open_connection(std::string_view target, drv::string &err) {
|
static SOCKET open_connection(std::string_view target, std::string &err) {
|
||||||
PADDRINFOA addrs = nullptr;
|
PADDRINFOA addrs = nullptr;
|
||||||
PADDRINFOA goodaddr = nullptr;
|
PADDRINFOA goodaddr = nullptr;
|
||||||
SOCKET sock = INVALID_SOCKET;
|
SOCKET sock = INVALID_SOCKET;
|
||||||
@@ -107,7 +103,7 @@ error:
|
|||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET listen_on_port(int port, drv::string &err) {
|
SOCKET listen_on_port(int port, std::string &err) {
|
||||||
int status;
|
int status;
|
||||||
err.clear();
|
err.clear();
|
||||||
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
|
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
@@ -140,7 +136,7 @@ error:
|
|||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SOCKET accept_on_socket(SOCKET listen_socket, drv::string &err) {
|
static SOCKET accept_on_socket(SOCKET listen_socket, std::string &err) {
|
||||||
SOCKET chsock = accept(listen_socket, nullptr, nullptr);
|
SOCKET chsock = accept(listen_socket, nullptr, nullptr);
|
||||||
if (chsock != INVALID_SOCKET) {
|
if (chsock != INVALID_SOCKET) {
|
||||||
set_nonblocking(chsock);
|
set_nonblocking(chsock);
|
||||||
@@ -156,7 +152,7 @@ static SOCKET accept_on_socket(SOCKET listen_socket, drv::string &err) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_send(SOCKET socket, const char *bytes, int nbytes, drv::string &err) {
|
static int socket_send(SOCKET socket, const char *bytes, int nbytes, std::string &err) {
|
||||||
err.clear();
|
err.clear();
|
||||||
int wbytes = send(socket, bytes, nbytes, 0);
|
int wbytes = send(socket, bytes, nbytes, 0);
|
||||||
if (wbytes == SOCKET_ERROR) {
|
if (wbytes == SOCKET_ERROR) {
|
||||||
@@ -173,7 +169,7 @@ static int socket_send(SOCKET socket, const char *bytes, int nbytes, drv::string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_recv(SOCKET socket, char *bytes, int nbytes, drv::string &err) {
|
static int socket_recv(SOCKET socket, char *bytes, int nbytes, std::string &err) {
|
||||||
err.clear();
|
err.clear();
|
||||||
int nrecv = recv(socket, bytes, nbytes, 0);
|
int nrecv = recv(socket, bytes, nbytes, 0);
|
||||||
if (nrecv < 0) {
|
if (nrecv < 0) {
|
||||||
@@ -195,7 +191,7 @@ static int socket_close(SOCKET socket) {
|
|||||||
return closesocket(socket);
|
return closesocket(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_poll(struct pollfd *pollvec, int pollcount, int mstimeout, drv::string &err) {
|
static int socket_poll(struct pollfd *pollvec, int pollcount, int mstimeout, std::string &err) {
|
||||||
int status = WSAPoll(pollvec, pollcount, mstimeout);
|
int status = WSAPoll(pollvec, pollcount, mstimeout);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
err = winsock_error_string(WSAGetLastError());
|
err = winsock_error_string(WSAGetLastError());
|
||||||
@@ -276,7 +272,7 @@ int main(int argc, char **argv)
|
|||||||
allocate_buffers();
|
allocate_buffers();
|
||||||
init_winsock();
|
init_winsock();
|
||||||
OPENSSL_init_ssl(0, NULL);
|
OPENSSL_init_ssl(0, NULL);
|
||||||
initialize_engine();
|
SourceDB::register_lua_builtins();
|
||||||
driver_drive(argc, argv);
|
driver_drive(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,9 @@
|
|||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace drv {
|
namespace drv {
|
||||||
|
|
||||||
void split_host_port(std::string_view target, drv::string &host, drv::string &port) {
|
void split_host_port(std::string_view target, std::string &host, std::string &port) {
|
||||||
size_t lastcolon = target.rfind(':');
|
size_t lastcolon = target.rfind(':');
|
||||||
if (lastcolon == std::string_view::npos) {
|
if (lastcolon == std::string_view::npos) {
|
||||||
host = ""; port = ""; return;
|
host = ""; port = ""; return;
|
||||||
@@ -23,8 +22,8 @@ void split_host_port(std::string_view target, drv::string &host, drv::string &po
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drv::vector<drv::string> parse_control_lst(std::string_view ctrl) {
|
std::vector<std::string> parse_control_lst(std::string_view ctrl) {
|
||||||
drv::vector<drv::string> result;
|
std::vector<std::string> result;
|
||||||
while (!ctrl.empty()) {
|
while (!ctrl.empty()) {
|
||||||
std::string_view line = util::sv_read_line(ctrl);
|
std::string_view line = util::sv_read_line(ctrl);
|
||||||
std::string_view trimmed = util::sv_trim(line);
|
std::string_view trimmed = util::sv_trim(line);
|
||||||
@@ -40,7 +39,7 @@ drv::vector<drv::string> parse_control_lst(std::string_view ctrl) {
|
|||||||
|
|
||||||
LuaDefine(unittests_driverutil, "", "some unit tests") {
|
LuaDefine(unittests_driverutil, "", "some unit tests") {
|
||||||
// Test split_host_port
|
// Test split_host_port
|
||||||
drv::string host, port;
|
std::string host, port;
|
||||||
drv::split_host_port("stanford.edu:80", host, port);
|
drv::split_host_port("stanford.edu:80", host, port);
|
||||||
LuaAssertStrEq(L, host, "stanford.edu");
|
LuaAssertStrEq(L, host, "stanford.edu");
|
||||||
LuaAssertStrEq(L, port, "80");
|
LuaAssertStrEq(L, port, "80");
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
namespace drv {
|
namespace drv {
|
||||||
|
|
||||||
void split_host_port(std::string_view target, drv::string &host, drv::string &port);
|
void split_host_port(std::string_view target, std::string &host, std::string &port);
|
||||||
|
|
||||||
drv::vector<drv::string> parse_control_lst(std::string_view ctrl);
|
std::vector<std::string> parse_control_lst(std::string_view ctrl);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
122
luprex/core/cpp/eng-malloc.cpp
Normal file
122
luprex/core/cpp/eng-malloc.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
|
||||||
|
// We only use a custom allocator on linux (for now)
|
||||||
|
// The allocator we chose is 'dlmalloc' (doug lea's malloc).
|
||||||
|
// It's a good allocator for single-threaded programs.
|
||||||
|
// It needs to be configured by setting a bunch of defines.
|
||||||
|
//
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
// We need this to define dlmalloc, not malloc.
|
||||||
|
#define USE_DL_PREFIX 1
|
||||||
|
|
||||||
|
// We don't need mspaces.
|
||||||
|
#define ONLY_MSPACES 0
|
||||||
|
#define MSPACES 0
|
||||||
|
|
||||||
|
// We don't need mallinfo
|
||||||
|
#define NO_MALLINFO 1
|
||||||
|
|
||||||
|
// We don't need dlmalloc_inspect_all
|
||||||
|
#define MALLOC_INSPECT_ALL 0
|
||||||
|
|
||||||
|
// Disable locking. The entire engine is single-threaded.
|
||||||
|
#define USE_LOCKS 0
|
||||||
|
|
||||||
|
// This allocator can use sbrk to obtain RAM. We're going to
|
||||||
|
// emulate sbrk, in order to put it in a different memory region
|
||||||
|
// than the system malloc, which also uses sbrk.
|
||||||
|
#define HAVE_MORECORE 1
|
||||||
|
#define MORECORE emulated_sbrk
|
||||||
|
#define MORECORE_CANNOT_TRIM 1
|
||||||
|
|
||||||
|
// We won't let the memory allocator use mmap. This is because
|
||||||
|
// opening the replay log may be implemented in stdio using mmap.
|
||||||
|
// So using mmap might trigger different results under replay.
|
||||||
|
#define HAVE_MMAP 0
|
||||||
|
|
||||||
|
// Fix a warning in dlmalloc.
|
||||||
|
#define MAX_RELEASE_CHECK_RATE INT_MAX
|
||||||
|
|
||||||
|
// Don't generate random seeds, or time-based seeds.
|
||||||
|
#define USE_DEV_RANDOM 0
|
||||||
|
#define LACKS_TIME_H 1
|
||||||
|
|
||||||
|
// Don't export any dlmalloc functions.
|
||||||
|
#define DLMALLOC_EXPORT static inline
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
static char *emulated_sbrk_base;
|
||||||
|
static intptr_t emulated_sbrk_used;
|
||||||
|
static intptr_t emulated_sbrk_limit;
|
||||||
|
|
||||||
|
// We assume that the increments are already aligned to the system
|
||||||
|
// page size, because dlmalloc does that for us.
|
||||||
|
//
|
||||||
|
// Our emulated sbrk cannot trim the memory size. It can only grow.
|
||||||
|
//
|
||||||
|
static void *emulated_sbrk(intptr_t increment) {
|
||||||
|
if (emulated_sbrk_base == 0) {
|
||||||
|
emulated_sbrk_limit = intptr_t(64) * 1024 * 1024 * 1024;
|
||||||
|
void *map = mmap(nullptr, emulated_sbrk_limit, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
|
assert(map != MAP_FAILED);
|
||||||
|
assert(map != nullptr);
|
||||||
|
emulated_sbrk_base = (char *)map;
|
||||||
|
emulated_sbrk_used = 0;
|
||||||
|
}
|
||||||
|
int64_t old_used = emulated_sbrk_used;
|
||||||
|
int64_t new_used = emulated_sbrk_used + increment;
|
||||||
|
if (new_used > emulated_sbrk_limit) {
|
||||||
|
return (void *)(-1);
|
||||||
|
}
|
||||||
|
assert(new_used >= old_used);
|
||||||
|
emulated_sbrk_used = new_used;
|
||||||
|
if (new_used > old_used) {
|
||||||
|
int status = mprotect(emulated_sbrk_base + old_used, new_used - old_used, PROT_READ | PROT_WRITE);
|
||||||
|
assert(status == 0);
|
||||||
|
}
|
||||||
|
return emulated_sbrk_base + old_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "dlmalloc/dlmalloc.c"
|
||||||
|
|
||||||
|
namespace eng {
|
||||||
|
static uint32_t hash;
|
||||||
|
void *malloc(size_t size) {
|
||||||
|
void *result = dlmalloc(size);
|
||||||
|
hash += uint32_t(uintptr_t(result)) + 0x83748374;
|
||||||
|
hash += hash << 10;
|
||||||
|
hash ^= hash >> 6;
|
||||||
|
hash += uint32_t(size) + 0x85893489;
|
||||||
|
hash += hash << 10;
|
||||||
|
hash ^= hash >> 6;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void *realloc(void *p, size_t size) {
|
||||||
|
void *result = dlrealloc(p, size);
|
||||||
|
hash += uint32_t(uintptr_t(p)) + 0x74741912;
|
||||||
|
hash += hash << 10;
|
||||||
|
hash ^= hash >> 6;
|
||||||
|
hash += uint32_t(uintptr_t(result)) + 0x68843823;
|
||||||
|
hash += hash << 10;
|
||||||
|
hash ^= hash >> 6;
|
||||||
|
hash += uint32_t(size) + 0x81444120;
|
||||||
|
hash += hash << 10;
|
||||||
|
hash ^= hash >> 6;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void free(void *p) {
|
||||||
|
hash += uint32_t(uintptr_t(p)) + 0x87823448;
|
||||||
|
dlfree(p);
|
||||||
|
}
|
||||||
|
int memhash() {
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
} // namespace eng
|
||||||
|
|
||||||
|
#endif // ifdef __linux__
|
||||||
|
|
||||||
|
|
||||||
192
luprex/core/cpp/eng-malloc.hpp
Normal file
192
luprex/core/cpp/eng-malloc.hpp
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
//
|
||||||
|
// eng-malloc
|
||||||
|
//
|
||||||
|
// The engine has its own private eng::malloc which it uses to allocate
|
||||||
|
// everything. The engine's malloc heap only contains engine data structures.
|
||||||
|
// This helps achieve determinism when playing a replay log.
|
||||||
|
//
|
||||||
|
// The engine's eng::malloc is a thin wrapper around Doug Lea's Malloc, a good
|
||||||
|
// general-purpose single-threaded malloc. It's probably not the fastest any
|
||||||
|
// more (it was, once), but it's still quite good. It's also fairly easy
|
||||||
|
// to work with.
|
||||||
|
//
|
||||||
|
// In order to get all engine data structures into the eng::malloc heap, you
|
||||||
|
// need to jump through quite a few hoops:
|
||||||
|
//
|
||||||
|
// * 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.
|
||||||
|
//
|
||||||
|
// * 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.
|
||||||
|
//
|
||||||
|
// * 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 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 eng::malloc
|
||||||
|
// heap.
|
||||||
|
//
|
||||||
|
// * Failing to jump through all these hoops won't break your code in any
|
||||||
|
// obvious way - you'll just have some of your data structures in the malloc
|
||||||
|
// heap instead of the eng::malloc heap. This can break determinism of
|
||||||
|
// replay.
|
||||||
|
//
|
||||||
|
#ifndef ENG_MALLOC_HPP
|
||||||
|
#define ENG_MALLOC_HPP
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace eng {
|
||||||
|
#ifdef __linux__
|
||||||
|
void* malloc(size_t x);
|
||||||
|
void free(void *p);
|
||||||
|
void* realloc(void*, size_t);
|
||||||
|
int memhash();
|
||||||
|
#else
|
||||||
|
inline void *malloc(size_t x) { return ::malloc(x); }
|
||||||
|
inline void free(void *p) { return ::free(x); }
|
||||||
|
inline void *realloc(void *p, size_t x) { return ::realloc(p, x); }
|
||||||
|
inline int memhash() { return 0; }
|
||||||
|
#endif
|
||||||
|
} // namespace eng
|
||||||
|
|
||||||
|
// An allocator for lua states that uses eng::malloc and eng::free
|
||||||
|
namespace eng {
|
||||||
|
inline void *l_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
|
||||||
|
if (nsize == 0) {
|
||||||
|
::eng::free(ptr);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return ::eng::realloc(ptr, nsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace eng
|
||||||
|
|
||||||
|
// eng_allocator is similar to std::allocator, but allocates
|
||||||
|
// objects using eng::malloc and eng::free.
|
||||||
|
template <class T>
|
||||||
|
class eng_allocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
eng_allocator() noexcept {}
|
||||||
|
template <class U> eng_allocator(eng_allocator<U> const&) noexcept {}
|
||||||
|
|
||||||
|
value_type* allocate(std::size_t n)
|
||||||
|
{
|
||||||
|
return static_cast<value_type*>(eng::malloc(n*sizeof(value_type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(value_type* p, std::size_t) noexcept
|
||||||
|
{
|
||||||
|
eng::free(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Another name for eng_allocator is eng::allocator.
|
||||||
|
namespace eng {
|
||||||
|
template<class T>
|
||||||
|
using allocator = ::eng_allocator<T>;
|
||||||
|
} // namespace eng
|
||||||
|
|
||||||
|
// Mandated equality and inequality operators for eng_allocator.
|
||||||
|
template <class T, class U>
|
||||||
|
bool operator==(const eng_allocator<T> &, const eng_allocator<U> &) noexcept
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template <class T, class U>
|
||||||
|
bool operator!=(const eng_allocator<T> &, const eng_allocator<U> &) noexcept
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eng::opnew. A class containing operator new and operator delete,
|
||||||
|
// meant to be used as a base class for inheritance.
|
||||||
|
namespace eng {
|
||||||
|
class opnew {
|
||||||
|
public:
|
||||||
|
void *operator new(size_t size)
|
||||||
|
{
|
||||||
|
return ::eng::malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *p, size_t size)
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
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.
|
||||||
|
namespace eng {
|
||||||
|
template<class T, class... Args>
|
||||||
|
inline ::std::unique_ptr<T> make_unique(Args&&... args) {
|
||||||
|
return std::make_unique<T>(args...);
|
||||||
|
}
|
||||||
|
} // namespace eng
|
||||||
|
|
||||||
|
#endif // ENG_MALLOC_HPP
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
|
|
||||||
#include "eng-tests.hpp"
|
|
||||||
#include "drivenengine.hpp"
|
#include "drivenengine.hpp"
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
@@ -96,7 +95,7 @@ public:
|
|||||||
virtual void event_update() {
|
virtual void event_update() {
|
||||||
double clock = get_clock();
|
double clock = get_clock();
|
||||||
if (clock > last_clock_ + 0.5) {
|
if (clock > last_clock_ + 0.5) {
|
||||||
int ms = dlmalloc_hash();
|
int ms = eng::memhash();
|
||||||
stdostream() << std::fixed << std::setprecision(2) << clock << " " << std::hex << ms << " ";
|
stdostream() << std::fixed << std::setprecision(2) << clock << " " << std::hex << ms << " ";
|
||||||
count_++;
|
count_++;
|
||||||
last_clock_ = clock;
|
last_clock_ = clock;
|
||||||
@@ -122,23 +121,9 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
UniqueDrivenEngine make_DriverStubTest() {
|
DrivenEngineDefine("driverstubtest", DriverStubTest);
|
||||||
return UniqueDrivenEngine(new DriverStubTest);
|
DrivenEngineDefine("driverwebservertest", DriverWebServerTest);
|
||||||
}
|
DrivenEngineDefine("driverdnsfailtest", DriverDNSFailTest);
|
||||||
|
DrivenEngineDefine("driverprintclocktest", DriverPrintClockTest);
|
||||||
UniqueDrivenEngine make_DriverWebServerTest() {
|
DrivenEngineDefine("rununittests", RunUnitTests);
|
||||||
return UniqueDrivenEngine(new DriverWebServerTest);
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueDrivenEngine make_DriverDNSFailTest() {
|
|
||||||
return UniqueDrivenEngine(new DriverDNSFailTest);
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueDrivenEngine make_DriverPrintClockTest() {
|
|
||||||
return UniqueDrivenEngine(new DriverPrintClockTest);
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueDrivenEngine make_RunUnitTests() {
|
|
||||||
return UniqueDrivenEngine(new RunUnitTests);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
#ifndef DRIVERTESTS_HPP
|
#ifndef DRIVERTESTS_HPP
|
||||||
#define DRIVERTESTS_HPP
|
#define DRIVERTESTS_HPP
|
||||||
|
|
||||||
#include "drivenengine.hpp"
|
|
||||||
|
|
||||||
UniqueDrivenEngine make_DriverStubTest();
|
|
||||||
UniqueDrivenEngine make_DriverListenTest();
|
|
||||||
UniqueDrivenEngine make_DriverWebServerTest();
|
|
||||||
UniqueDrivenEngine make_DriverDNSFailTest();
|
|
||||||
UniqueDrivenEngine make_DriverPrintClockTest();
|
|
||||||
UniqueDrivenEngine make_RunUnitTests();
|
|
||||||
|
|
||||||
#endif // DRIVERTESTS_HPP
|
#endif // DRIVERTESTS_HPP
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
|
|
||||||
class GuiElt {
|
class GuiElt : public eng::nevernew {
|
||||||
friend class Gui;
|
friend class Gui;
|
||||||
public:
|
public:
|
||||||
enum Type {
|
enum Type {
|
||||||
@@ -27,7 +27,7 @@ public:
|
|||||||
const eng::string &label() const { return label_; }
|
const eng::string &label() const { return label_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Gui {
|
class Gui : public eng::nevernew {
|
||||||
public:
|
public:
|
||||||
using EltVec = eng::vector<GuiElt>;
|
using EltVec = eng::vector<GuiElt>;
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
#include "wrap-map.hpp"
|
#include "wrap-map.hpp"
|
||||||
#include "wrap-sstream.hpp"
|
#include "wrap-sstream.hpp"
|
||||||
#include "wrap-deque.hpp"
|
#include "wrap-deque.hpp"
|
||||||
#include "wrap-ostream.hpp"
|
|
||||||
|
|
||||||
#include "idalloc.hpp"
|
#include "idalloc.hpp"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
|
||||||
static bool ranges_equal(const eng::deque<int64_t> &dq, int64_t a, int64_t b, int64_t c) {
|
static bool ranges_equal(const eng::deque<int64_t> &dq, int64_t a, int64_t b, int64_t c) {
|
||||||
if (dq.size() != 3) return false;
|
if (dq.size() != 3) return false;
|
||||||
|
|||||||
@@ -68,15 +68,14 @@
|
|||||||
#include "wrap-map.hpp"
|
#include "wrap-map.hpp"
|
||||||
#include "wrap-sstream.hpp"
|
#include "wrap-sstream.hpp"
|
||||||
#include "wrap-deque.hpp"
|
#include "wrap-deque.hpp"
|
||||||
#include "wrap-ostream.hpp"
|
|
||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "debugcollector.hpp"
|
#include "debugcollector.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
class IdGlobalPool {
|
class IdGlobalPool : public eng::nevernew {
|
||||||
public:
|
public:
|
||||||
// Construct and destroy global pools. Note that after constructing
|
// Construct and destroy global pools. Note that after constructing
|
||||||
// a global pool, it is generally also necessary to initialize it
|
// a global pool, it is generally also necessary to initialize it
|
||||||
@@ -120,7 +119,7 @@ private:
|
|||||||
friend int unittests_idalloc(lua_State *L);
|
friend int unittests_idalloc(lua_State *L);
|
||||||
};
|
};
|
||||||
|
|
||||||
class IdPlayerPool {
|
class IdPlayerPool : public eng::nevernew {
|
||||||
public:
|
public:
|
||||||
// Construct a player pool.
|
// Construct a player pool.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public:
|
|||||||
void deserialize(StreamBuffer *sb);
|
void deserialize(StreamBuffer *sb);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Invocation {
|
class Invocation : public eng::nevernew {
|
||||||
public:
|
public:
|
||||||
enum Kind {
|
enum Kind {
|
||||||
KIND_INVALID,
|
KIND_INVALID,
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
#include "wrap-memory.hpp"
|
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
|
|
||||||
#include "drivenengine.hpp"
|
#include "drivenengine.hpp"
|
||||||
#include "lpxclient.hpp"
|
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
#include "luaconsole.hpp"
|
#include "luaconsole.hpp"
|
||||||
#include "invocation.hpp"
|
#include "invocation.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "printbuffer.hpp"
|
#include "printbuffer.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class LpxClient : public DrivenEngine {
|
class LpxClient : public DrivenEngine {
|
||||||
public:
|
public:
|
||||||
using StringVec = LuaConsole::StringVec;
|
using StringVec = LuaConsole::StringVec;
|
||||||
@@ -282,7 +282,5 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
UniqueDrivenEngine make_LpxClient() {
|
DrivenEngineDefine("lpxclient", LpxClient);
|
||||||
return UniqueDrivenEngine(new LpxClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
#ifndef LPXCLIENT_HPP
|
#ifndef LPXCLIENT_HPP
|
||||||
#define LPXCLIENT_HPP
|
#define LPXCLIENT_HPP
|
||||||
|
|
||||||
#include "drivenengine.hpp"
|
|
||||||
|
|
||||||
UniqueDrivenEngine make_LpxClient();
|
|
||||||
|
|
||||||
#endif // LPXCLIENT_HPP
|
#endif // LPXCLIENT_HPP
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
#include "wrap-memory.hpp"
|
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
|
|
||||||
#include "lpxserver.hpp"
|
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
#include "drivenengine.hpp"
|
#include "drivenengine.hpp"
|
||||||
#include "luaconsole.hpp"
|
#include "luaconsole.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "printbuffer.hpp"
|
#include "printbuffer.hpp"
|
||||||
|
|
||||||
class Client {
|
#include <memory>
|
||||||
|
|
||||||
|
class Client : public eng::opnew {
|
||||||
public:
|
public:
|
||||||
int64_t actor_id_;
|
int64_t actor_id_;
|
||||||
SharedChannel channel_;
|
SharedChannel channel_;
|
||||||
UniqueWorld sync_;
|
UniqueWorld sync_;
|
||||||
};
|
};
|
||||||
using UniqueClient = eng::unique_ptr<Client>;
|
using UniqueClient = std::unique_ptr<Client>;
|
||||||
using ClientVector = eng::vector<UniqueClient>;
|
using ClientVector = eng::vector<UniqueClient>;
|
||||||
|
|
||||||
class LpxServer : public DrivenEngine {
|
class LpxServer : public DrivenEngine {
|
||||||
@@ -179,7 +179,5 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
UniqueDrivenEngine make_LpxServer() {
|
DrivenEngineDefine("lpxserver", LpxServer);
|
||||||
return UniqueDrivenEngine(new LpxServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
#ifndef LPXSERVER_HPP
|
#ifndef LPXSERVER_HPP
|
||||||
#define LPXSERVER_HPP
|
#define LPXSERVER_HPP
|
||||||
|
|
||||||
#include "drivenengine.hpp"
|
|
||||||
|
|
||||||
UniqueDrivenEngine make_LpxServer();
|
|
||||||
|
|
||||||
#endif // LPXSERVER_HPP
|
#endif // LPXSERVER_HPP
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "eng-malloc.hpp"
|
||||||
|
#include "luastack.hpp"
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
|
|
||||||
@@ -8,7 +10,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
LuaConsole::LuaConsole() {
|
LuaConsole::LuaConsole() {
|
||||||
lua_state_ = luaL_newstate();
|
lua_state_ = LuaStack::newstate(eng::l_alloc);
|
||||||
clear_raw_input();
|
clear_raw_input();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
|
|
||||||
class LuaConsole {
|
class LuaConsole : public eng::nevernew {
|
||||||
public:
|
public:
|
||||||
using StringVec = eng::vector<eng::string>;
|
using StringVec = eng::vector<eng::string>;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
|
|
||||||
LuaSnap::LuaSnap() {
|
LuaSnap::LuaSnap() {
|
||||||
state_ = luaL_newstate();
|
state_ = LuaStack::newstate(eng::l_alloc);
|
||||||
LuaStack LS(state_);
|
LuaStack LS(state_);
|
||||||
|
|
||||||
// Create the persist table and the unpersist table.
|
// Create the persist table and the unpersist table.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
|
|
||||||
class LuaSnap {
|
class LuaSnap : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
lua_State *state_;
|
lua_State *state_;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
LuaSpecial LuaRegistry(LUA_REGISTRYINDEX);
|
LuaSpecial LuaRegistry(LUA_REGISTRYINDEX);
|
||||||
LuaNilMarker LuaNil;
|
LuaNilMarker LuaNil;
|
||||||
@@ -11,20 +12,12 @@ LuaFunctionReg::LuaFunctionReg(const char *n, const char *a, const char *d, lua_
|
|||||||
args_ = a;
|
args_ = a;
|
||||||
docs_ = d;
|
docs_ = d;
|
||||||
func_ = f;
|
func_ = f;
|
||||||
next_ = LuaFunctionRegistry;
|
next_ = All;
|
||||||
LuaFunctionRegistry = this;
|
All = this;
|
||||||
}
|
|
||||||
|
|
||||||
LuaFunctionReg::List LuaFunctionReg::all() {
|
|
||||||
LuaFunctionReg::List result;
|
|
||||||
for (LuaFunctionReg *r = LuaFunctionRegistry; r != 0; r = r->next_) {
|
|
||||||
result.push_back(r);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LuaFunctionReg *LuaFunctionReg::lookup(lua_CFunction fn) {
|
const LuaFunctionReg *LuaFunctionReg::lookup(lua_CFunction fn) {
|
||||||
for (const LuaFunctionReg *r = LuaFunctionRegistry; r != 0; r = r->next_) {
|
for (const LuaFunctionReg *r = All; r != 0; r = r->next_) {
|
||||||
if (r->func_ == fn) {
|
if (r->func_ == fn) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -32,8 +25,31 @@ const LuaFunctionReg *LuaFunctionReg::lookup(lua_CFunction fn) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaFunctionReg *LuaFunctionReg::LuaFunctionRegistry;
|
LuaFunctionReg *LuaFunctionReg::All;
|
||||||
|
|
||||||
|
static int panicf(lua_State *L) {
|
||||||
|
const char *p = lua_tostring(L, -1);
|
||||||
|
fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", p);
|
||||||
|
fflush(stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// An allocator for lua states that uses system malloc and system free.
|
||||||
|
static void *l_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
|
||||||
|
if (nsize == 0) {
|
||||||
|
free(ptr);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return realloc(ptr, nsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_State *LuaStack::newstate (lua_Alloc allocf) {
|
||||||
|
if (allocf == nullptr) allocf = l_alloc;
|
||||||
|
lua_State *L = lua_newstate(allocf, NULL);
|
||||||
|
if (L) lua_atpanic(L, &panicf);
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
bool LuaStack::ckboolean(LuaSlot s) const {
|
bool LuaStack::ckboolean(LuaSlot s) const {
|
||||||
luaL_checktype(L_, s, LUA_TBOOLEAN);
|
luaL_checktype(L_, s, LUA_TBOOLEAN);
|
||||||
@@ -154,7 +170,7 @@ lua_State *LuaStack::newthread(LuaSlot target) const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LuaStack::validclassname(const eng::string &cname) {
|
bool LuaStack::validclassname(std::string_view cname) {
|
||||||
if (cname.empty()) return false;
|
if (cname.empty()) return false;
|
||||||
if (cname == "_G") return false;
|
if (cname == "_G") return false;
|
||||||
return true;
|
return true;
|
||||||
@@ -243,15 +259,7 @@ eng::string LuaStack::getclass(LuaSlot classtab, LuaSlot classname) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eng::string LuaStack::getclass(LuaSlot tab, const char *name) const {
|
eng::string LuaStack::getclass(LuaSlot tab, std::string_view name) const {
|
||||||
push_any_value(name);
|
|
||||||
LuaSpecial classname(lua_gettop(L_));
|
|
||||||
eng::string err = getclass(tab, classname);
|
|
||||||
lua_pop(L_, 1);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
eng::string LuaStack::getclass(LuaSlot tab, const eng::string &name) const {
|
|
||||||
push_any_value(name);
|
push_any_value(name);
|
||||||
LuaSpecial classname(lua_gettop(L_));
|
LuaSpecial classname(lua_gettop(L_));
|
||||||
eng::string err = getclass(tab, classname);
|
eng::string err = getclass(tab, classname);
|
||||||
@@ -288,14 +296,7 @@ void LuaStack::makeclass(LuaSlot classtab, LuaSlot classname) const {
|
|||||||
LS.result();
|
LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaStack::makeclass(LuaSlot tab, const char *name) const {
|
void LuaStack::makeclass(LuaSlot tab, std::string_view name) const {
|
||||||
push_any_value(name);
|
|
||||||
LuaSpecial classname(lua_gettop(L_));
|
|
||||||
makeclass(tab, classname);
|
|
||||||
lua_pop(L_, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LuaStack::makeclass(LuaSlot tab, const eng::string &name) const {
|
|
||||||
push_any_value(name);
|
push_any_value(name);
|
||||||
LuaSpecial classname(lua_gettop(L_));
|
LuaSpecial classname(lua_gettop(L_));
|
||||||
makeclass(tab, classname);
|
makeclass(tab, classname);
|
||||||
|
|||||||
@@ -155,7 +155,6 @@
|
|||||||
#define LUASTACK_HPP
|
#define LUASTACK_HPP
|
||||||
|
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-vector.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
@@ -164,7 +163,7 @@ extern "C" {
|
|||||||
#include "eris.h"
|
#include "eris.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
class LuaSlot {
|
class LuaSlot : public eng::nevernew {
|
||||||
protected:
|
protected:
|
||||||
int index_;
|
int index_;
|
||||||
private:
|
private:
|
||||||
@@ -227,7 +226,7 @@ int LuaTypeTagValue(lua_State *L) { return 0; }
|
|||||||
#define LUA_TT_GLOBALDB 22
|
#define LUA_TT_GLOBALDB 22
|
||||||
#define LUA_TT_CLASS 23
|
#define LUA_TT_CLASS 23
|
||||||
|
|
||||||
class LuaStack {
|
class LuaStack : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
int narg_;
|
int narg_;
|
||||||
int ngap_;
|
int ngap_;
|
||||||
@@ -296,6 +295,7 @@ private:
|
|||||||
void push_any_value(LuaNilMarker s) const { lua_pushnil(L_); }
|
void push_any_value(LuaNilMarker s) const { lua_pushnil(L_); }
|
||||||
void push_any_value(LuaSlot s) const { lua_pushvalue(L_, s); }
|
void push_any_value(LuaSlot s) const { lua_pushvalue(L_, s); }
|
||||||
void push_any_value(const eng::string &s) const { lua_pushlstring(L_, s.c_str(), s.size()); }
|
void push_any_value(const eng::string &s) const { lua_pushlstring(L_, s.c_str(), s.size()); }
|
||||||
|
void push_any_value(std::string_view s) const { lua_pushlstring(L_, s.data(), s.size()); }
|
||||||
void push_any_value(const char *s) const { lua_pushstring(L_, s); }
|
void push_any_value(const char *s) const { lua_pushstring(L_, s); }
|
||||||
void push_any_value(float s) const { lua_pushnumber(L_, s); }
|
void push_any_value(float s) const { lua_pushnumber(L_, s); }
|
||||||
void push_any_value(double s) const { lua_pushnumber(L_, s); }
|
void push_any_value(double s) const { lua_pushnumber(L_, s); }
|
||||||
@@ -334,6 +334,8 @@ public:
|
|||||||
int result();
|
int result();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static lua_State *newstate (lua_Alloc allocf);
|
||||||
|
|
||||||
lua_State *state() const { return L_; }
|
lua_State *state() const { return L_; }
|
||||||
|
|
||||||
int type(LuaSlot s) const { return lua_type(L_, s); }
|
int type(LuaSlot s) const { return lua_type(L_, s); }
|
||||||
@@ -379,7 +381,7 @@ public:
|
|||||||
|
|
||||||
// Return true if the classname is legal.
|
// Return true if the classname is legal.
|
||||||
bool validclassname(LuaSlot value) const;
|
bool validclassname(LuaSlot value) const;
|
||||||
static bool validclassname(const eng::string &cname);
|
static bool validclassname(std::string_view cname);
|
||||||
|
|
||||||
// Return the class name if x is a valid classtab.
|
// Return the class name if x is a valid classtab.
|
||||||
// Otherwise, returns empty string. If nonempty, the
|
// Otherwise, returns empty string. If nonempty, the
|
||||||
@@ -392,15 +394,13 @@ public:
|
|||||||
// There are lots of error conditions, including such things
|
// There are lots of error conditions, including such things
|
||||||
// as no such class, corrupted class, classname invalid, etc.
|
// as no such class, corrupted class, classname invalid, etc.
|
||||||
eng::string getclass(LuaSlot tab, LuaSlot name) const;
|
eng::string getclass(LuaSlot tab, LuaSlot name) const;
|
||||||
eng::string getclass(LuaSlot tab, const char *name) const;
|
eng::string getclass(LuaSlot tab, std::string_view name) const;
|
||||||
eng::string getclass(LuaSlot tab, const eng::string &name) const;
|
|
||||||
|
|
||||||
// Create a class, or look up an existing class.
|
// Create a class, or look up an existing class.
|
||||||
// WARNING: this routine assert-fails if the parameter is not
|
// WARNING: this routine assert-fails if the parameter is not
|
||||||
// a valid classname. Check the classname before calling this!
|
// a valid classname. Check the classname before calling this!
|
||||||
void makeclass(LuaSlot tab, LuaSlot name) const;
|
void makeclass(LuaSlot tab, LuaSlot name) const;
|
||||||
void makeclass(LuaSlot tab, const char *name) const;
|
void makeclass(LuaSlot tab, std::string_view name) const;
|
||||||
void makeclass(LuaSlot tab, const eng::string &name) const;
|
|
||||||
|
|
||||||
// Get the ID of a tangible. It's a little weird to put this in
|
// Get the ID of a tangible. It's a little weird to put this in
|
||||||
// this module.
|
// this module.
|
||||||
@@ -470,7 +470,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class LuaFunctionReg {
|
class LuaFunctionReg : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
const char *name_;
|
const char *name_;
|
||||||
const char *args_;
|
const char *args_;
|
||||||
@@ -478,19 +478,16 @@ private:
|
|||||||
lua_CFunction func_;
|
lua_CFunction func_;
|
||||||
LuaFunctionReg *next_;
|
LuaFunctionReg *next_;
|
||||||
|
|
||||||
static LuaFunctionReg *LuaFunctionRegistry;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using List = eng::vector<LuaFunctionReg *>;
|
static LuaFunctionReg *All;
|
||||||
|
|
||||||
LuaFunctionReg(const char *name, const char *args, const char *docs, lua_CFunction f);
|
LuaFunctionReg(const char *name, const char *args, const char *docs, lua_CFunction f);
|
||||||
static List all();
|
|
||||||
static const LuaFunctionReg *lookup(lua_CFunction fn);
|
static const LuaFunctionReg *lookup(lua_CFunction fn);
|
||||||
|
|
||||||
const char *get_name() const { return name_; }
|
const char *get_name() const { return name_; }
|
||||||
const char *get_args() const { return args_; }
|
const char *get_args() const { return args_; }
|
||||||
const char *get_docs() const { return docs_; }
|
const char *get_docs() const { return docs_; }
|
||||||
lua_CFunction get_func() const { return func_; }
|
lua_CFunction get_func() const { return func_; }
|
||||||
|
LuaFunctionReg *next() const { return next_; }
|
||||||
void set_func(lua_CFunction fn) { func_ = fn; }
|
void set_func(lua_CFunction fn) { func_ = fn; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "wrap-algorithm.hpp"
|
|
||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "planemap.hpp"
|
#include "planemap.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
|
|
||||||
class PlaneMap;
|
class PlaneMap;
|
||||||
|
|
||||||
class PlaneItem {
|
class PlaneItem : public eng::nevernew {
|
||||||
friend class PlaneMap;
|
friend class PlaneMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -112,7 +112,7 @@ public:
|
|||||||
void set_xyz(float x, float y, float z) { set_pos(plane_, x, y, z); }
|
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;
|
friend class PlaneItem;
|
||||||
private:
|
private:
|
||||||
using EltVec = eng::vector<PlaneItem *>;
|
using EltVec = eng::vector<PlaneItem *>;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
#include "wrap-ostream.hpp"
|
#include <ostream>
|
||||||
|
|
||||||
#include "pprint.hpp"
|
#include "pprint.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "table.hpp"
|
#include "table.hpp"
|
||||||
@@ -8,7 +7,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
void atomic_print(LuaStack &LS, LuaSlot val, bool quote, eng::ostream *os) {
|
void atomic_print(LuaStack &LS, LuaSlot val, bool quote, std::ostream *os) {
|
||||||
int tt = LS.type(val);
|
int tt = LS.type(val);
|
||||||
switch (tt) {
|
switch (tt) {
|
||||||
case LUA_TNIL:
|
case LUA_TNIL:
|
||||||
@@ -103,7 +102,7 @@ struct Inspector {
|
|||||||
bool indent;
|
bool indent;
|
||||||
int maxlen;
|
int maxlen;
|
||||||
bool anyindent;
|
bool anyindent;
|
||||||
eng::ostream *stream;
|
std::ostream *stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void tabify(Inspector &insp, int level) {
|
static void tabify(Inspector &insp, int level) {
|
||||||
@@ -235,7 +234,7 @@ static void pprint_r(Inspector &insp, int level, LuaSlot root) {
|
|||||||
LS.result();
|
LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pprint(LuaStack &LS0, LuaSlot root, bool indent, eng::ostream *os) {
|
void pprint(LuaStack &LS0, LuaSlot root, bool indent, std::ostream *os) {
|
||||||
Inspector insp;
|
Inspector insp;
|
||||||
LuaStack LS(LS0.state(), insp.ids);
|
LuaStack LS(LS0.state(), insp.ids);
|
||||||
findtables(LS, root, insp.ids);
|
findtables(LS, root, insp.ids);
|
||||||
|
|||||||
@@ -19,10 +19,8 @@
|
|||||||
#ifndef PPRINT_HPP
|
#ifndef PPRINT_HPP
|
||||||
#define PPRINT_HPP
|
#define PPRINT_HPP
|
||||||
|
|
||||||
#include "wrap-ostream.hpp"
|
|
||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
// Atomic print to a stream.
|
// Atomic print to a stream.
|
||||||
//
|
//
|
||||||
@@ -30,10 +28,10 @@
|
|||||||
// it just prints "<table>". This routine is the heart of the lua
|
// it just prints "<table>". This routine is the heart of the lua
|
||||||
// primitives 'print' and 'tostring'.
|
// primitives 'print' and 'tostring'.
|
||||||
//
|
//
|
||||||
void atomic_print(LuaStack &LS, LuaSlot val, bool quote, eng::ostream *os);
|
void atomic_print(LuaStack &LS, LuaSlot val, bool quote, std::ostream *os);
|
||||||
|
|
||||||
// Pretty print to a stream.
|
// Pretty print to a stream.
|
||||||
//
|
//
|
||||||
void pprint(LuaStack &LS, LuaSlot val, bool indent, eng::ostream *os);
|
void pprint(LuaStack &LS, LuaSlot val, bool indent, std::ostream *os);
|
||||||
|
|
||||||
#endif // PPRINT_HPP
|
#endif // PPRINT_HPP
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "wrap-algorithm.hpp"
|
|
||||||
#include "wrap-sstream.hpp"
|
#include "wrap-sstream.hpp"
|
||||||
|
|
||||||
#include "printbuffer.hpp"
|
#include "printbuffer.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
struct PrintBufferCore {
|
struct PrintBufferCore : public eng::opnew {
|
||||||
// The most recent lines printed.
|
// The most recent lines printed.
|
||||||
eng::deque<eng::string> lines_;
|
eng::deque<eng::string> lines_;
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ void PrintBuffer::patch(StreamBuffer *sb, DebugCollector *dbc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PrintChanneler::channel(const PrintBuffer *printbuffer, eng::ostream &ostream) {
|
bool PrintChanneler::channel(const PrintBuffer *printbuffer, std::ostream &ostream) {
|
||||||
if (printbuffer == nullptr) return false;
|
if (printbuffer == nullptr) return false;
|
||||||
if (printbuffer->first_line() > line_) {
|
if (printbuffer->first_line() > line_) {
|
||||||
line_ = printbuffer->first_line();
|
line_ = printbuffer->first_line();
|
||||||
|
|||||||
@@ -79,18 +79,17 @@
|
|||||||
|
|
||||||
#include "wrap-deque.hpp"
|
#include "wrap-deque.hpp"
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-memory.hpp"
|
#include <ostream>
|
||||||
#include "wrap-ostream.hpp"
|
|
||||||
|
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "invocation.hpp"
|
#include "invocation.hpp"
|
||||||
#include "debugcollector.hpp"
|
#include "debugcollector.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
struct PrintBufferCore;
|
struct PrintBufferCore;
|
||||||
|
|
||||||
class PrintBuffer {
|
class PrintBuffer : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
PrintBufferCore *core_;
|
PrintBufferCore *core_;
|
||||||
|
|
||||||
@@ -139,7 +138,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PrintChanneler {
|
class PrintChanneler : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
int64_t line_;
|
int64_t line_;
|
||||||
public:
|
public:
|
||||||
@@ -151,7 +150,7 @@ public:
|
|||||||
// Copy any new lines from the printbuffer to the stdostream.
|
// Copy any new lines from the printbuffer to the stdostream.
|
||||||
// Update the current line number. Return true if the printbuffer
|
// Update the current line number. Return true if the printbuffer
|
||||||
// contains any lines that have already been channeled.
|
// contains any lines that have already been channeled.
|
||||||
bool channel(const PrintBuffer *pb, eng::ostream &ostream);
|
bool channel(const PrintBuffer *pb, std::ostream &ostream);
|
||||||
|
|
||||||
// Generate an invocation that removes unnecessary lines from the
|
// Generate an invocation that removes unnecessary lines from the
|
||||||
// printbuffer.
|
// printbuffer.
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
|
|
||||||
#include "wrap-sstream.hpp"
|
#include "wrap-sstream.hpp"
|
||||||
#include "wrap-ostream.hpp"
|
|
||||||
|
|
||||||
#include "sched.hpp"
|
#include "sched.hpp"
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
bool SchedEntry::operator < (const SchedEntry &other) const {
|
bool SchedEntry::operator < (const SchedEntry &other) const {
|
||||||
if (clock_ < other.clock_) return true;
|
if (clock_ < other.clock_) return true;
|
||||||
if (clock_ > other.clock_) return false;
|
if (clock_ > other.clock_) return false;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
class SchedEntry {
|
class SchedEntry : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
friend class Schedule;
|
friend class Schedule;
|
||||||
int64_t clock_;
|
int64_t clock_;
|
||||||
@@ -30,7 +30,7 @@ public:
|
|||||||
eng::string debug_string() const;
|
eng::string debug_string() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Schedule {
|
class Schedule : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
eng::set<SchedEntry> schedule_;
|
eng::set<SchedEntry> schedule_;
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
#include "wrap-map.hpp"
|
#include "wrap-map.hpp"
|
||||||
#include "wrap-set.hpp"
|
#include "wrap-set.hpp"
|
||||||
#include "wrap-algorithm.hpp"
|
|
||||||
#include "wrap-sstream.hpp"
|
#include "wrap-sstream.hpp"
|
||||||
|
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
@@ -13,6 +12,7 @@
|
|||||||
#include "source.hpp"
|
#include "source.hpp"
|
||||||
#include "luasnap.hpp"
|
#include "luasnap.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@@ -54,10 +54,10 @@ LuaDefine(classname, "classtable", "get the class name from a class table") {
|
|||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_reg_name(const LuaFunctionReg *reg, eng::string &classname, eng::string &funcname) {
|
static void get_reg_name(const LuaFunctionReg *reg, std::string_view &classname, std::string_view &funcname) {
|
||||||
eng::string name = reg->get_name();
|
std::string_view name(reg->get_name());
|
||||||
size_t upos = name.find('_');
|
size_t upos = name.find('_');
|
||||||
if (upos == eng::string::npos) {
|
if (upos == std::string_view::npos) {
|
||||||
funcname = name;
|
funcname = name;
|
||||||
classname = "";
|
classname = "";
|
||||||
} else {
|
} else {
|
||||||
@@ -337,11 +337,10 @@ static void source_clear_globals(lua_State *L) {
|
|||||||
static void source_load_cfunctions(lua_State *L) {
|
static void source_load_cfunctions(lua_State *L) {
|
||||||
LuaVar classobj;
|
LuaVar classobj;
|
||||||
LuaStack LS(L, classobj);
|
LuaStack LS(L, classobj);
|
||||||
auto regs = LuaFunctionReg::all();
|
for (auto r = LuaFunctionReg::All; r != nullptr; r=r->next()) {
|
||||||
for (const LuaFunctionReg *r : regs) {
|
|
||||||
lua_CFunction func = r->get_func();
|
lua_CFunction func = r->get_func();
|
||||||
eng::string classname;
|
std::string_view classname;
|
||||||
eng::string funcname;
|
std::string_view funcname;
|
||||||
get_reg_name(r, classname, funcname);
|
get_reg_name(r, classname, funcname);
|
||||||
if (classname.empty()) {
|
if (classname.empty()) {
|
||||||
LS.getglobaltable(classobj);
|
LS.getglobaltable(classobj);
|
||||||
@@ -497,17 +496,17 @@ void SourceDB::deserialize_source(util::LuaSourceVec *sv, StreamBuffer *sb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function should not touch the dlmalloc heap.
|
||||||
void SourceDB::register_lua_builtins() {
|
void SourceDB::register_lua_builtins() {
|
||||||
lua_State *L = luaL_newstate();
|
lua_State *L = LuaStack::newstate(nullptr);
|
||||||
luaL_openlibs(L);
|
luaL_openlibs(L);
|
||||||
LuaVar globals,classtab,func;
|
LuaVar globals,classtab,func;
|
||||||
LuaStack LS(L, globals, classtab, func);
|
LuaStack LS(L, globals, classtab, func);
|
||||||
LS.getglobaltable(globals);
|
LS.getglobaltable(globals);
|
||||||
auto regs = LuaFunctionReg::all();
|
for (auto reg = LuaFunctionReg::All; reg != nullptr; reg=reg->next()) {
|
||||||
for (LuaFunctionReg *reg : regs) {
|
|
||||||
if (reg->get_func() == nullptr) {
|
if (reg->get_func() == nullptr) {
|
||||||
eng::string funcname;
|
std::string_view funcname;
|
||||||
eng::string classname;
|
std::string_view classname;
|
||||||
get_reg_name(reg, classname, funcname);
|
get_reg_name(reg, classname, funcname);
|
||||||
if (classname.empty()) {
|
if (classname.empty()) {
|
||||||
LS.rawget(func, globals, funcname);
|
LS.rawget(func, globals, funcname);
|
||||||
@@ -540,8 +539,8 @@ eng::string SourceDB::function_docs(const LuaStack &LS0, LuaSlot fn) {
|
|||||||
if (reg == nullptr) {
|
if (reg == nullptr) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
eng::string classname;
|
std::string_view classname;
|
||||||
eng::string funcname;
|
std::string_view funcname;
|
||||||
get_reg_name(reg, classname, funcname);
|
get_reg_name(reg, classname, funcname);
|
||||||
eng::ostringstream oss;
|
eng::ostringstream oss;
|
||||||
util::StringVec docs = util::split_docstring(reg->get_docs());
|
util::StringVec docs = util::split_docstring(reg->get_docs());
|
||||||
|
|||||||
@@ -127,7 +127,7 @@
|
|||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "debugcollector.hpp"
|
#include "debugcollector.hpp"
|
||||||
|
|
||||||
class SourceDB {
|
class SourceDB : public eng::nevernew {
|
||||||
private:
|
private:
|
||||||
lua_State *lua_state_;
|
lua_State *lua_state_;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "spookyv2.hpp"
|
#include "spookyv2.hpp"
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ StreamBuffer::StreamBuffer() {
|
|||||||
|
|
||||||
StreamBuffer::StreamBuffer(int64_t size, bool fixed) {
|
StreamBuffer::StreamBuffer(int64_t size, bool fixed) {
|
||||||
assert(size >= 0);
|
assert(size >= 0);
|
||||||
init(fixed, true, (char*)dlmalloc(size), size);
|
init(fixed, true, (char*)eng::malloc(size), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamBuffer::StreamBuffer(const char *s, int64_t size) {
|
StreamBuffer::StreamBuffer(const char *s, int64_t size) {
|
||||||
@@ -40,7 +40,7 @@ StreamBuffer::StreamBuffer(const eng::string &src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StreamBuffer::~StreamBuffer() {
|
StreamBuffer::~StreamBuffer() {
|
||||||
if (owned_ && (buf_lo_ != 0)) dlfree(buf_lo_);
|
if (owned_ && (buf_lo_ != 0)) eng::free(buf_lo_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t StreamBuffer::total_reads() const {
|
int64_t StreamBuffer::total_reads() const {
|
||||||
@@ -87,9 +87,9 @@ void StreamBuffer::make_space_slow(int64_t bytes) {
|
|||||||
} else if (existing_size >= desired_size) {
|
} else if (existing_size >= desired_size) {
|
||||||
if (data_size > 0) memcpy(buf_lo_, read_cursor_, data_size);
|
if (data_size > 0) memcpy(buf_lo_, read_cursor_, data_size);
|
||||||
} else {
|
} else {
|
||||||
char *nbuf = (char *)dlmalloc(desired_size);
|
char *nbuf = (char *)eng::malloc(desired_size);
|
||||||
if (data_size > 0) memcpy(nbuf, read_cursor_, data_size);
|
if (data_size > 0) memcpy(nbuf, read_cursor_, data_size);
|
||||||
if (buf_lo_ != nullptr) dlfree(buf_lo_);
|
if (buf_lo_ != nullptr) eng::free(buf_lo_);
|
||||||
buf_lo_ = nbuf;
|
buf_lo_ = nbuf;
|
||||||
buf_hi_ = nbuf + desired_size;
|
buf_hi_ = nbuf + desired_size;
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ char *StreamBuffer::get_overwrite(int64_t size, int64_t write_count_after) {
|
|||||||
void StreamBuffer::clear() {
|
void StreamBuffer::clear() {
|
||||||
assert(owned_);
|
assert(owned_);
|
||||||
if (!fixed_size_) {
|
if (!fixed_size_) {
|
||||||
if (buf_lo_ != nullptr) dlfree(buf_lo_);
|
if (buf_lo_ != nullptr) eng::free(buf_lo_);
|
||||||
buf_lo_ = 0;
|
buf_lo_ = 0;
|
||||||
buf_hi_ = 0;
|
buf_hi_ = 0;
|
||||||
}
|
}
|
||||||
@@ -490,7 +490,7 @@ void *StreamBuffer::lua_reader_ud(int64_t size) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
class StreamBufferWriter : public std::streambuf {
|
class StreamBufferWriter : public std::streambuf, public eng::opnew {
|
||||||
private:
|
private:
|
||||||
StreamBuffer *target_;
|
StreamBuffer *target_;
|
||||||
public:
|
public:
|
||||||
@@ -504,18 +504,18 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class StreamBufferOStream : public eng::ostream {
|
class StreamBufferOStream : public std::ostream, public eng::opnew {
|
||||||
private:
|
private:
|
||||||
StreamBufferWriter writer_;
|
StreamBufferWriter writer_;
|
||||||
public:
|
public:
|
||||||
StreamBufferOStream(StreamBuffer *t) : eng::ostream(nullptr), writer_(t) {
|
StreamBufferOStream(StreamBuffer *t) : std::ostream(nullptr), writer_(t) {
|
||||||
rdbuf(&writer_);
|
rdbuf(&writer_);
|
||||||
}
|
}
|
||||||
virtual ~StreamBufferOStream() {
|
virtual ~StreamBufferOStream() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
eng::ostream &StreamBuffer::ostream() {
|
std::ostream &StreamBuffer::ostream() {
|
||||||
if (ostream_ == nullptr) {
|
if (ostream_ == nullptr) {
|
||||||
ostream_.reset(new StreamBufferOStream(this));
|
ostream_.reset(new StreamBufferOStream(this));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,15 +214,15 @@
|
|||||||
|
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-sstream.hpp"
|
#include "wrap-sstream.hpp"
|
||||||
#include "wrap-utility.hpp"
|
|
||||||
|
#include <utility>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
class StreamException : public eng::nevernew
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
class StreamException
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual char const *what() const { return "General stream exception"; }
|
virtual char const *what() const { return "General stream exception"; }
|
||||||
@@ -240,7 +240,7 @@ public:
|
|||||||
virtual char const *what() const { return "Stream contained invalid data"; }
|
virtual char const *what() const { return "Stream contained invalid data"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class StreamBuffer {
|
class StreamBuffer : public eng::nevernew {
|
||||||
public:
|
public:
|
||||||
// Construct an empty buffer.
|
// Construct an empty buffer.
|
||||||
StreamBuffer();
|
StreamBuffer();
|
||||||
@@ -404,7 +404,7 @@ public:
|
|||||||
void *lua_reader_ud(int64_t bytes);
|
void *lua_reader_ud(int64_t bytes);
|
||||||
|
|
||||||
// Get an ostream that writes into the StreamBuffer.
|
// Get an ostream that writes into the StreamBuffer.
|
||||||
eng::ostream &ostream();
|
std::ostream &ostream();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Start and end of the allocated block.
|
// Start and end of the allocated block.
|
||||||
@@ -429,7 +429,7 @@ private:
|
|||||||
int64_t lua_reader_size_;
|
int64_t lua_reader_size_;
|
||||||
|
|
||||||
// The ostream. Only allocated on demand.
|
// The ostream. Only allocated on demand.
|
||||||
eng::unique_ptr<eng::ostream> ostream_;
|
std::unique_ptr<std::ostream> ostream_;
|
||||||
|
|
||||||
// Initialize with a new buffer.
|
// Initialize with a new buffer.
|
||||||
void init(bool fixed, bool owned, char *buf, int64_t size);
|
void init(bool fixed, bool owned, char *buf, int64_t size);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-memory.hpp"
|
|
||||||
#include "wrap-algorithm.hpp"
|
|
||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
@@ -10,11 +8,13 @@
|
|||||||
#include "invocation.hpp"
|
#include "invocation.hpp"
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
#include "traceback.hpp"
|
#include "traceback.hpp"
|
||||||
#include "textgame.hpp"
|
|
||||||
#include "luaconsole.hpp"
|
#include "luaconsole.hpp"
|
||||||
#include "pprint.hpp"
|
#include "pprint.hpp"
|
||||||
#include "printbuffer.hpp"
|
#include "printbuffer.hpp"
|
||||||
|
#include "drivenengine.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
@@ -131,3 +131,4 @@ private:
|
|||||||
UniqueDrivenEngine make_TextGame() {
|
UniqueDrivenEngine make_TextGame() {
|
||||||
return UniqueDrivenEngine(new TextGame);
|
return UniqueDrivenEngine(new TextGame);
|
||||||
}
|
}
|
||||||
|
static DrivenEngineReg reg_TextGame("textgame", make_TextGame);
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
|
|
||||||
// We only use a custom allocator on linux (for now)
|
|
||||||
// The allocator we chose is 'dlmalloc' (doug lea's malloc).
|
|
||||||
// It's a good allocator for single-threaded programs.
|
|
||||||
// It needs to be configured by setting a bunch of defines.
|
|
||||||
//
|
|
||||||
#ifdef __linux__
|
|
||||||
|
|
||||||
// We need this to define dlmalloc, not malloc.
|
|
||||||
#define USE_DL_PREFIX 1
|
|
||||||
|
|
||||||
// We don't need mspaces.
|
|
||||||
#define ONLY_MSPACES 0
|
|
||||||
#define MSPACES 0
|
|
||||||
|
|
||||||
// We don't need mallinfo
|
|
||||||
#define NO_MALLINFO 1
|
|
||||||
|
|
||||||
// We don't need dlmalloc_inspect_all
|
|
||||||
#define MALLOC_INSPECT_ALL 0
|
|
||||||
|
|
||||||
// We don't need dlmalloc_stats.
|
|
||||||
#define NO_MALLOC_STATS 1
|
|
||||||
|
|
||||||
// Disable locking. The entire engine is single-threaded.
|
|
||||||
#define USE_LOCKS 0
|
|
||||||
|
|
||||||
// For now, we'll let the allocator use mmap to get memory.
|
|
||||||
// It's not clear if this is going to be deterministic.
|
|
||||||
#define HAVE_MMAP 1
|
|
||||||
|
|
||||||
// One way to force determinism would be to emulate sbrk
|
|
||||||
// using mmap and mremap, always putting the heap at a fixed
|
|
||||||
// address. For now, we're not doing that, we're just
|
|
||||||
// using mmap and relying on that being deterministic (we hope).
|
|
||||||
#define HAVE_MORECORE 0
|
|
||||||
#define MORECORE emulate_sbrk
|
|
||||||
|
|
||||||
// The properties of mmap under linux
|
|
||||||
#define MMAP_CLEARS 1
|
|
||||||
#define HAVE_MREMAP 1
|
|
||||||
|
|
||||||
// Don't generate random seeds, or time-based seeds.
|
|
||||||
#define USE_DEV_RANDOM 0
|
|
||||||
#define LACKS_TIME_H 1
|
|
||||||
|
|
||||||
#include "dlmalloc/dlmalloc.c"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int dlmalloc_hash() {
|
|
||||||
void *blocks[15];
|
|
||||||
int hash = 0;
|
|
||||||
for (int i = 0; i < 15; i++) {
|
|
||||||
void *blk = dlmalloc(1 << i);
|
|
||||||
blocks[i] = blk;
|
|
||||||
hash = (hash * 17) + (int)(intptr_t)(blk);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 15; i++) {
|
|
||||||
dlfree(blocks[i]);
|
|
||||||
}
|
|
||||||
return (hash & 0x7FFFFFFF) | (0x40000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef TWO_MALLOCS_HPP
|
|
||||||
#define TWO_MALLOCS_HPP
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
// dlmalloc is only used on linux.
|
|
||||||
extern "C" {
|
|
||||||
#ifdef __linux__
|
|
||||||
void* dlmalloc(size_t x);
|
|
||||||
void dlfree(void *p);
|
|
||||||
void* dlrealloc(void*, size_t);
|
|
||||||
#else
|
|
||||||
void* dlmalloc(size_t x) { return malloc(x); }
|
|
||||||
void dlfree(void *p) { free(p); }
|
|
||||||
void* dlrealloc(void *p, size_t x) { return realloc(p,x); }
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the current state of the dlmalloc allocator as a 30-bit hash.
|
|
||||||
extern int dlmalloc_hash();
|
|
||||||
|
|
||||||
// EngAllocator: a class meant to be used as an STL Allocator.
|
|
||||||
// Causes objects to be allocated using dlmalloc and dlfree.
|
|
||||||
template <class T>
|
|
||||||
class EngAllocator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
EngAllocator() noexcept {}
|
|
||||||
template <class U> EngAllocator(EngAllocator<U> const&) noexcept {}
|
|
||||||
|
|
||||||
value_type* allocate(std::size_t n)
|
|
||||||
{
|
|
||||||
return static_cast<value_type*>(dlmalloc(n*sizeof(value_type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate(value_type* p, std::size_t) noexcept
|
|
||||||
{
|
|
||||||
dlfree(p);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class U>
|
|
||||||
bool operator==(EngAllocator<T> const&, EngAllocator<U> const&) noexcept
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, class U>
|
|
||||||
bool operator!=(EngAllocator<T> const&, EngAllocator<U> const&) noexcept
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DrvAllocator: a class meant to be used as an STL Allocator.
|
|
||||||
// Causes objects to be allocated using malloc and free.
|
|
||||||
template <class T>
|
|
||||||
class DrvAllocator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
DrvAllocator() noexcept {}
|
|
||||||
template <class U> DrvAllocator(DrvAllocator<U> const&) noexcept {}
|
|
||||||
|
|
||||||
value_type* allocate(std::size_t n)
|
|
||||||
{
|
|
||||||
return static_cast<value_type*>(dlmalloc(n*sizeof(value_type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate(value_type* p, std::size_t) noexcept
|
|
||||||
{
|
|
||||||
dlfree(p);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class U>
|
|
||||||
bool operator==(DrvAllocator<T> const&, DrvAllocator<U> const&) noexcept
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, class U>
|
|
||||||
bool operator!=(DrvAllocator<T> const&, DrvAllocator<U> const&) noexcept
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // TWO_MALLOCS_HPP
|
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-vector.hpp"
|
#include "wrap-vector.hpp"
|
||||||
#include "wrap-algorithm.hpp"
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
@@ -8,7 +9,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <fstream>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ bool is_identifier(const eng::string &str) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void quote_string(const eng::string &s, eng::ostream *os) {
|
void quote_string(const eng::string &s, std::ostream *os) {
|
||||||
bool anysq = false;
|
bool anysq = false;
|
||||||
bool anydq = false;
|
bool anydq = false;
|
||||||
for (char c : s) {
|
for (char c : s) {
|
||||||
@@ -363,22 +363,22 @@ eng::string XYZ::debug_string() const {
|
|||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
eng::ostream &operator<<(eng::ostream &oss, const util::hex64 &v) {
|
std::ostream &operator<<(std::ostream &oss, const util::hex64 &v) {
|
||||||
oss << "0x" << std::setw(16) << std::setfill('0') << std::hex;
|
oss << "0x" << std::setw(16) << std::setfill('0') << std::hex;
|
||||||
return oss;
|
return oss;
|
||||||
}
|
}
|
||||||
|
|
||||||
eng::ostream &operator<<(eng::ostream &oss, const util::hex32 &v) {
|
std::ostream &operator<<(std::ostream &oss, const util::hex32 &v) {
|
||||||
oss << "0x" << std::setw(8) << std::setfill('0') << std::hex;
|
oss << "0x" << std::setw(8) << std::setfill('0') << std::hex;
|
||||||
return oss;
|
return oss;
|
||||||
}
|
}
|
||||||
|
|
||||||
eng::ostream &operator<<(eng::ostream &oss, const util::hex16 &v) {
|
std::ostream &operator<<(std::ostream &oss, const util::hex16 &v) {
|
||||||
oss << "0x" << std::setw(4) << std::setfill('0') << std::hex;
|
oss << "0x" << std::setw(4) << std::setfill('0') << std::hex;
|
||||||
return oss;
|
return oss;
|
||||||
}
|
}
|
||||||
|
|
||||||
eng::ostream &operator<<(eng::ostream &oss, const util::hex8 &v) {
|
std::ostream &operator<<(std::ostream &oss, const util::hex8 &v) {
|
||||||
oss << "0x" << std::setw(2) << std::setfill('0') << std::hex;
|
oss << "0x" << std::setw(2) << std::setfill('0') << std::hex;
|
||||||
return oss;
|
return oss;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
#include "wrap-string.hpp"
|
#include "wrap-string.hpp"
|
||||||
#include "wrap-set.hpp"
|
#include "wrap-set.hpp"
|
||||||
#include "wrap-map.hpp"
|
#include "wrap-map.hpp"
|
||||||
#include "wrap-algorithm.hpp"
|
#include "wrap-vector.hpp"
|
||||||
#include "wrap-sstream.hpp"
|
#include "wrap-sstream.hpp"
|
||||||
#include "wrap-ostream.hpp"
|
#include <ostream>
|
||||||
#include "wrap-memory.hpp"
|
#include <memory>
|
||||||
#include "wrap-utility.hpp"
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
@@ -32,11 +32,11 @@ enum MessageType {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using StringVec = eng::vector<eng::string>;
|
using StringVec = eng::vector<eng::string>;
|
||||||
using StringPair = eng::pair<eng::string, eng::string>;
|
using StringPair = std::pair<eng::string, eng::string>;
|
||||||
using StringSet = eng::set<eng::string>;
|
using StringSet = eng::set<eng::string>;
|
||||||
using LuaSourceVec = eng::vector<StringPair>;
|
using LuaSourceVec = eng::vector<StringPair>;
|
||||||
using LuaSourcePtr = eng::unique_ptr<LuaSourceVec>;
|
using LuaSourcePtr = std::unique_ptr<LuaSourceVec>;
|
||||||
using HashValue = eng::pair<uint64_t, uint64_t>;
|
using HashValue = std::pair<uint64_t, uint64_t>;
|
||||||
using IdVector = eng::vector<int64_t>;
|
using IdVector = eng::vector<int64_t>;
|
||||||
|
|
||||||
// Return seconds elapsed, for profiling purposes.
|
// Return seconds elapsed, for profiling purposes.
|
||||||
@@ -46,7 +46,7 @@ double profiling_clock();
|
|||||||
bool is_identifier(const eng::string &str);
|
bool is_identifier(const eng::string &str);
|
||||||
|
|
||||||
// Output a string to a stream using Lua string escaping and quoting.
|
// Output a string to a stream using Lua string escaping and quoting.
|
||||||
void quote_string(const eng::string &str, eng::ostream *os);
|
void quote_string(const eng::string &str, std::ostream *os);
|
||||||
|
|
||||||
// ID vector quick create.
|
// ID vector quick create.
|
||||||
IdVector id_vector_create(int64_t id1=-1, int64_t id2=-1, int64_t id3=-1, int64_t id4=-1);
|
IdVector id_vector_create(int64_t id1=-1, int64_t id2=-1, int64_t id3=-1, int64_t id4=-1);
|
||||||
@@ -128,8 +128,8 @@ bool is_lua_comment(const eng::string &line);
|
|||||||
|
|
||||||
// Remove nullptrs from a vector of unique pointers.
|
// Remove nullptrs from a vector of unique pointers.
|
||||||
template<class T>
|
template<class T>
|
||||||
void remove_nullptrs(eng::vector<eng::unique_ptr<T>> &vec) {
|
void remove_nullptrs(eng::vector<std::unique_ptr<T>> &vec) {
|
||||||
eng::unique_ptr<T> nullp;
|
std::unique_ptr<T> nullp;
|
||||||
auto iter = std::remove(vec.begin(), vec.end(), nullp);
|
auto iter = std::remove(vec.begin(), vec.end(), nullp);
|
||||||
vec.erase(iter, vec.end());
|
vec.erase(iter, vec.end());
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ struct XYZ {
|
|||||||
eng::string debug_string() const;
|
eng::string debug_string() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// These are formatting directives that can be sent to a eng::ostream.
|
// These are formatting directives that can be sent to a std::ostream.
|
||||||
class hex64 {};
|
class hex64 {};
|
||||||
class hex32 {};
|
class hex32 {};
|
||||||
class hex16 {};
|
class hex16 {};
|
||||||
@@ -158,9 +158,9 @@ public:
|
|||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
eng::ostream &operator<<(eng::ostream &oss, const util::hex64 &v);
|
std::ostream &operator<<(std::ostream &oss, const util::hex64 &v);
|
||||||
eng::ostream &operator<<(eng::ostream &oss, const util::hex32 &v);
|
std::ostream &operator<<(std::ostream &oss, const util::hex32 &v);
|
||||||
eng::ostream &operator<<(eng::ostream &oss, const util::hex16 &v);
|
std::ostream &operator<<(std::ostream &oss, const util::hex16 &v);
|
||||||
eng::ostream &operator<<(eng::ostream &oss, const util::hex8 &v);
|
std::ostream &operator<<(std::ostream &oss, const util::hex8 &v);
|
||||||
|
|
||||||
#endif // UTIL_HPP
|
#endif // UTIL_HPP
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ LuaDefine(tangible_nopredict, "",
|
|||||||
LuaDefine(pprint, "obj1,obj2,...",
|
LuaDefine(pprint, "obj1,obj2,...",
|
||||||
"|Pretty-print object or objects.") {
|
"|Pretty-print object or objects.") {
|
||||||
World *w = World::fetch_global_pointer(L);
|
World *w = World::fetch_global_pointer(L);
|
||||||
eng::ostream *ostream = w->lthread_print_stream();
|
std::ostream *ostream = w->lthread_print_stream();
|
||||||
LuaStack LS(L);
|
LuaStack LS(L);
|
||||||
for (int i = 1; i <= lua_gettop(L); i++) {
|
for (int i = 1; i <= lua_gettop(L); i++) {
|
||||||
LuaSpecial root(i);
|
LuaSpecial root(i);
|
||||||
@@ -327,7 +327,7 @@ LuaDefine(pprint, "obj1,obj2,...",
|
|||||||
LuaDefine(print, "obj1,obj2,...",
|
LuaDefine(print, "obj1,obj2,...",
|
||||||
"|Print object or objects.") {
|
"|Print object or objects.") {
|
||||||
World *w = World::fetch_global_pointer(L);
|
World *w = World::fetch_global_pointer(L);
|
||||||
eng::ostream *ostream = w->lthread_print_stream();
|
std::ostream *ostream = w->lthread_print_stream();
|
||||||
LuaStack LS(L);
|
LuaStack LS(L);
|
||||||
int n = lua_gettop(L);
|
int n = lua_gettop(L);
|
||||||
for (int i = 1; i <= n; i++) {
|
for (int i = 1; i <= n; i++) {
|
||||||
@@ -342,7 +342,7 @@ LuaDefine(print, "obj1,obj2,...",
|
|||||||
LuaDefine(doc, "function",
|
LuaDefine(doc, "function",
|
||||||
"|Print documentation for specified function.") {
|
"|Print documentation for specified function.") {
|
||||||
World *w = World::fetch_global_pointer(L);
|
World *w = World::fetch_global_pointer(L);
|
||||||
eng::ostream *ostream = w->lthread_print_stream();
|
std::ostream *ostream = w->lthread_print_stream();
|
||||||
LuaArg func;
|
LuaArg func;
|
||||||
LuaStack LS(L, func);
|
LuaStack LS(L, func);
|
||||||
eng::string doc = SourceDB::function_docs(LS, func);
|
eng::string doc = SourceDB::function_docs(LS, func);
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ eng::string World::probe_lua(int64_t actor_id, const eng::string &lua) {
|
|||||||
|
|
||||||
// If there's an error message, print it.
|
// If there's an error message, print it.
|
||||||
// Otherwise, pretty-print the results.
|
// Otherwise, pretty-print the results.
|
||||||
eng::ostream *ostream = lthread_print_stream();
|
std::ostream *ostream = lthread_print_stream();
|
||||||
if (status == LUA_OK) {
|
if (status == LUA_OK) {
|
||||||
for (int i = top + 1; i <= lua_gettop(L); i++) {
|
for (int i = top + 1; i <= lua_gettop(L); i++) {
|
||||||
LuaSpecial root(i);
|
LuaSpecial root(i);
|
||||||
@@ -683,7 +683,7 @@ void World::run_scheduled_threads() {
|
|||||||
lua_State *CO = LS.ckthread(thread);
|
lua_State *CO = LS.ckthread(thread);
|
||||||
open_lthread_state(LS.ckinteger(actorid), sched.place_id(), LS.ckboolean(useppool), true);
|
open_lthread_state(LS.ckinteger(actorid), sched.place_id(), LS.ckboolean(useppool), true);
|
||||||
int status = lua_resume(CO, nullptr, LS.ckint(nargs));
|
int status = lua_resume(CO, nullptr, LS.ckint(nargs));
|
||||||
eng::ostream *ostream = lthread_print_stream();
|
std::ostream *ostream = lthread_print_stream();
|
||||||
|
|
||||||
// Three possible outcomes: finished, yielded, or errored.
|
// Three possible outcomes: finished, yielded, or errored.
|
||||||
if (!util::world_type_authoritative(world_type_)) {
|
if (!util::world_type_authoritative(world_type_)) {
|
||||||
@@ -786,7 +786,7 @@ void World::close_lthread_state() {
|
|||||||
clear_lthread_state();
|
clear_lthread_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
eng::ostream *World::lthread_print_stream() const {
|
std::ostream *World::lthread_print_stream() const {
|
||||||
if (lthread_prints_ != nullptr) {
|
if (lthread_prints_ != nullptr) {
|
||||||
return lthread_prints_.get();
|
return lthread_prints_.get();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ eng::string World::paired_tables_debug_string(lua_State *master) const {
|
|||||||
LuaVar mntmap, sntmap, mtab, stab, mtid, stid;
|
LuaVar mntmap, sntmap, mtab, stab, mtid, stid;
|
||||||
LuaStack MLS(master, mntmap, mtab, mtid);
|
LuaStack MLS(master, mntmap, mtab, mtid);
|
||||||
LuaStack SLS(synch, sntmap, stab, stid);
|
LuaStack SLS(synch, sntmap, stab, stid);
|
||||||
eng::vector<eng::pair<eng::string, eng::string>> result;
|
eng::vector<std::pair<eng::string, eng::string>> result;
|
||||||
eng::ostringstream oss;
|
eng::ostringstream oss;
|
||||||
|
|
||||||
// Fetch the numbered tables map.
|
// Fetch the numbered tables map.
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
#define WORLD_HPP
|
#define WORLD_HPP
|
||||||
|
|
||||||
#include "wrap-set.hpp"
|
#include "wrap-set.hpp"
|
||||||
#include "wrap-utility.hpp"
|
|
||||||
#include "wrap-memory.hpp"
|
|
||||||
#include "wrap-unordered-map.hpp"
|
#include "wrap-unordered-map.hpp"
|
||||||
#include "wrap-map.hpp"
|
#include "wrap-map.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "planemap.hpp"
|
#include "planemap.hpp"
|
||||||
#include "idalloc.hpp"
|
#include "idalloc.hpp"
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
|
|
||||||
class World;
|
class World;
|
||||||
|
|
||||||
class Tangible {
|
class Tangible : public eng::opnew {
|
||||||
private:
|
private:
|
||||||
friend class World;
|
friend class World;
|
||||||
|
|
||||||
@@ -87,9 +88,9 @@ public:
|
|||||||
void configure_id_pool_for_actor() { id_player_pool_.set_fifo_capacity(3); id_player_pool_.refill(); }
|
void configure_id_pool_for_actor() { id_player_pool_.set_fifo_capacity(3); id_player_pool_.refill(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
using UniqueTangible = eng::unique_ptr<Tangible>;
|
using UniqueTangible = std::unique_ptr<Tangible>;
|
||||||
|
|
||||||
class World {
|
class World : public eng::opnew {
|
||||||
public:
|
public:
|
||||||
using IdVector = util::IdVector;
|
using IdVector = util::IdVector;
|
||||||
using TanVector = eng::vector<const Tangible*>;
|
using TanVector = eng::vector<const Tangible*>;
|
||||||
@@ -247,7 +248,7 @@ public:
|
|||||||
void open_lthread_state(int64_t actor_id, int64_t place_id, bool ppool, bool prints);
|
void open_lthread_state(int64_t actor_id, int64_t place_id, bool ppool, bool prints);
|
||||||
void close_lthread_state();
|
void close_lthread_state();
|
||||||
|
|
||||||
eng::ostream *lthread_print_stream() const;
|
std::ostream *lthread_print_stream() const;
|
||||||
|
|
||||||
// Allocate a single ID.
|
// Allocate a single ID.
|
||||||
//
|
//
|
||||||
@@ -489,7 +490,7 @@ private:
|
|||||||
int64_t lthread_actor_id_;
|
int64_t lthread_actor_id_;
|
||||||
int64_t lthread_place_id_;
|
int64_t lthread_place_id_;
|
||||||
int64_t lthread_use_ppool_;
|
int64_t lthread_use_ppool_;
|
||||||
eng::unique_ptr<eng::ostringstream> lthread_prints_;
|
std::unique_ptr<eng::ostringstream> lthread_prints_;
|
||||||
|
|
||||||
friend class Tangible;
|
friend class Tangible;
|
||||||
friend int lfn_tangible_animate(lua_State *L);
|
friend int lfn_tangible_animate(lua_State *L);
|
||||||
@@ -502,7 +503,7 @@ private:
|
|||||||
friend int lfn_tangible_scan(lua_State *L);
|
friend int lfn_tangible_scan(lua_State *L);
|
||||||
};
|
};
|
||||||
|
|
||||||
using UniqueWorld = eng::unique_ptr<World>;
|
using UniqueWorld = std::unique_ptr<World>;
|
||||||
|
|
||||||
|
|
||||||
#endif // WORLD_HPP
|
#endif // WORLD_HPP
|
||||||
|
|||||||
@@ -10,13 +10,10 @@ with open(f"wrap-{dash}.hpp", "w") as f:
|
|||||||
print(f"#ifndef WRAP_{ubase}_HPP", file=f)
|
print(f"#ifndef WRAP_{ubase}_HPP", file=f)
|
||||||
print(f"#define WRAP_{ubase}_HPP", file=f)
|
print(f"#define WRAP_{ubase}_HPP", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print('#include "two-mallocs.hpp"', file=f)
|
print('#include "eng-malloc.hpp"', file=f)
|
||||||
print(f"#include <{base}>", file=f)
|
print(f"#include <{base}>", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print("namespace eng {", file=f)
|
print("namespace eng {", file=f)
|
||||||
print("} // namespace eng", file=f)
|
print("} // namespace eng", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print("namespace drv {", file=f)
|
|
||||||
print("} // namespace drv", file=f)
|
|
||||||
print("", file=f)
|
|
||||||
print(f"#endif // WRAP_{ubase}_HPP", file=f)
|
print(f"#endif // WRAP_{ubase}_HPP", file=f)
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
#ifndef WRAP_ALGORITHM_HPP
|
|
||||||
#define WRAP_ALGORITHM_HPP
|
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace eng {
|
|
||||||
} // namespace eng
|
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_ALGORITHM_HPP
|
|
||||||
@@ -1,17 +1,14 @@
|
|||||||
#ifndef WRAP_DEQUE_HPP
|
#ifndef WRAP_DEQUE_HPP
|
||||||
#define WRAP_DEQUE_HPP
|
#define WRAP_DEQUE_HPP
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
namespace eng {
|
namespace eng {
|
||||||
template<class T>
|
template<class T>
|
||||||
using deque = std::deque<T, EngAllocator<T>>;
|
class deque : public std::deque<T, eng::allocator<T>>, public eng::opnew {
|
||||||
|
using std::deque<T, eng::allocator<T>>::deque;
|
||||||
|
};
|
||||||
} // namespace eng
|
} // namespace eng
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class T>
|
|
||||||
using deque = std::deque<T, DrvAllocator<T>>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_DEQUE_HPP
|
#endif // WRAP_DEQUE_HPP
|
||||||
|
|||||||
@@ -1,25 +1,14 @@
|
|||||||
#ifndef WRAP_MAP_HPP
|
#ifndef WRAP_MAP_HPP
|
||||||
#define WRAP_MAP_HPP
|
#define WRAP_MAP_HPP
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace eng {
|
namespace eng {
|
||||||
template<class T>
|
|
||||||
using less = std::less<T>;
|
|
||||||
template<class A, class B>
|
|
||||||
using pair = std::pair<A, B>;
|
|
||||||
template<class K, class V, class C=std::less<K>>
|
template<class K, class V, class C=std::less<K>>
|
||||||
using map = std::map<K, V, C, EngAllocator<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
|
} // namespace eng
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class T>
|
|
||||||
using less = std::less<T>;
|
|
||||||
template<class A, class B>
|
|
||||||
using pair = std::pair<A, B>;
|
|
||||||
template<class K, class V, class C=std::less<K>>
|
|
||||||
using map = std::map<K, V, C, DrvAllocator<std::pair<const K, V>>>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_MAP_HPP
|
#endif // WRAP_MAP_HPP
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef WRAP_MEMORY_HPP
|
|
||||||
#define WRAP_MEMORY_HPP
|
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace eng {
|
|
||||||
template<class T, class D=std::default_delete<T>>
|
|
||||||
using unique_ptr = std::unique_ptr<T, D>;
|
|
||||||
template<class T>
|
|
||||||
using shared_ptr = std::shared_ptr<T>;
|
|
||||||
} // namespace eng
|
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class T, class D=std::default_delete<T>>
|
|
||||||
using unique_ptr = std::unique_ptr<T, D>;
|
|
||||||
template<class T>
|
|
||||||
using shared_ptr = std::shared_ptr<T>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_MEMORY_HPP
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#ifndef WRAP_OSTREAM_HPP
|
|
||||||
#define WRAP_OSTREAM_HPP
|
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace eng {
|
|
||||||
using ostream = std::ostream;
|
|
||||||
} // namespace eng
|
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
using ostream = std::ostream;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_OSTREAM_HPP
|
|
||||||
@@ -1,21 +1,14 @@
|
|||||||
#ifndef WRAP_SET_HPP
|
#ifndef WRAP_SET_HPP
|
||||||
#define WRAP_SET_HPP
|
#define WRAP_SET_HPP
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
namespace eng {
|
namespace eng {
|
||||||
template<class T>
|
|
||||||
using less = std::less<T>;
|
|
||||||
template<class K, class C=std::less<K>>
|
template<class K, class C=std::less<K>>
|
||||||
using set = std::set<K, C, EngAllocator<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
|
} // namespace eng
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class T>
|
|
||||||
using less = std::less<T>;
|
|
||||||
template<class K, class C=std::less<K>>
|
|
||||||
using set = std::set<K, C, DrvAllocator<K>>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_SET_HPP
|
#endif // WRAP_SET_HPP
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
#ifndef WRAP_SSTREAM_HPP
|
#ifndef WRAP_SSTREAM_HPP
|
||||||
#define WRAP_SSTREAM_HPP
|
#define WRAP_SSTREAM_HPP
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
|
#include "wrap-string.hpp"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
namespace eng {
|
namespace eng {
|
||||||
template<class C, class T=std::char_traits<C>>
|
template<class C, class T=std::char_traits<C>>
|
||||||
using basic_ostringstream = std::basic_ostringstream<C, T, EngAllocator<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>;
|
using ostringstream = basic_ostringstream<char>;
|
||||||
} // namespace eng
|
} // namespace eng
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class C, class T=std::char_traits<C>>
|
|
||||||
using basic_ostringstream = std::basic_ostringstream<C, T, DrvAllocator<C>>;
|
|
||||||
using ostringstream = basic_ostringstream<char>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_SSTREAM_HPP
|
#endif // WRAP_SSTREAM_HPP
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
#ifndef WRAP_STRING_HPP
|
#ifndef WRAP_STRING_HPP
|
||||||
#define WRAP_STRING_HPP
|
#define WRAP_STRING_HPP
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace eng {
|
namespace eng {
|
||||||
template<class C, class T=std::char_traits<C>>
|
template<class C, class T=std::char_traits<C>>
|
||||||
using basic_string = std::basic_string<C, T, EngAllocator<C>>;
|
using basic_string = std::basic_string<C, T, eng::allocator<C>>;
|
||||||
using string = basic_string<char>;
|
using string = basic_string<char>;
|
||||||
} // namespace eng
|
} // namespace eng
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class C, class T=std::char_traits<C>>
|
|
||||||
using basic_string = std::basic_string<C, T, DrvAllocator<C>>;
|
|
||||||
using string = basic_string<char>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_STRING_HPP
|
#endif // WRAP_STRING_HPP
|
||||||
|
|||||||
@@ -1,29 +1,14 @@
|
|||||||
#ifndef WRAP_UNORDERED_MAP_HPP
|
#ifndef WRAP_UNORDERED_MAP_HPP
|
||||||
#define WRAP_UNORDERED_MAP_HPP
|
#define WRAP_UNORDERED_MAP_HPP
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace eng {
|
namespace eng {
|
||||||
template<class T>
|
|
||||||
using hash = std::hash<T>;
|
|
||||||
template<class T>
|
|
||||||
using equal_to = std::equal_to<T>;
|
|
||||||
template<class A, class B>
|
|
||||||
using pair = std::pair<A, B>;
|
|
||||||
template<class K, class V, class H=std::hash<K>, class E=std::equal_to<K>>
|
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, EngAllocator<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
|
} // namespace eng
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class T>
|
|
||||||
using hash = std::hash<T>;
|
|
||||||
template<class T>
|
|
||||||
using equal_to = std::equal_to<T>;
|
|
||||||
template<class A, class B>
|
|
||||||
using pair = std::pair<A, B>;
|
|
||||||
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, DrvAllocator<std::pair<const K, V>>>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_UNORDERED_MAP_HPP
|
#endif // WRAP_UNORDERED_MAP_HPP
|
||||||
|
|||||||
@@ -1,25 +1,14 @@
|
|||||||
#ifndef WRAP_UNORDERED_SET_HPP
|
#ifndef WRAP_UNORDERED_SET_HPP
|
||||||
#define WRAP_UNORDERED_SET_HPP
|
#define WRAP_UNORDERED_SET_HPP
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace eng {
|
namespace eng {
|
||||||
template<class T>
|
|
||||||
using hash = std::hash<T>;
|
|
||||||
template<class T>
|
|
||||||
using equal_to = std::equal_to<T>;
|
|
||||||
template<class K, class H=std::hash<K>, class E=std::equal_to<K>>
|
template<class K, class H=std::hash<K>, class E=std::equal_to<K>>
|
||||||
using unordered_set = std::unordered_set<K, H, E, EngAllocator<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
|
} // namespace eng
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class T>
|
|
||||||
using hash = std::hash<T>;
|
|
||||||
template<class T>
|
|
||||||
using equal_to = std::equal_to<T>;
|
|
||||||
template<class K, class H=std::hash<K>, class E=std::equal_to<K>>
|
|
||||||
using unordered_set = std::unordered_set<K, H, E, DrvAllocator<K>>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_UNORDERED_SET_HPP
|
#endif // WRAP_UNORDERED_SET_HPP
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef WRAP_UTILITY_HPP
|
|
||||||
#define WRAP_UTILITY_HPP
|
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace eng {
|
|
||||||
template<class A, class B>
|
|
||||||
using pair = std::pair<A, B>;
|
|
||||||
template< class T1, class T2 >
|
|
||||||
constexpr std::pair<T1,T2> make_pair( T1&& t, T2&& u ) { return std::make_pair(t,u); }
|
|
||||||
} // namespace eng
|
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class A, class B>
|
|
||||||
using pair = std::pair<A, B>;
|
|
||||||
template< class T1, class T2 >
|
|
||||||
constexpr std::pair<T1,T2> make_pair( T1&& t, T2&& u ) { return std::make_pair(t,u); }
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_UTILITY_HPP
|
|
||||||
@@ -1,17 +1,14 @@
|
|||||||
#ifndef WRAP_VECTOR_HPP
|
#ifndef WRAP_VECTOR_HPP
|
||||||
#define WRAP_VECTOR_HPP
|
#define WRAP_VECTOR_HPP
|
||||||
|
|
||||||
#include "two-mallocs.hpp"
|
#include "eng-malloc.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace eng {
|
namespace eng {
|
||||||
template<class T>
|
template<class T>
|
||||||
using vector = std::vector<T, EngAllocator<T>>;
|
class vector : public std::vector<T, eng::allocator<T>>, public eng::opnew {
|
||||||
|
using std::vector<T, eng::allocator<T>>::vector;
|
||||||
|
};
|
||||||
} // namespace eng
|
} // namespace eng
|
||||||
|
|
||||||
namespace drv {
|
|
||||||
template<class T>
|
|
||||||
using vector = std::vector<T, DrvAllocator<T>>;
|
|
||||||
} // namespace drv
|
|
||||||
|
|
||||||
#endif // WRAP_VECTOR_HPP
|
#endif // WRAP_VECTOR_HPP
|
||||||
|
|||||||
@@ -4286,10 +4286,9 @@ static int sys_trim(mstate m, size_t pad) {
|
|||||||
if (HAVE_MMAP &&
|
if (HAVE_MMAP &&
|
||||||
sp->size >= extra &&
|
sp->size >= extra &&
|
||||||
!has_segment_link(m, sp)) { /* can't shrink if pinned */
|
!has_segment_link(m, sp)) { /* can't shrink if pinned */
|
||||||
size_t newsize = sp->size - extra;
|
|
||||||
/* Prefer mremap, fall back to munmap */
|
/* Prefer mremap, fall back to munmap */
|
||||||
if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
|
if ((CALL_MREMAP(sp->base, sp->size, (sp->size - extra), 0) != MFAIL) ||
|
||||||
(CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
|
(CALL_MUNMAP(sp->base + (sp->size - extra), extra) == 0)) {
|
||||||
released = extra;
|
released = extra;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user