1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 use core::ops; 15 16 use ylong_io::Interest; 17 18 const READABLE: usize = 0b0_01; 19 const WRITABLE: usize = 0b0_10; 20 const READ_CLOSED: usize = 0b0_0100; 21 const WRITE_CLOSED: usize = 0b0_1000; 22 23 cfg_not_ffrt! { 24 use ylong_io::{Event, EventTrait}; 25 } 26 27 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)] 28 pub struct Ready(usize); 29 30 #[derive(Debug)] 31 pub(crate) struct ReadyEvent { 32 tick: u8, 33 pub(crate) ready: Ready, 34 } 35 36 impl Ready { 37 pub const EMPTY: Ready = Ready(0); 38 39 pub const READABLE: Ready = Ready(READABLE); 40 41 pub const WRITABLE: Ready = Ready(WRITABLE); 42 43 pub const READ_CLOSED: Ready = Ready(READ_CLOSED); 44 45 pub const WRITE_CLOSED: Ready = Ready(WRITE_CLOSED); 46 47 pub const ALL: Ready = Ready(READABLE | WRITABLE | READ_CLOSED | WRITE_CLOSED); 48 49 #[cfg(not(feature = "ffrt"))] from_event(event: &Event) -> Ready50 pub(crate) fn from_event(event: &Event) -> Ready { 51 let mut ready = Ready::EMPTY; 52 53 if event.is_readable() { 54 ready |= Ready::READABLE; 55 } 56 57 if event.is_writable() { 58 ready |= Ready::WRITABLE; 59 } 60 61 if event.is_read_closed() { 62 ready |= Ready::READ_CLOSED; 63 } 64 65 if event.is_write_closed() { 66 ready |= Ready::WRITE_CLOSED; 67 } 68 ready 69 } 70 is_empty(self) -> bool71 pub fn is_empty(self) -> bool { 72 self == Ready::EMPTY 73 } 74 is_readable(self) -> bool75 pub fn is_readable(self) -> bool { 76 (self & Ready::READABLE).0 != 0 || self.is_read_closed() 77 } 78 is_writable(self) -> bool79 pub fn is_writable(self) -> bool { 80 (self & Ready::WRITABLE).0 != 0 || self.is_write_closed() 81 } 82 is_read_closed(self) -> bool83 pub fn is_read_closed(self) -> bool { 84 (self & Ready::READ_CLOSED).0 != 0 85 } 86 is_write_closed(self) -> bool87 pub fn is_write_closed(self) -> bool { 88 (self & Ready::WRITE_CLOSED).0 != 0 89 } 90 from_usize(val: usize) -> Ready91 pub(crate) fn from_usize(val: usize) -> Ready { 92 Ready(val & Ready::ALL.as_usize()) 93 } 94 as_usize(self) -> usize95 pub(crate) fn as_usize(self) -> usize { 96 self.0 97 } 98 from_interest(interest: Interest) -> Ready99 pub(crate) fn from_interest(interest: Interest) -> Ready { 100 let mut ready = Ready::EMPTY; 101 102 if interest.is_readable() { 103 ready |= Ready::READABLE; 104 ready |= Ready::READ_CLOSED; 105 } 106 107 if interest.is_writable() { 108 ready |= Ready::WRITABLE; 109 ready |= Ready::WRITE_CLOSED; 110 } 111 112 ready 113 } 114 intersection(self, interest: Interest) -> Ready115 pub(crate) fn intersection(self, interest: Interest) -> Ready { 116 Ready(self.0 & Ready::from_interest(interest).0) 117 } 118 satisfies(self, interest: Interest) -> bool119 pub(crate) fn satisfies(self, interest: Interest) -> bool { 120 self.0 & Ready::from_interest(interest).0 != 0 121 } 122 } 123 124 impl ops::BitOr<Ready> for Ready { 125 type Output = Ready; 126 127 #[inline] bitor(self, other: Ready) -> Self::Output128 fn bitor(self, other: Ready) -> Self::Output { 129 Ready(self.0 | other.0) 130 } 131 } 132 133 impl ops::BitOrAssign<Ready> for Ready { 134 #[inline] bitor_assign(&mut self, other: Ready)135 fn bitor_assign(&mut self, other: Ready) { 136 self.0 |= other.0 137 } 138 } 139 140 impl ops::BitAnd<Ready> for Ready { 141 type Output = Ready; 142 143 #[inline] bitand(self, other: Ready) -> Self::Output144 fn bitand(self, other: Ready) -> Self::Output { 145 Ready(self.0 & other.0) 146 } 147 } 148 149 impl ops::Sub<Ready> for Ready { 150 type Output = Ready; 151 152 #[inline] sub(self, other: Ready) -> Self::Output153 fn sub(self, other: Ready) -> Self::Output { 154 Ready(self.0 & !other.0) 155 } 156 } 157 158 impl ReadyEvent { new(tick: u8, ready: Ready) -> Self159 pub fn new(tick: u8, ready: Ready) -> Self { 160 ReadyEvent { tick, ready } 161 } 162 get_tick(&self) -> u8163 pub fn get_tick(&self) -> u8 { 164 self.tick 165 } 166 get_ready(&self) -> Ready167 pub fn get_ready(&self) -> Ready { 168 self.ready 169 } 170 } 171 172 cfg_ffrt! { 173 fn is_readable(event: i32) -> bool { 174 (event as libc::c_int & libc::EPOLLIN) != 0 175 || (event as libc::c_int & libc::EPOLLPRI) != 0 176 } 177 178 fn is_writable(event: i32) -> bool { 179 (event as libc::c_int & libc::EPOLLOUT) != 0 180 } 181 182 fn is_read_closed(event: i32) -> bool { 183 event as libc::c_int & libc::EPOLLHUP != 0 184 || (event as libc::c_int & libc::EPOLLIN != 0 185 && event as libc::c_int & libc::EPOLLRDHUP != 0) 186 } 187 188 fn is_write_closed(event: i32) -> bool { 189 event as libc::c_int & libc::EPOLLHUP != 0 190 || (event as libc::c_int & libc::EPOLLOUT != 0 191 && event as libc::c_int & libc::EPOLLERR != 0) 192 || event as libc::c_int == libc::EPOLLERR 193 } 194 195 pub(crate) fn from_event_inner(event: i32) -> Ready { 196 let mut ready = Ready::EMPTY; 197 if is_readable(event) { 198 ready |= Ready::READABLE; 199 } 200 201 if is_writable(event) { 202 ready |= Ready::WRITABLE; 203 } 204 205 if is_read_closed(event) { 206 ready |= Ready::READ_CLOSED; 207 } 208 209 if is_write_closed(event) { 210 ready |= Ready::WRITE_CLOSED; 211 } 212 ready 213 } 214 } 215 216 #[cfg(test)] 217 mod test { 218 use ylong_io::Interest; 219 220 use crate::net::{Ready, ReadyEvent}; 221 222 // @title ready from_event function ut test 223 // @design conditions of use override 224 // @precon none 225 // @brief 1. Create an event 226 // 2. Call from_event 227 // 3. Verify the returned results 228 // @expect 1. Event readable to get readable Ready instances 229 // 2. Event writable, call writable Ready instances 230 // 3. Event Read Close, Call Read Close Ready Instance 231 // 4. Event Write Close, Call Write Close Ready Instance 232 // @auto Yes 233 #[test] 234 #[cfg(all(not(feature = "ffrt"), target_os = "linux"))] ut_ready_from_event()235 fn ut_ready_from_event() { 236 ut_ready_from_event_01(); 237 ut_ready_from_event_02(); 238 ut_ready_from_event_03(); 239 ut_ready_from_event_04(); 240 241 // Readable 242 fn ut_ready_from_event_01() { 243 let mut event = libc::epoll_event { 244 events: 0b00, 245 u64: 0, 246 }; 247 event.events |= libc::EPOLLIN as u32; 248 let ready = Ready::from_event(&event); 249 assert_eq!(ready.0, 0b01); 250 } 251 252 // Writable 253 fn ut_ready_from_event_02() { 254 let mut event = libc::epoll_event { 255 events: 0b00, 256 u64: 0, 257 }; 258 event.events |= libc::EPOLLOUT as u32; 259 let ready = Ready::from_event(&event); 260 assert_eq!(ready.0, 0b10); 261 } 262 263 // Read off 264 fn ut_ready_from_event_03() { 265 let mut event = libc::epoll_event { 266 events: 0b00, 267 u64: 0, 268 }; 269 event.events |= (libc::EPOLLIN | libc::EPOLLRDHUP) as u32; 270 let ready = Ready::from_event(&event); 271 assert_eq!(ready.0, 0b101); 272 } 273 274 // Write Off 275 fn ut_ready_from_event_04() { 276 let mut event = libc::epoll_event { 277 events: 0x00, 278 u64: 0, 279 }; 280 event.events |= (libc::EPOLLOUT | libc::EPOLLERR) as u32; 281 let ready = Ready::from_event(&event); 282 assert_eq!(ready.0, 0b1010); 283 } 284 } 285 286 /// UT test cases for ready from_usize function 287 /// 288 /// # Brief 289 /// 1. Enter a usize, call from_usize 290 /// 2. Verify the returned results 291 #[test] ut_ready_from_usize()292 fn ut_ready_from_usize() { 293 let ready = Ready::from_usize(0x01); 294 assert_eq!(ready.0, 0x01); 295 } 296 297 /// UT test cases for ready is_empty function 298 /// 299 /// # Brief 300 /// 1. Create a Ready 301 /// 2. Call is_empty 302 /// 3. Verify the returned results 303 #[test] ut_ready_is_empty()304 fn ut_ready_is_empty() { 305 let ready = Ready::from_usize(0x00); 306 assert!(ready.is_empty()); 307 308 let ready = Ready::from_usize(0x01); 309 assert!(!ready.is_empty()); 310 } 311 312 /// UT test cases for ready is_readable function 313 /// 314 /// # Brief 315 /// 1. Create a Ready 316 /// 2. Call is_readable 317 /// 3. Verify the returned results 318 #[test] ut_ready_is_readable()319 fn ut_ready_is_readable() { 320 let ready = Ready::from_usize(0x01); 321 assert!(ready.is_readable()); 322 323 let ready = Ready::from_usize(0x02); 324 assert!(!ready.is_readable()); 325 } 326 327 /// UT test cases for ready is_writable function 328 /// 329 /// # Brief 330 /// 1. Create a Ready 331 /// 2. Call is_writable 332 /// 3. Verify the returned results 333 #[test] ut_ready_is_writable()334 fn ut_ready_is_writable() { 335 let ready = Ready::from_usize(0x02); 336 assert!(ready.is_writable()); 337 338 let ready = Ready::from_usize(0x01); 339 assert!(!ready.is_writable()); 340 } 341 342 /// UT test cases for ready is_read_closed function 343 /// 344 /// # Brief 345 /// 1. Create a Ready 346 /// 2. Call is_read_closed 347 /// 3. Verify the returned results 348 #[test] ut_ready_is_read_closed()349 fn ut_ready_is_read_closed() { 350 let ready = Ready::from_usize(0x04); 351 assert!(ready.is_read_closed()); 352 353 let ready = Ready::from_usize(0x01); 354 assert!(!ready.is_read_closed()); 355 } 356 357 /// UT test cases for ready is_write_closed function 358 /// 359 /// # Brief 360 /// 1. Create a Ready 361 /// 2. Call is_write_closed 362 /// 3. Verify the returned results 363 #[test] ut_ready_is_write_closed()364 fn ut_ready_is_write_closed() { 365 let ready = Ready::from_usize(0x08); 366 assert!(ready.is_write_closed()); 367 368 let ready = Ready::from_usize(0x01); 369 assert!(!ready.is_write_closed()); 370 } 371 372 /// UT test cases for ready as_usize function 373 /// 374 /// # Brief 375 /// 1. Create a Ready 376 /// 2. Call as_usize 377 /// 3. Verify the returned results 378 #[test] ut_ready_as_usize()379 fn ut_ready_as_usize() { 380 let ready = Ready::from_usize(0x08); 381 assert_eq!(ready.as_usize(), 0x08); 382 } 383 384 /// UT test cases for ready from_interest function 385 /// 386 /// # Brief 387 /// 1. Create a Interest instances 388 /// 2. Call from_interest 389 /// 3. Verify the returned results 390 #[test] ut_ready_from_interest()391 fn ut_ready_from_interest() { 392 let interest = Interest::READABLE; 393 let ready = Ready::from_interest(interest); 394 assert_eq!(ready.as_usize(), 0b101); 395 396 let interest = Interest::WRITABLE; 397 let ready = Ready::from_interest(interest); 398 assert_eq!(ready.as_usize(), 0b1010); 399 } 400 401 /// UT test cases for ready intersection function 402 /// 403 /// # Brief 404 /// 1. Create a Interest instances and a Ready instances 405 /// 2. Call intersection 406 /// 3. Verify the returned results 407 #[test] ut_ready_intersection()408 fn ut_ready_intersection() { 409 let interest = Interest::READABLE; 410 let ready = Ready::from_usize(0b1111); 411 let res = ready.intersection(interest); 412 assert_eq!(res.0, 0b0101); 413 } 414 415 /// UT test cases for ready satisfies function 416 /// 417 /// # Brief 418 /// 1. Create a Interest instances, and a Ready instances 419 /// 2. Call satisfies 420 /// 3. Verify the returned results 421 #[test] ut_ready_satisfies()422 fn ut_ready_satisfies() { 423 let interest = Interest::READABLE; 424 let ready = Ready::from_usize(0b1111); 425 assert!(ready.satisfies(interest)); 426 427 let ready = Ready::from_usize(0b0000); 428 assert!(!ready.satisfies(interest)); 429 } 430 431 /// UT test cases for ready bitor function 432 /// 433 /// # Brief 434 /// 1. Create two Ready instances 435 /// 2. Call bitor or use | logical operators 436 /// 3. Verify the returned results 437 #[test] ut_ready_bitor()438 fn ut_ready_bitor() { 439 let ready1 = Ready::from_usize(0b1010); 440 let ready2 = Ready::from_usize(0b0101); 441 let ready3 = ready1 | ready2; 442 assert_eq!(ready3.0, 0b1111); 443 } 444 445 /// UT test cases for ready bitor_assign function 446 /// 447 /// # Brief 448 /// 1. Create two Ready instances 449 /// 2. Call bitor_assign or use |= logical operators 450 /// 3. Verify the returned results 451 #[test] ut_ready_bitor_assign()452 fn ut_ready_bitor_assign() { 453 let mut ready1 = Ready::from_usize(0b1010); 454 let ready2 = Ready::from_usize(0b0101); 455 ready1 |= ready2; 456 assert_eq!(ready1.0, 0b1111); 457 } 458 459 /// UT test cases for ready bitand function 460 /// 461 /// # Brief 462 /// 1. Create two Ready instances 463 /// 2. Call bitand or use & logical operators 464 /// 3. Verify the returned results 465 #[test] ut_ready_bitand()466 fn ut_ready_bitand() { 467 let ready1 = Ready::from_usize(0b1010); 468 let ready2 = Ready::from_usize(0b0101); 469 let ready = ready1 & ready2; 470 assert_eq!(ready.0, 0b0000); 471 } 472 473 /// UT test cases for ready bitsub function 474 /// 475 /// # Brief 476 /// 1. Create two Ready instances 477 /// 2. Call bitsub or use - logical operators 478 /// 3. Verify the returned results 479 #[test] ut_ready_bitsub()480 fn ut_ready_bitsub() { 481 let ready1 = Ready::from_usize(0b1111); 482 let ready2 = Ready::from_usize(0b0101); 483 let ready = ready1 - ready2; 484 assert_eq!(ready.0, 0b1010); 485 } 486 487 /// UT test cases for ready_event new function 488 /// 489 /// # Brief 490 /// 1. Call new 491 /// 2. Verify the returned results 492 #[test] ut_ready_event_new()493 fn ut_ready_event_new() { 494 let ready_event = ReadyEvent::new(1u8, Ready::from_usize(0b0101)); 495 assert_eq!(ready_event.tick, 1u8); 496 assert_eq!(ready_event.ready.0, 0b0101); 497 } 498 499 /// UT test cases for ready_event get_tick function 500 /// 501 /// # Brief 502 /// 1. Create a ready_event 503 /// 2. Call get_tick 504 /// 3. Verify the returned results 505 #[test] ut_ready_event_get_tick()506 fn ut_ready_event_get_tick() { 507 let ready_event = ReadyEvent::new(1u8, Ready::from_usize(0b0101)); 508 assert_eq!(ready_event.get_tick(), 1u8); 509 } 510 511 /// UT test cases for ready_event get_ready function 512 /// 513 /// # Brief 514 /// 1. Create a ready_event 515 /// 2. Call get_ready 516 /// 3. Verify the returned results 517 #[test] ut_ready_event_get_ready()518 fn ut_ready_event_get_ready() { 519 let ready_event = ReadyEvent::new(1u8, Ready::from_usize(0b0101)); 520 assert_eq!(ready_event.get_ready().0, 0b0101); 521 } 522 } 523