Fix nu_select! macro for borrowck

This commit is contained in:
Andrew Poelstra 2014-07-26 19:36:38 -07:00
parent 322c937c3c
commit 6f7e73d6b4
2 changed files with 31 additions and 37 deletions

View File

@ -341,7 +341,7 @@ impl<'tree> Iterator<&'tree Block> for RevStaleBlockIter<'tree> {
/// This function emulates the GetCompact(SetCompact(n)) in the satoshi code, /// This function emulates the GetCompact(SetCompact(n)) in the satoshi code,
/// which drops the precision to something that can be encoded precisely in /// which drops the precision to something that can be encoded precisely in
/// the nBits block header field. Savour the perversity. This is in Bitcoin /// the nBits block header field. Savour the perversity. This is in Bitcoin
/// consensus code. What. The. Fuck. /// consensus code. What. Gaah!
fn satoshi_the_precision(n: &Uint256) -> Uint256 { fn satoshi_the_precision(n: &Uint256) -> Uint256 {
// Shift by B bits right then left to turn the low bits to zero // Shift by B bits right then left to turn the low bits to zero
let bits = 8 * ((n.bits() + 7) / 8 - 3); let bits = 8 * ((n.bits() + 7) / 8 - 3);

View File

@ -28,15 +28,6 @@ macro_rules! nu_select(
use rustrt::task::Task; use rustrt::task::Task;
use sync::comm::Packet; use sync::comm::Packet;
/// Obtains a borrowed reference to an object for an arbitrary amount of
/// time (it is on you to make sure the aliasing rules are followed and
/// that the borrow does not exceed the object's lifetime!!!!!!!!!!!!!!)
/// to subvert the borrow-checker. This is a workaround for the current
/// lexical-scope-based borrow times.
unsafe fn borrow_without_checking<'a, 'b, T>(obj: &'a T) -> &'b T {
&*(obj as *const _)
}
// Is anything already ready to receive? Grab it without waiting. // Is anything already ready to receive? Grab it without waiting.
$( $(
if (&$rx as &Packet).can_recv() { if (&$rx as &Packet).can_recv() {
@ -51,7 +42,8 @@ macro_rules! nu_select(
// that we started. // that we started.
let mut started_count = 0; let mut started_count = 0;
// Restrict lifetime of borrows in `packets` // Restrict lifetime of borrows in `packets`
let packets = [ $( unsafe { borrow_without_checking(&$rx) } as &Packet, )+ ]; {
let packets = [ $( &$rx as &Packet, )+ ];
let task: Box<Task> = Local::take(); let task: Box<Task> = Local::take();
task.deschedule(packets.len(), |task| { task.deschedule(packets.len(), |task| {
@ -63,29 +55,31 @@ macro_rules! nu_select(
Err(task) => Err(task) Err(task) => Err(task)
} }
}); });
}
let mut i = -1; let mut i = 0;
$( let ret = $(
// Abort every one, but only react to the first // Abort the receivers, stopping at the first ready one to get its data.
if { i += 1; i < started_count } && if { i += 1; i <= started_count } &&
// If start_selection() failed, abort_selection() will fail too, // If start_selection() failed, abort_selection() will fail too,
// but it still counts as "data available". // but it still counts as "data available".
(packets[i].abort_selection() || i == started_count - 1) { ($rx.abort_selection() || i == started_count) {
// Abort the remainder, ignoring their return values
i += 1;
while i < started_count {
packets[i].abort_selection();
i += 1;
}
// End manually-tracked borrow of $rx in packets
drop(packets);
// React to the first // React to the first
let $name = $rx.$meth(); let $name = $rx.$meth();
$code $code
} })else+
)else+
else { else {
fail!("we didn't find the ready receiver, but we should have had one"); } fail!("we didn't find the ready receiver, but we should have had one");
};
// At this point, the first i receivers have been aborted. We need to abort the rest:
$(if i > 0 {
i -= 1;
} else {
$rx.abort_selection();
})+
let _ = i; // Shut up `i -= 1 but i is never read` warning
// Return
ret
} }
}) })
) )