Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
2a999b4b
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2a999b4b
编写于
6月 09, 2018
作者:
J
Joshua Liebow-Feeser
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add Ref/RefMut map_split method
上级
c131bdca
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
185 addition
and
19 deletion
+185
-19
src/libcore/cell.rs
src/libcore/cell.rs
+126
-19
src/libcore/tests/cell.rs
src/libcore/tests/cell.rs
+58
-0
src/libcore/tests/lib.rs
src/libcore/tests/lib.rs
+1
-0
未找到文件。
src/libcore/cell.rs
浏览文件 @
2a999b4b
...
...
@@ -570,11 +570,20 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
// Values [1, MAX-1] represent the number of `Ref` active
// (will not outgrow its range since `usize` is the size of the address space)
// Values [1, MIN_WRITING-1] represent the number of `Ref` active. Values in
// [MIN_WRITING, MAX-1] represent the number of `RefMut` active. Multiple
// `RefMut`s can only be active at a time if they refer to distinct,
// nonoverlapping components of a `RefCell` (e.g., different ranges of a slice).
//
// `Ref` and `RefMut` are both two words in size, and so there will likely never
// be enough `Ref`s or `RefMut`s in existence to overflow half of the `usize`
// range. Thus, a `BorrowFlag` will probably never overflow. However, this is
// not a guarantee, as a pathological program could repeatedly create and then
// mem::forget `Ref`s or `RefMut`s. Thus, all code must explicitly check for
// overflow in order to avoid unsafety.
type
BorrowFlag
=
usize
;
const
UNUSED
:
BorrowFlag
=
0
;
const
WRITING
:
BorrowFlag
=
!
0
;
const
MIN_WRITING
:
BorrowFlag
=
(
!
0
)
/
2
+
1
;
// 0b1000...
impl
<
T
>
RefCell
<
T
>
{
/// Creates a new `RefCell` containing `value`.
...
...
@@ -775,8 +784,9 @@ pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> {
/// Mutably borrows the wrapped value.
///
/// The borrow lasts until the returned `RefMut` exits scope. The value
/// cannot be borrowed while this borrow is active.
/// The borrow lasts until the returned `RefMut` or all `RefMut`s derived
/// from it exit scope. The value cannot be borrowed while this borrow is
/// active.
///
/// # Panics
///
...
...
@@ -818,8 +828,9 @@ pub fn borrow_mut(&self) -> RefMut<T> {
/// Mutably borrows the wrapped value, returning an error if the value is currently borrowed.
///
/// The borrow lasts until the returned `RefMut` exits scope. The value cannot be borrowed
/// while this borrow is active.
/// The borrow lasts until the returned `RefMut` or all `RefMut`s derived
/// from it exit scope. The value cannot be borrowed while this borrow is
/// active.
///
/// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).
///
...
...
@@ -1010,12 +1021,15 @@ struct BorrowRef<'b> {
impl
<
'b
>
BorrowRef
<
'b
>
{
#[inline]
fn
new
(
borrow
:
&
'b
Cell
<
BorrowFlag
>
)
->
Option
<
BorrowRef
<
'b
>>
{
match
borrow
.get
()
{
WRITING
=>
None
,
b
=>
{
borrow
.set
(
b
+
1
);
Some
(
BorrowRef
{
borrow
:
borrow
})
},
let
b
=
borrow
.get
();
if
b
>=
MIN_WRITING
{
None
}
else
{
// Prevent the borrow counter from overflowing into
// a writing borrow.
assert
!
(
b
<
MIN_WRITING
-
1
);
borrow
.set
(
b
+
1
);
Some
(
BorrowRef
{
borrow
})
}
}
}
...
...
@@ -1024,7 +1038,7 @@ impl<'b> Drop for BorrowRef<'b> {
#[inline]
fn
drop
(
&
mut
self
)
{
let
borrow
=
self
.borrow
.get
();
debug_assert!
(
borrow
!=
WRITING
&&
borrow
!=
UNUSED
);
debug_assert!
(
borrow
<
MIN_
WRITING
&&
borrow
!=
UNUSED
);
self
.borrow
.set
(
borrow
-
1
);
}
}
...
...
@@ -1036,8 +1050,9 @@ fn clone(&self) -> BorrowRef<'b> {
// is not set to WRITING.
let
borrow
=
self
.borrow
.get
();
debug_assert!
(
borrow
!=
UNUSED
);
// Prevent the borrow counter from overflowing.
assert
!
(
borrow
!=
WRITING
);
// Prevent the borrow counter from overflowing into
// a writing borrow.
assert
!
(
borrow
<
MIN_WRITING
-
1
);
self
.borrow
.set
(
borrow
+
1
);
BorrowRef
{
borrow
:
self
.borrow
}
}
...
...
@@ -1109,6 +1124,37 @@ pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
borrow
:
orig
.borrow
,
}
}
/// Split a `Ref` into multiple `Ref`s for different components of the
/// borrowed data.
///
/// The `RefCell` is already immutably borrowed, so this cannot fail.
///
/// This is an associated function that needs to be used as
/// `Ref::map_split(...)`. A method would interfere with methods of the same
/// name on the contents of a `RefCell` used through `Deref`.
///
/// # Examples
///
/// ```
/// #![feature(refcell_map_split)]
/// use std::cell::{Ref, RefCell};
///
/// let cell = RefCell::new([1, 2, 3, 4]);
/// let borrow = cell.borrow();
/// let (begin, end) = Ref::map_split(borrow, |slice| slice.split_at(2));
/// assert_eq!(*begin, [1, 2]);
/// assert_eq!(*end, [3, 4]);
/// ```
#[unstable(feature
=
"refcell_map_split"
,
issue
=
"51476"
)]
#[inline]
pub
fn
map_split
<
U
:
?
Sized
,
V
:
?
Sized
,
F
>
(
orig
:
Ref
<
'b
,
T
>
,
f
:
F
)
->
(
Ref
<
'b
,
U
>
,
Ref
<
'b
,
V
>
)
where
F
:
FnOnce
(
&
T
)
->
(
&
U
,
&
V
)
{
let
(
a
,
b
)
=
f
(
orig
.value
);
let
borrow
=
orig
.borrow
.clone
();
(
Ref
{
value
:
a
,
borrow
},
Ref
{
value
:
b
,
borrow
:
orig
.borrow
})
}
}
#[unstable(feature
=
"coerce_unsized"
,
issue
=
"27732"
)]
...
...
@@ -1157,6 +1203,44 @@ pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
borrow
:
borrow
,
}
}
/// Split a `RefMut` into multiple `RefMut`s for different components of the
/// borrowed data.
///
/// The underlying `RefCell` will remain mutably borrowed until both
/// returned `RefMut`s go out of scope.
///
/// The `RefCell` is already mutably borrowed, so this cannot fail.
///
/// This is an associated function that needs to be used as
/// `RefMut::map_split(...)`. A method would interfere with methods of the
/// same name on the contents of a `RefCell` used through `Deref`.
///
/// # Examples
///
/// ```
/// #![feature(refcell_map_split)]
/// use std::cell::{RefCell, RefMut};
///
/// let cell = RefCell::new([1, 2, 3, 4]);
/// let borrow = cell.borrow_mut();
/// let (mut begin, mut end) = RefMut::map_split(borrow, |slice| slice.split_at_mut(2));
/// assert_eq!(*begin, [1, 2]);
/// assert_eq!(*end, [3, 4]);
/// begin.copy_from_slice(&[4, 3]);
/// end.copy_from_slice(&[2, 1]);
/// ```
#[unstable(feature
=
"refcell_map_split"
,
issue
=
"51476"
)]
#[inline]
pub
fn
map_split
<
U
:
?
Sized
,
V
:
?
Sized
,
F
>
(
orig
:
RefMut
<
'b
,
T
>
,
f
:
F
)
->
(
RefMut
<
'b
,
U
>
,
RefMut
<
'b
,
V
>
)
where
F
:
FnOnce
(
&
mut
T
)
->
(
&
mut
U
,
&
mut
V
)
{
let
(
a
,
b
)
=
f
(
orig
.value
);
let
borrow
=
orig
.borrow
.clone
();
(
RefMut
{
value
:
a
,
borrow
},
RefMut
{
value
:
b
,
borrow
:
orig
.borrow
})
}
}
struct
BorrowRefMut
<
'b
>
{
...
...
@@ -1167,22 +1251,45 @@ impl<'b> Drop for BorrowRefMut<'b> {
#[inline]
fn
drop
(
&
mut
self
)
{
let
borrow
=
self
.borrow
.get
();
debug_assert!
(
borrow
==
WRITING
);
self
.borrow
.set
(
UNUSED
);
debug_assert!
(
borrow
>=
MIN_WRITING
);
self
.borrow
.set
(
if
borrow
==
MIN_WRITING
{
UNUSED
}
else
{
borrow
-
1
});
}
}
impl
<
'b
>
BorrowRefMut
<
'b
>
{
#[inline]
fn
new
(
borrow
:
&
'b
Cell
<
BorrowFlag
>
)
->
Option
<
BorrowRefMut
<
'b
>>
{
// NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
// mutable reference, and so there must currently be no existing
// references. Thus, while clone increments the mutable refcount, here
// we simply go directly from UNUSED to MIN_WRITING.
match
borrow
.get
()
{
UNUSED
=>
{
borrow
.set
(
WRITING
);
borrow
.set
(
MIN_
WRITING
);
Some
(
BorrowRefMut
{
borrow
:
borrow
})
},
_
=>
None
,
}
}
// Clone a `BorrowRefMut`.
//
// This is only valid if each `BorrowRefMut` is used to track a mutable
// reference to a distinct, nonoverlapping range of the original object.
// This isn't in a Clone impl so that code doesn't call this implicitly.
#[inline]
fn
clone
(
&
self
)
->
BorrowRefMut
<
'b
>
{
let
borrow
=
self
.borrow
.get
();
debug_assert!
(
borrow
>=
MIN_WRITING
);
// Prevent the borrow counter from overflowing.
assert
!
(
borrow
!=
!
0
);
self
.borrow
.set
(
borrow
+
1
);
BorrowRefMut
{
borrow
:
self
.borrow
}
}
}
/// A wrapper type for a mutably borrowed value from a `RefCell<T>`.
...
...
src/libcore/tests/cell.rs
浏览文件 @
2a999b4b
...
...
@@ -165,6 +165,64 @@ fn ref_map_does_not_update_flag() {
assert
!
(
x
.try_borrow_mut
()
.is_ok
());
}
#[test]
fn
ref_map_split_updates_flag
()
{
let
x
=
RefCell
::
new
([
1
,
2
]);
{
let
b1
=
x
.borrow
();
assert
!
(
x
.try_borrow
()
.is_ok
());
assert
!
(
x
.try_borrow_mut
()
.is_err
());
{
let
(
_
b2
,
_
b3
)
=
Ref
::
map_split
(
b1
,
|
slc
|
slc
.split_at
(
1
));
assert
!
(
x
.try_borrow
()
.is_ok
());
assert
!
(
x
.try_borrow_mut
()
.is_err
());
}
assert
!
(
x
.try_borrow
()
.is_ok
());
assert
!
(
x
.try_borrow_mut
()
.is_ok
());
}
assert
!
(
x
.try_borrow
()
.is_ok
());
assert
!
(
x
.try_borrow_mut
()
.is_ok
());
{
let
b1
=
x
.borrow_mut
();
assert
!
(
x
.try_borrow
()
.is_err
());
assert
!
(
x
.try_borrow_mut
()
.is_err
());
{
let
(
_
b2
,
_
b3
)
=
RefMut
::
map_split
(
b1
,
|
slc
|
slc
.split_at_mut
(
1
));
assert
!
(
x
.try_borrow
()
.is_err
());
assert
!
(
x
.try_borrow_mut
()
.is_err
());
drop
(
_
b2
);
assert
!
(
x
.try_borrow
()
.is_err
());
assert
!
(
x
.try_borrow_mut
()
.is_err
());
}
assert
!
(
x
.try_borrow
()
.is_ok
());
assert
!
(
x
.try_borrow_mut
()
.is_ok
());
}
assert
!
(
x
.try_borrow
()
.is_ok
());
assert
!
(
x
.try_borrow_mut
()
.is_ok
());
}
#[test]
fn
ref_map_split
()
{
let
x
=
RefCell
::
new
([
1
,
2
]);
let
(
b1
,
b2
)
=
Ref
::
map_split
(
x
.borrow
(),
|
slc
|
slc
.split_at
(
1
));
assert_eq!
(
*
b1
,
[
1
]);
assert_eq!
(
*
b2
,
[
2
]);
}
#[test]
fn
ref_mut_map_split
()
{
let
x
=
RefCell
::
new
([
1
,
2
]);
{
let
(
mut
b1
,
mut
b2
)
=
RefMut
::
map_split
(
x
.borrow_mut
(),
|
slc
|
slc
.split_at_mut
(
1
));
assert_eq!
(
*
b1
,
[
1
]);
assert_eq!
(
*
b2
,
[
2
]);
b1
[
0
]
=
2
;
b2
[
0
]
=
1
;
}
assert_eq!
(
*
x
.borrow
(),
[
2
,
1
]);
}
#[test]
fn
ref_map_accessor
()
{
struct
X
(
RefCell
<
(
u32
,
char
)
>
);
...
...
src/libcore/tests/lib.rs
浏览文件 @
2a999b4b
...
...
@@ -29,6 +29,7 @@
#![feature(pattern)]
#![feature(range_is_empty)]
#![feature(raw)]
#![feature(refcell_map_split)]
#![feature(refcell_replace_swap)]
#![feature(slice_patterns)]
#![feature(slice_rotate)]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录