make Send/Sync impl of RawTable manual

This commit is contained in:
Alexis 2015-01-29 22:18:45 -05:00
parent 474b324eda
commit 998599187f
2 changed files with 35 additions and 12 deletions

View File

@ -16,15 +16,14 @@ use clone::Clone;
use cmp; use cmp;
use hash::{Hash, Hasher}; use hash::{Hash, Hasher};
use iter::{Iterator, IteratorExt, ExactSizeIterator, count}; use iter::{Iterator, IteratorExt, ExactSizeIterator, count};
use marker::{Copy, Sized, self}; use marker::{Copy, Send, Sync, Sized, self};
use mem::{min_align_of, size_of}; use mem::{min_align_of, size_of};
use mem; use mem;
use num::{Int, UnsignedInt}; use num::{Int, UnsignedInt};
use ops::{Deref, DerefMut, Drop}; use ops::{Deref, DerefMut, Drop};
use option::Option; use option::Option;
use option::Option::{Some, None}; use option::Option::{Some, None};
use ptr::{Unique, PtrExt, copy_nonoverlapping_memory, zero_memory}; use ptr::{self, PtrExt, copy_nonoverlapping_memory, zero_memory};
use ptr;
use rt::heap::{allocate, deallocate}; use rt::heap::{allocate, deallocate};
use collections::hash_state::HashState; use collections::hash_state::HashState;
@ -70,12 +69,15 @@ const EMPTY_BUCKET: u64 = 0u64;
pub struct RawTable<K, V> { pub struct RawTable<K, V> {
capacity: uint, capacity: uint,
size: uint, size: uint,
hashes: Unique<u64>, hashes: *mut u64,
// Because K/V do not appear directly in any of the types in the struct, // Because K/V do not appear directly in any of the types in the struct,
// inform rustc that in fact instances of K and V are reachable from here. // inform rustc that in fact instances of K and V are reachable from here.
marker: marker::CovariantType<(K,V)>, marker: marker::CovariantType<(K,V)>,
} }
unsafe impl<K: Send, V: Send> Send for RawTable<K, V> {}
unsafe impl<K: Sync, V: Sync> Sync for RawTable<K, V> {}
struct RawBucket<K, V> { struct RawBucket<K, V> {
hash: *mut u64, hash: *mut u64,
key: *mut K, key: *mut K,
@ -565,7 +567,7 @@ impl<K, V> RawTable<K, V> {
return RawTable { return RawTable {
size: 0, size: 0,
capacity: 0, capacity: 0,
hashes: Unique::null(), hashes: ptr::null_mut(),
marker: marker::CovariantType, marker: marker::CovariantType,
}; };
} }
@ -604,7 +606,7 @@ impl<K, V> RawTable<K, V> {
RawTable { RawTable {
capacity: capacity, capacity: capacity,
size: 0, size: 0,
hashes: Unique(hashes), hashes: hashes,
marker: marker::CovariantType, marker: marker::CovariantType,
} }
} }
@ -613,14 +615,14 @@ impl<K, V> RawTable<K, V> {
let hashes_size = self.capacity * size_of::<u64>(); let hashes_size = self.capacity * size_of::<u64>();
let keys_size = self.capacity * size_of::<K>(); let keys_size = self.capacity * size_of::<K>();
let buffer = self.hashes.0 as *mut u8; let buffer = self.hashes as *mut u8;
let (keys_offset, vals_offset) = calculate_offsets(hashes_size, let (keys_offset, vals_offset) = calculate_offsets(hashes_size,
keys_size, min_align_of::<K>(), keys_size, min_align_of::<K>(),
min_align_of::<V>()); min_align_of::<V>());
unsafe { unsafe {
RawBucket { RawBucket {
hash: self.hashes.0, hash: self.hashes,
key: buffer.offset(keys_offset as int) as *mut K, key: buffer.offset(keys_offset as int) as *mut K,
val: buffer.offset(vals_offset as int) as *mut V val: buffer.offset(vals_offset as int) as *mut V
} }
@ -632,7 +634,7 @@ impl<K, V> RawTable<K, V> {
pub fn new(capacity: uint) -> RawTable<K, V> { pub fn new(capacity: uint) -> RawTable<K, V> {
unsafe { unsafe {
let ret = RawTable::new_uninitialized(capacity); let ret = RawTable::new_uninitialized(capacity);
zero_memory(ret.hashes.0, capacity); zero_memory(ret.hashes, capacity);
ret ret
} }
} }
@ -652,7 +654,7 @@ impl<K, V> RawTable<K, V> {
RawBuckets { RawBuckets {
raw: self.first_bucket_raw(), raw: self.first_bucket_raw(),
hashes_end: unsafe { hashes_end: unsafe {
self.hashes.0.offset(self.capacity as int) self.hashes.offset(self.capacity as int)
}, },
marker: marker::ContravariantLifetime, marker: marker::ContravariantLifetime,
} }
@ -964,7 +966,7 @@ impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
#[unsafe_destructor] #[unsafe_destructor]
impl<K, V> Drop for RawTable<K, V> { impl<K, V> Drop for RawTable<K, V> {
fn drop(&mut self) { fn drop(&mut self) {
if self.hashes.0.is_null() { if self.hashes.is_null() {
return; return;
} }
// This is done in reverse because we've likely partially taken // This is done in reverse because we've likely partially taken
@ -984,7 +986,7 @@ impl<K, V> Drop for RawTable<K, V> {
vals_size, min_align_of::<V>()); vals_size, min_align_of::<V>());
unsafe { unsafe {
deallocate(self.hashes.0 as *mut u8, size, align); deallocate(self.hashes as *mut u8, size, align);
// Remember how everything was allocated out of one buffer // Remember how everything was allocated out of one buffer
// during initialization? We only need one call to free here. // during initialization? We only need one call to free here.
} }

View File

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Regression test for HashMap only impl'ing Send/Sync if its contents do
use std::collections::HashMap;
use std::rc::Rc;
fn foo<T: Send>() {}
fn main() {
foo::<HashMap<Rc<()>, Rc<()>>>();
//~^ ERROR: the trait `core::marker::Send` is not implemented for the type `alloc::rc::Rc<()>`
}