1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
use std::alloc::{alloc, dealloc, realloc, Layout};
use std::mem::size_of;
struct MyVec {
arr: *mut u8,
len: usize,
cap: usize,
}
impl MyVec {
fn new(init_size: usize) -> MyVec {
MyVec {
arr: unsafe { alloc(arr_layout(init_size)) },
len: 0,
cap: init_size,
}
}
fn push(&mut self, value: i32) {
unsafe {
if self.len >= self.cap {
self.arr = realloc(
self.arr,
arr_layout(self.cap),
self.cap * 2 * size_of::<i32>(),
);
self.cap *= 2;
}
*(self.arr as *mut i32).offset(self.len as isize) = value;
self.len += 1;
}
}
fn as_slice(&self) -> &[i32] {
unsafe { std::slice::from_raw_parts(self.arr as *mut i32, self.len) }
}
}
impl Clone for MyVec {
fn clone(&self) -> MyVec {
unsafe {
let arr = alloc(arr_layout(self.cap));
std::ptr::copy_nonoverlapping(self.arr, arr, self.len);
MyVec { arr, ..*self }
}
}
}
fn arr_layout(cap: usize) -> Layout {
Layout::from_size_align(cap * size_of::<i32>(), size_of::<i32>()).unwrap()
}
impl Drop for MyVec {
fn drop(&mut self) {
println!("hi drop");
unsafe { dealloc(self.arr as *mut u8, arr_layout(self.cap)) };
}
}
fn consume(v: MyVec) {
println!("Consuming {:?}!", v.as_slice());
}
fn main() {
// Ownership:
// - Each value in Rust has an owner.
// - There can only be one owner at a time.
// - When the owner goes out of scope, the value will be dropped.
let mut v = MyVec::new(10);
v.push(100);
v.push(200);
// Semantic 1: types that does not have Copy trait have "move semantic":
// all the operator = , argument passing, and `return` are move operatons
// Semantic 2: moved value cannot be accessed anymore
// Semantic 3: moved variable can bind to a new value
// Semantic 4: re-assigning to a variable will cause the old value to be dropped
//
// Semantic 5: types that have Copy trait have "copy semantic":
// all the operator = , argument passing, and `return` are copy
//
// Usage: clone must be explicit!
let v2 = v.clone();
consume(v);
v = MyVec::new(4);
// how drop is implemented
// alternative 1
fn mydrop(v: MyVec) {
println!("In mydrop");
}
// alternative 2
{
let move_into_scope = v;
}
// mydrop(v);
println!("After mydrop");
// let v2 = v.clone();
// dbg!(v.len);
let t = 10;
let t_cloned = 5.clone();
let t_moved_actually_copied = t;
#[derive(Clone, Copy)]
struct MyInt {
x: i32,
}
let x = MyInt { x: 2000 };
let y = x;
println!("x.x = {}, y.x = {}", x.x, y.x);
// Copy: special marker trait
// Clone: trait that provide method to duplicate something
// Drop: non-trivial destructor
//
// Rule 1: Copy xor Drop
// Rule 2: Copy requires Clone
// Rule 3: Drop and Clone are orthogonal
dbg!(t);
}
/*
// Ownership works not only for allocation, but also for any **resources**
struct File {
fd: i32,
}
impl File {
fn open(filename) -> File {
File { fd: [>call C open(filename)<] }
}
}
impl Drop for File {
fn drop(&mut self) {
// close(self.fd)
}
} */
|