X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fhdsd%2Fscd%2Fscd_chan_wrapper.cpp;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fhdsd%2Fscd%2Fscd_chan_wrapper.cpp;h=262924042027d74b8112a8a73823133d460c2e35;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/hdsd/scd/scd_chan_wrapper.cpp b/dol/src/dol/visitor/hdsd/scd/scd_chan_wrapper.cpp new file mode 100644 index 0000000..2629240 --- /dev/null +++ b/dol/src/dol/visitor/hdsd/scd/scd_chan_wrapper.cpp @@ -0,0 +1,201 @@ +#include "scd_chan_wrapper.h" + +#include +#include + +#include "scd_logging.h" + + +scd_chan_wrapper::scd_chan_wrapper(scd_simulator& sim, const std::string& name, + sc_prim_channel& chan): + _sim(sim), _name(name), _is_initialized(false), + _is_writing(false), _is_reading(false) +{ + try + { + _chan_in = &dynamic_cast(chan); + } catch (std::bad_cast e) + { + _chan_in = NULL; + } + + try + { + _chan_out = &dynamic_cast(chan); + } catch (std::bad_cast e) + { + _chan_out = NULL; + } + + if (_chan_in == NULL && _chan_out == NULL) + scd_warn("channel \"" + _name + "\" is not a remote channel"); +} + + +scd_chan_wrapper::~scd_chan_wrapper() +{ + if ( _is_initialized ) + { + _sim.get_poller().remove_handler(*this); + _socket->close(); + delete _socket; + } +} + + +bool scd_chan_wrapper::is_initialized() const { return _is_initialized; } + + +const std::string& scd_chan_wrapper::get_name() const { return _name; } + + +void scd_chan_wrapper::connect(scd_socket* sock) +{ + assert(!_is_initialized); + + _socket = sock; + _is_initialized = true; + + sock_ev flags = SOCK_EV_CLOSE; + if (_chan_in != NULL) + { + flags |= SOCK_EV_READ; + _is_reading = true; + } + _sim.get_poller().register_handler(*this, flags); + +} // connect() + + +void scd_chan_wrapper::process() +{ + // check if channel has data to send + if (_chan_out != NULL && _is_initialized ) + { + if (!_is_writing && _socket->is_valid() && _chan_out->available() > 0 ) + { + // register write event + sock_ev events; + _sim.get_poller().get_ev(*this, events); + events |= SOCK_EV_WRITE; + _sim.get_poller().set_ev( *this, events ); + _is_writing = true; + } + } + + // check if channel has data to read + if (_chan_in != NULL && _is_initialized ) + { + if (!_is_reading && _socket->is_valid() && _chan_in->free() > 0 ) + { + // register read event + sock_ev events; + _sim.get_poller().get_ev(*this, events); + events |= SOCK_EV_READ; + _sim.get_poller().set_ev( *this, events ); + _is_reading = true; + } + } + +} // process() + + +void scd_chan_wrapper::close() +{ + if (_is_initialized) + _socket->close(); + +} // close() + + +void scd_chan_wrapper::handle_sock_ev(sock_ev events) +{ + if (events & SOCK_EV_CLOSE) + { + scd_debug("channel \"" + _name + "\" closed connection"); + _sim.get_poller().set_ev(*this, 0); + _sim.get_cont_man().set_fail(); + close(); + return; + } // end close event + + if (events & SOCK_EV_READ) + { + _read_event(); + } + + if (events & SOCK_EV_WRITE) + { + _write_event(); + } + +} // handle_sock_ev() + + +const scd_socket& scd_chan_wrapper::get_sock() { return *_socket; } + + +void scd_chan_wrapper::_read_event() +{ + size_t free = _chan_in->free(); + + /* receive portions as long as they can be received */ + size_t recv = 0xFF; //dummy + while ( free != 0 && recv != 0) + { + free = ( free < SCD_CHAN_BUFLEN ) ? free : SCD_CHAN_BUFLEN ; + recv = _socket->recv(_buf, free); + if (recv != 0) + _chan_in->receive(_buf, recv); + free = _chan_in->free(); + } + + if (free == 0) + { + sock_ev events; + _sim.get_poller().get_ev(*this, events); + events &= ~SOCK_EV_READ; + _sim.get_poller().set_ev(*this, events ); + _is_reading = false; + return; + } + + if (!_socket->is_valid()) + { + scd_debug("channel \"" + _name + "\" closed connection"); + _sim.get_poller().set_ev(*this, 0); + _sim.get_cont_man().set_fail(); + return; + } + +} // end _read_event() + + +void scd_chan_wrapper::_write_event() +{ + /* send portions as long as they can be sent */ + size_t sent = 0xFF; //dummy + while ( sent ) + { + sent = _socket->send( _chan_out->send(), _chan_out->available() ); + if (sent != 0) + _chan_out->remove(sent); + } + + if (_chan_out->available() == 0) + { + sock_ev events; + _sim.get_poller().get_ev(*this, events); + events &= ~SOCK_EV_WRITE; + _sim.get_poller().set_ev(*this, events ); + _is_writing = false; + return; + } + + if (!_socket->is_valid()) + { + scd_debug("channel \"" + _name + "\" closed connection"); + _sim.get_poller().set_ev(*this, 0); + _sim.get_cont_man().set_fail(); + } +}