diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2010-06-23 21:03:09 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2010-06-23 21:03:09 -0700 |
| commit | d6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch) | |
| tree | b425187e232966063ffc2f0d14c04a55d8f004ef /src/rt/rust_comm.cpp | |
| parent | c01efc669f09508b55eced32d3c88702578a7c3e (diff) | |
| download | rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.gz rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip | |
Populate tree.
Diffstat (limited to 'src/rt/rust_comm.cpp')
| -rw-r--r-- | src/rt/rust_comm.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/rt/rust_comm.cpp b/src/rt/rust_comm.cpp new file mode 100644 index 00000000000..58b9ef4c424 --- /dev/null +++ b/src/rt/rust_comm.cpp @@ -0,0 +1,199 @@ + +#include "rust_internal.h" + +template class ptr_vec<rust_token>; +template class ptr_vec<rust_alarm>; +template class ptr_vec<rust_chan>; + +rust_alarm::rust_alarm(rust_task *receiver) : + receiver(receiver) +{ +} + + +// Circular buffers. + +circ_buf::circ_buf(rust_dom *dom, size_t unit_sz) : + dom(dom), + alloc(INIT_CIRC_BUF_UNITS * unit_sz), + unit_sz(unit_sz), + next(0), + unread(0), + data((uint8_t *)dom->calloc(alloc)) +{ + I(dom, unit_sz); + dom->log(rust_log::MEM|rust_log::COMM, + "new circ_buf(alloc=%d, unread=%d) -> circ_buf=0x%" PRIxPTR, + alloc, unread, this); + I(dom, data); +} + +circ_buf::~circ_buf() +{ + dom->log(rust_log::MEM|rust_log::COMM, + "~circ_buf 0x%" PRIxPTR, + this); + I(dom, data); + // I(dom, unread == 0); + dom->free(data); +} + +void +circ_buf::transfer(void *dst) +{ + size_t i; + uint8_t *d = (uint8_t *)dst; + I(dom, dst); + for (i = 0; i < unread; i += unit_sz) + memcpy(&d[i], &data[next + i % alloc], unit_sz); +} + +void +circ_buf::push(void *src) +{ + size_t i; + void *tmp; + + I(dom, src); + I(dom, unread <= alloc); + + /* Grow if necessary. */ + if (unread == alloc) { + I(dom, alloc <= MAX_CIRC_BUF_SIZE); + tmp = dom->malloc(alloc << 1); + transfer(tmp); + alloc <<= 1; + dom->free(data); + data = (uint8_t *)tmp; + } + + dom->log(rust_log::MEM|rust_log::COMM, + "circ buf push, unread=%d, alloc=%d, unit_sz=%d", + unread, alloc, unit_sz); + + I(dom, unread < alloc); + I(dom, unread + unit_sz <= alloc); + + i = (next + unread) % alloc; + memcpy(&data[i], src, unit_sz); + + dom->log(rust_log::MEM|rust_log::COMM, "pushed data at index %d", i); + unread += unit_sz; +} + +void +circ_buf::shift(void *dst) +{ + size_t i; + void *tmp; + + I(dom, dst); + I(dom, unit_sz > 0); + I(dom, unread >= unit_sz); + I(dom, unread <= alloc); + I(dom, data); + i = next; + memcpy(dst, &data[i], unit_sz); + dom->log(rust_log::MEM|rust_log::COMM, "shifted data from index %d", i); + unread -= unit_sz; + next += unit_sz; + I(dom, next <= alloc); + if (next == alloc) + next = 0; + + /* Shrink if necessary. */ + if (alloc >= INIT_CIRC_BUF_UNITS * unit_sz && + unread <= alloc / 4) { + tmp = dom->malloc(alloc / 2); + transfer(tmp); + alloc >>= 1; + dom->free(data); + data = (uint8_t *)tmp; + } +} + + +// Ports. + +rust_port::rust_port(rust_task *task, size_t unit_sz) : + task(task), + unit_sz(unit_sz), + writers(task->dom), + chans(task->dom) +{ + rust_dom *dom = task->dom; + dom->log(rust_log::MEM|rust_log::COMM, + "new rust_port(task=0x%" PRIxPTR ", unit_sz=%d) -> port=0x%" + PRIxPTR, (uintptr_t)task, unit_sz, (uintptr_t)this); +} + +rust_port::~rust_port() +{ + rust_dom *dom = task->dom; + dom->log(rust_log::COMM|rust_log::MEM, + "~rust_port 0x%" PRIxPTR, + (uintptr_t)this); + while (chans.length() > 0) + chans.pop()->disassociate(); +} + + +// Tokens. + +rust_token::rust_token(rust_chan *chan) : + chan(chan), + idx(0), + submitted(false) +{ +} + +rust_token::~rust_token() +{ +} + +bool +rust_token::pending() const +{ + return submitted; +} + +void +rust_token::submit() +{ + rust_port *port = chan->port; + rust_dom *dom = chan->task->dom; + + I(dom, port); + I(dom, !submitted); + + port->writers.push(this); + submitted = true; +} + +void +rust_token::withdraw() +{ + rust_task *task = chan->task; + rust_port *port = chan->port; + rust_dom *dom = task->dom; + + I(dom, port); + I(dom, submitted); + + if (task->blocked()) + task->wakeup(this); // must be blocked on us (or dead) + port->writers.swapdel(this); + submitted = false; +} + + +// +// Local Variables: +// mode: C++ +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// |
