From e4c291530e4cc160eca30811e17d614f236147a4 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 7 Jun 2012 12:18:34 -0700 Subject: [PATCH] Basic functionality for new ports and chans The first benchmark shows about twice the throughput of the old system. --- src/libcore/arc.rs | 17 +++++--- src/libcore/core.rc | 3 +- src/libcore/dvec.rs | 50 +++++++++++++++--------- src/libcore/newcomm.rs | 88 ++++++++++++++++++++++++++++++++++++++++++ src/libcore/vec.rs | 24 ++++++++---- 5 files changed, 149 insertions(+), 33 deletions(-) create mode 100644 src/libcore/newcomm.rs diff --git a/src/libcore/arc.rs b/src/libcore/arc.rs index a6baae0d082..2fa656f3eeb 100644 --- a/src/libcore/arc.rs +++ b/src/libcore/arc.rs @@ -28,6 +28,7 @@ resource arc_destruct(data: *libc::c_void) { unsafe { let data: ~arc_data = unsafe::reinterpret_cast(data); let new_count = rustrt::rust_atomic_decrement(&mut data.count); + let data_ptr : *() = unsafe::reinterpret_cast(data); assert new_count >= 0; if new_count == 0 { // drop glue takes over. @@ -68,17 +69,19 @@ allowing them to share the underlying data."] fn clone(rc: &arc) -> arc { unsafe { let ptr: ~arc_data = unsafe::reinterpret_cast(**rc); - rustrt::rust_atomic_increment(&mut ptr.count); + let new_count = rustrt::rust_atomic_increment(&mut ptr.count); + let data_ptr : *() = unsafe::reinterpret_cast(ptr); + assert new_count >= 2; unsafe::forget(ptr); } arc_destruct(**rc) } // An arc over mutable data that is protected by a lock. -type ex_data = {lock: sys::lock_and_signal, data: T}; -type exclusive = arc_destruct>; +type ex_data = {lock: sys::lock_and_signal, data: T}; +type exclusive = arc_destruct>; -fn exclusive(-data: T) -> exclusive { +fn exclusive(-data: T) -> exclusive { let data = ~{mut count: 1, data: {lock: sys::create_lock(), data: data}}; unsafe { @@ -88,12 +91,14 @@ fn exclusive(-data: T) -> exclusive { } } -impl methods for exclusive { +impl methods for exclusive { fn clone() -> exclusive { unsafe { // this makes me nervous... let ptr: ~arc_data> = unsafe::reinterpret_cast(*self); - rustrt::rust_atomic_increment(&mut ptr.count); + let new_count = rustrt::rust_atomic_increment(&mut ptr.count); + let data_ptr : *() = unsafe::reinterpret_cast(ptr); + assert new_count > 1; unsafe::forget(ptr); } arc_destruct(*self) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 913832a7f07..3185d8e30c0 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -39,7 +39,7 @@ export float, f32, f64; export box, char, str, ptr, vec, bool; export either, option, result, iter; export libc, os, io, run, rand, sys, unsafe, logging; -export arc, comm, task, future; +export arc, newcomm, comm, task, future; export extfmt; export tuple; export to_str; @@ -176,6 +176,7 @@ mod dvec_iter { // Concurrency mod arc; +mod newcomm; mod comm; mod task; mod future; diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index d30179fd881..85d61d3f606 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -132,14 +132,6 @@ impl extensions for dvec { self.check_not_borrowed(); self.data <- w; } -} - -impl extensions for dvec { - #[doc = "Append a single item to the end of the list"] - fn push(t: A) { - self.check_not_borrowed(); - vec::push(self.data, t); - } #[doc = "Remove and return the last element"] fn pop() -> A { @@ -151,6 +143,38 @@ impl extensions for dvec { } } + #[doc = "Insert a single item at the front of the list"] + fn unshift(-t: A) { + unsafe { + let mut data = unsafe::reinterpret_cast(null::<()>()); + data <-> self.data; + let data_ptr: *() = unsafe::reinterpret_cast(data); + if data_ptr.is_null() { fail "Recursive use of dvec"; } + log(error, "a"); + self.data <- [mut t] + data; + log(error, "b"); + } + } + + #[doc = "Append a single item to the end of the list"] + fn push(+t: A) { + self.check_not_borrowed(); + vec::push(self.data, t); + } + + + #[doc = "Remove and return the first element"] + fn shift() -> A { + self.borrow { |v| + let mut v = vec::from_mut(v); + let result = vec::shift(v); + self.return(vec::to_mut(v)); + result + } + } +} + +impl extensions for dvec { #[doc = " Append all elements of a vector to the end of the list @@ -213,16 +237,6 @@ impl extensions for dvec { } } - #[doc = "Remove and return the first element"] - fn shift() -> A { - self.borrow { |v| - let mut v = vec::from_mut(v); - let result = vec::shift(v); - self.return(vec::to_mut(v)); - result - } - } - #[doc = "Copy out an individual element"] #[inline(always)] fn [](idx: uint) -> A { diff --git a/src/libcore/newcomm.rs b/src/libcore/newcomm.rs new file mode 100644 index 00000000000..6934dba84cd --- /dev/null +++ b/src/libcore/newcomm.rs @@ -0,0 +1,88 @@ +#[doc="A new implementation of communication. + +This should be implementing almost entirely in Rust, and hopefully +avoid needing a single global lock."] + +import arc::methods; +import dvec::dvec; +import dvec::{extensions}; + +export port; +export chan; +export send, recv; +export methods; + +type raw_port = arc::exclusive>; + +enum port { + port_(raw_port) +} +enum chan { + chan_(raw_port) +} + +fn port() -> port { + port_(arc::exclusive(dvec())) +} + +fn chan(p: port) -> chan { + chan_((*p).clone()) +} + +fn send(c: chan, -x: T) { + let mut x <- some(x); + (*c).with {|cond, data| + let mut xx = none; + xx <-> x; + alt xx { + some(y) { + let mut x <- y; + (*data).push(x); + cond.signal(); + } + none { fail } + }; + } +} + +fn recv(p: port) -> T { + (*p).with {|cond, data| + if (*data).len() == 0u { + cond.wait(); + } + assert (*data).len() > 0u; + (*data).shift() + } +} + +impl methods for chan { + fn send(-x: T) { + send(self, x) + } + + fn clone() -> chan { + chan_((*self).clone()) + } +} + +impl methods for port { + fn recv() -> T { + recv(self) + } + + fn chan() -> chan { + chan(self) + } +} + +#[cfg(test)] +mod test { + #[test] + fn newport_simple() { + let p = port(); + let c = chan(p); + + c.send(42); + assert p.recv() == 42; + } +} diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index c029e9f2448..689c641e061 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -371,17 +371,25 @@ fn rsplitn(v: [T]/&, n: uint, f: fn(T) -> bool) -> [[T]] { // Mutators #[doc = "Removes the first element from a vector and return it"] -fn shift(&v: [T]) -> T { +fn shift(&v: [T]) -> T { let ln = len::(v); assert (ln > 0u); - let e = v[0]; - v = slice::(v, 1u, ln); - ret e; -} -#[doc = "Prepend an element to a vector"] -fn unshift(&v: [T], +t: T) { - v = [t] + v; + let mut vv = []; + v <-> vv; + + unsafe { + let vv = unsafe::to_ptr(vv); + let r <- *vv; + + for uint::range(1u, ln) {|i| + // FIXME: this isn't legal, per se... + let r <- *ptr::offset(vv, i); + push(v, r); + } + + r + } } #[doc = "Remove the last element from a vector and return it"]