176 lines
4.2 KiB
C++
176 lines
4.2 KiB
C++
#include "drivenengine.hpp"
|
|
|
|
|
|
Channel::Channel(DrivenEngine *de, int chid, int port, const std::string &target) {
|
|
driven_ = de;
|
|
chid_ = chid;
|
|
sb_in_.reset(new StreamBuffer);
|
|
sb_out_.reset(new StreamBuffer);
|
|
port_ = port;
|
|
closed_ = false;
|
|
target_ = target;
|
|
assert(driven_->channels_[chid_] == nullptr);
|
|
driven_->channels_[chid_] = this;
|
|
}
|
|
|
|
Channel::~Channel() {
|
|
assert(driven_->channels_[chid_] == this);
|
|
driven_->new_closed_.insert(chid_);
|
|
driven_->new_outgoing_.erase(chid_);
|
|
driven_->channels_[chid_] = nullptr;
|
|
}
|
|
|
|
int DrivenEngine::find_unused_chid() {
|
|
// Note: channel ID zero is special, it is never reused.
|
|
for (int i = 0; i < MAX_CHAN; i++) {
|
|
int id = next_unused_chid_++;
|
|
if (next_unused_chid_ == MAX_CHAN) next_unused_chid_ = 1;
|
|
if (channels_[id] == nullptr) return id;
|
|
}
|
|
assert(false);
|
|
return 0;
|
|
}
|
|
|
|
Channel *DrivenEngine::get_chid(int chid) {
|
|
assert(unsigned(chid) < MAX_CHAN);
|
|
assert(channels_[chid] != nullptr);
|
|
return channels_[chid];
|
|
}
|
|
|
|
double DrivenEngine::get_clock() {
|
|
return clock_;
|
|
}
|
|
|
|
std::unique_ptr<Channel> DrivenEngine::new_outgoing_channel(const std::string &target) {
|
|
int chid = find_unused_chid();
|
|
new_outgoing_.insert(chid);
|
|
return std::unique_ptr<Channel>(new Channel(this, chid, 0, target));
|
|
}
|
|
|
|
std::unique_ptr<Channel> DrivenEngine::new_incoming_channel() {
|
|
if (accepted_channels_.empty()) {
|
|
return nullptr;
|
|
} else {
|
|
std::unique_ptr<Channel> result = std::move(accepted_channels_.back());
|
|
accepted_channels_.pop_back();
|
|
return std::move(result);
|
|
}
|
|
}
|
|
|
|
Channel *DrivenEngine::get_stdio_channel() {
|
|
return stdio_channel_.get();
|
|
}
|
|
|
|
util::LuaSourcePtr DrivenEngine::get_lua_source() {
|
|
return std::move(lua_source_);
|
|
}
|
|
|
|
void DrivenEngine::rescan_lua_source() {
|
|
rescan_lua_source_ = true;
|
|
}
|
|
|
|
void DrivenEngine::stop_driver() {
|
|
stop_driver_ = true;
|
|
}
|
|
|
|
void DrivenEngine::drv_get_new_closed(std::set<int> &channels) {
|
|
channels = std::move(new_closed_);
|
|
new_closed_.clear();
|
|
}
|
|
|
|
void DrivenEngine::drv_get_new_outgoing(std::set<int> &channels) {
|
|
channels = std::move(new_outgoing_);
|
|
new_outgoing_.clear();
|
|
}
|
|
|
|
const std::string &DrivenEngine::drv_get_target(int chid) {
|
|
return get_chid(chid)->target_;
|
|
}
|
|
|
|
bool DrivenEngine::drv_outgoing_empty(int chid) {
|
|
return get_chid(chid)->sb_out_->empty();
|
|
}
|
|
|
|
void DrivenEngine::drv_peek_outgoing(int chid, int *nbytes, const char **bytes) {
|
|
Channel *ch = get_chid(chid);
|
|
*nbytes = ch->sb_out_->fill();
|
|
*bytes = ch->sb_out_->data();
|
|
}
|
|
|
|
void DrivenEngine::drv_sent_outgoing(int chid, int nbytes) {
|
|
get_chid(chid)->sb_out_->read_bytes(nbytes);
|
|
}
|
|
|
|
void DrivenEngine::drv_recv_incoming(int chid, int nbytes, const char *bytes) {
|
|
if (nbytes > 0) {
|
|
get_chid(chid)->sb_in_->write_bytes(bytes, nbytes);
|
|
}
|
|
}
|
|
|
|
void DrivenEngine::drv_notify_close(int chid) {
|
|
get_chid(chid)->closed_ = true;
|
|
}
|
|
|
|
int DrivenEngine::drv_notify_accept(int port) {
|
|
int chid = find_unused_chid();
|
|
accepted_channels_.emplace_back(new Channel(this, chid, port, ""));
|
|
return chid;
|
|
}
|
|
|
|
void DrivenEngine::drv_set_clock(double t) {
|
|
clock_ = t;
|
|
}
|
|
|
|
void DrivenEngine::drv_set_lua_source(util::LuaSourcePtr source) {
|
|
lua_source_ = std::move(source);
|
|
rescan_lua_source_ = false;
|
|
}
|
|
|
|
void DrivenEngine::drv_invoke_event_init() {
|
|
event_init();
|
|
}
|
|
|
|
void DrivenEngine::drv_invoke_event_update() {
|
|
event_update();
|
|
}
|
|
|
|
bool DrivenEngine::drv_get_rescan_lua_source() {
|
|
return rescan_lua_source_;
|
|
}
|
|
|
|
bool DrivenEngine::drv_get_stop_driver() {
|
|
return stop_driver_;
|
|
}
|
|
|
|
DrivenEngine::DrivenEngine() {
|
|
for (int i = 0; i < MAX_CHAN; i++) {
|
|
channels_[i] = nullptr;
|
|
}
|
|
next_unused_chid_ = 1;
|
|
stdio_channel_.reset(new Channel(this, 0, 0, ""));
|
|
rescan_lua_source_ = true;
|
|
clock_ = 0.0;
|
|
stop_driver_ = false;
|
|
}
|
|
|
|
DrivenEngine::~DrivenEngine() {
|
|
// Delete the channels that we own.
|
|
stdio_channel_.reset();
|
|
accepted_channels_.clear();
|
|
// At this point, all channels should be gone.
|
|
for (int i = 0; i < MAX_CHAN; i++) {
|
|
assert(channels_[i] == nullptr);
|
|
}
|
|
}
|
|
|
|
static DrivenEngine *engine_;
|
|
|
|
void DrivenEngine::set(DrivenEngine *de) {
|
|
engine_ = de;
|
|
}
|
|
|
|
DrivenEngine *DrivenEngine::get() {
|
|
return engine_;
|
|
}
|
|
|