about summary refs log tree commit diff
path: root/src/rt/rust_comm.cpp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-06-23 21:03:09 -0700
committerGraydon Hoare <graydon@mozilla.com>2010-06-23 21:03:09 -0700
commitd6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch)
treeb425187e232966063ffc2f0d14c04a55d8f004ef /src/rt/rust_comm.cpp
parentc01efc669f09508b55eced32d3c88702578a7c3e (diff)
downloadrust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.gz
rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip
Populate tree.
Diffstat (limited to 'src/rt/rust_comm.cpp')
-rw-r--r--src/rt/rust_comm.cpp199
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:
+//