mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
make Send/Sync impl of RawTable manual
This commit is contained in:
parent
474b324eda
commit
998599187f
@ -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.
|
||||||
}
|
}
|
||||||
|
21
src/test/compile-fail/issue-21763.rs
Normal file
21
src/test/compile-fail/issue-21763.rs
Normal 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<()>`
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user