dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_chan_wrapper.cpp
1 #include "scd_chan_wrapper.h"
2
3 #include <cassert>
4 #include <cstdio>
5
6 #include "scd_logging.h"
7
8
9 scd_chan_wrapper::scd_chan_wrapper(scd_simulator& sim, const std::string& name,
10         sc_prim_channel& chan):
11     _sim(sim), _name(name), _is_initialized(false),
12     _is_writing(false), _is_reading(false)
13 {
14     try
15     {
16         _chan_in = &dynamic_cast<scd_rem_chan_in_if&>(chan);
17     } catch (std::bad_cast e)
18     {
19         _chan_in = NULL;
20     }
21
22     try
23     {
24         _chan_out = &dynamic_cast<scd_rem_chan_out_if&>(chan);
25     } catch (std::bad_cast e)
26     {
27         _chan_out = NULL;
28     }
29
30     if (_chan_in == NULL && _chan_out == NULL)
31         scd_warn("channel \"" + _name + "\" is not a remote channel");
32 }
33
34
35 scd_chan_wrapper::~scd_chan_wrapper()
36 {
37     if ( _is_initialized )
38     {
39         _sim.get_poller().remove_handler(*this);
40         _socket->close();
41         delete _socket;
42     }
43 }
44
45
46 bool scd_chan_wrapper::is_initialized() const { return _is_initialized; }
47
48
49 const std::string& scd_chan_wrapper::get_name() const { return _name; }
50
51
52 void scd_chan_wrapper::connect(scd_socket* sock)
53 {
54     assert(!_is_initialized);
55
56     _socket = sock;
57     _is_initialized = true;
58
59     sock_ev flags = SOCK_EV_CLOSE;
60     if (_chan_in != NULL)
61     {
62         flags |= SOCK_EV_READ;
63         _is_reading = true;
64     }
65     _sim.get_poller().register_handler(*this, flags);
66
67 } // connect()
68
69
70 void scd_chan_wrapper::process()
71 {
72     // check if channel has data to send
73     if (_chan_out != NULL && _is_initialized )
74     {
75         if (!_is_writing && _socket->is_valid() && _chan_out->available() > 0 )
76         {
77             // register write event
78             sock_ev events;
79             _sim.get_poller().get_ev(*this, events);
80             events |= SOCK_EV_WRITE;
81             _sim.get_poller().set_ev( *this, events );
82             _is_writing = true;
83         }
84     }
85
86     // check if channel has data to read
87     if (_chan_in != NULL && _is_initialized )
88     {
89         if (!_is_reading && _socket->is_valid() && _chan_in->free() > 0 )
90         {
91             // register read event
92             sock_ev events;
93             _sim.get_poller().get_ev(*this, events);
94             events |= SOCK_EV_READ;
95             _sim.get_poller().set_ev( *this, events );
96             _is_reading = true;
97         }
98     }
99
100 } // process()
101
102
103 void scd_chan_wrapper::close()
104 {
105     if (_is_initialized)
106         _socket->close();
107
108 } // close()
109
110
111 void scd_chan_wrapper::handle_sock_ev(sock_ev events)
112 {
113     if (events & SOCK_EV_CLOSE)
114     {
115         scd_debug("channel \"" + _name + "\" closed connection");
116         _sim.get_poller().set_ev(*this, 0);
117         _sim.get_cont_man().set_fail();
118         close();
119         return;
120     } // end close event
121
122     if (events & SOCK_EV_READ)
123     {
124         _read_event();
125     }
126
127     if (events & SOCK_EV_WRITE)
128     {
129         _write_event();
130     }
131
132 } // handle_sock_ev()
133
134
135 const scd_socket& scd_chan_wrapper::get_sock() { return *_socket; }
136
137
138 void scd_chan_wrapper::_read_event()
139 {
140     size_t free = _chan_in->free();
141
142     /* receive portions as long as they can be received */
143     size_t recv = 0xFF; //dummy
144     while ( free != 0 && recv != 0)
145     {
146         free = ( free < SCD_CHAN_BUFLEN ) ? free : SCD_CHAN_BUFLEN ;
147         recv = _socket->recv(_buf, free);
148         if (recv != 0)
149             _chan_in->receive(_buf, recv);
150         free = _chan_in->free();
151     }
152
153     if (free == 0)
154     {
155         sock_ev events;
156         _sim.get_poller().get_ev(*this, events);
157         events &= ~SOCK_EV_READ;
158         _sim.get_poller().set_ev(*this, events );
159         _is_reading = false;
160         return;
161     }
162
163     if (!_socket->is_valid())
164     {
165         scd_debug("channel \"" + _name + "\" closed connection");
166         _sim.get_poller().set_ev(*this, 0);
167         _sim.get_cont_man().set_fail();
168         return;
169     }
170
171 } // end _read_event()
172
173
174 void scd_chan_wrapper::_write_event()
175 {
176     /* send portions as long as they can be sent */
177     size_t sent = 0xFF; //dummy
178     while ( sent )
179     {
180         sent = _socket->send( _chan_out->send(), _chan_out->available() );
181         if (sent != 0)
182             _chan_out->remove(sent);
183     }
184
185     if (_chan_out->available() == 0)
186     {
187         sock_ev events;
188         _sim.get_poller().get_ev(*this, events);
189         events &= ~SOCK_EV_WRITE;
190         _sim.get_poller().set_ev(*this, events );
191         _is_writing = false;
192         return;
193     }
194
195     if (!_socket->is_valid())
196     {
197         scd_debug("channel \"" + _name + "\" closed connection");
198         _sim.get_poller().set_ev(*this, 0);
199         _sim.get_cont_man().set_fail();
200     }
201 }