Skip to content

Commit

Permalink
Update homework to 2024 edition.
Browse files Browse the repository at this point in the history
  • Loading branch information
Lee-Janggun committed Jan 15, 2025
1 parent 39cc955 commit 035a706
Show file tree
Hide file tree
Showing 25 changed files with 94 additions and 89 deletions.
2 changes: 1 addition & 1 deletion homework/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "cs431-homework"
version = "0.1.0"
authors = ["Jeehoon Kang <jeehoon.kang@kaist.ac.kr>"]
edition = "2021"
edition = "2024"

[[bin]]
name = "hello_server"
Expand Down
7 changes: 3 additions & 4 deletions homework/src/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use std::marker::PhantomData;
use std::ops::Deref;
use std::ptr::NonNull;
#[cfg(not(feature = "check-loom"))]
use std::sync::atomic::{fence, AtomicUsize, Ordering};
use std::sync::atomic::{AtomicUsize, Ordering, fence};
use std::{fmt, mem};

#[cfg(feature = "check-loom")]
use loom::sync::atomic::{fence, AtomicUsize, Ordering};
use loom::sync::atomic::{AtomicUsize, Ordering, fence};

const MAX_REFCOUNT: usize = (isize::MAX) as usize;

Expand Down Expand Up @@ -237,10 +237,9 @@ impl<T> Arc<T> {
/// }
/// assert_eq!(*x, "foo");
/// ```
#[allow(clippy::needless_pass_by_ref_mut)]
pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {
// We are careful to *not* create a reference covering the "count" fields, as
// this would alias with concurrent access to the reference counts.
// this would alias with concurrent access to the reference counts (e.g. by `Weak`).
unsafe { &mut (*this.ptr.as_ptr()).data }
}

Expand Down
2 changes: 1 addition & 1 deletion homework/src/bin/hello_server.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::io;
use std::sync::mpsc::{channel, sync_channel};
use std::sync::Arc;
use std::sync::mpsc::{channel, sync_channel};

use cs431_homework::hello_server::{CancellableTcpListener, Handler, Statistics, ThreadPool};

Expand Down
12 changes: 6 additions & 6 deletions homework/src/boc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::sync::Arc;
///
/// # Safety
///
/// `last()` should actually return the last request for the corresponding cown.
/// `last` should actually return the last request for the corresponding cown.
unsafe trait CownBase: Send {
/// Return a pointer to the tail of this cown's request queue.
fn last(&self) -> &AtomicPtr<Request>;
Expand Down Expand Up @@ -309,16 +309,16 @@ macro_rules! tuple_list {
($i:ident, $($e:ident),*,) => ( ($i, $crate::tuple_list!($($e),*)) );

// handling complex expressions
($i:expr) => ( ($i, ()) );
($i:expr,) => ( ($i, ()) );
($i:expr, $($e:expr),*) => ( ($i, $crate::tuple_list!($($e),*)) );
($i:expr, $($e:expr),*,) => ( ($i, $crate::tuple_list!($($e),*)) );
($i:expr_2021) => ( ($i, ()) );
($i:expr_2021,) => ( ($i, ()) );
($i:expr_2021, $($e:expr_2021),*) => ( ($i, $crate::tuple_list!($($e),*)) );
($i:expr_2021, $($e:expr_2021),*,) => ( ($i, $crate::tuple_list!($($e),*)) );
}

/// "When" block.
#[macro_export]
macro_rules! when {
( $( $cs:ident ),* ; $( $gs:ident ),* ; $thunk:expr ) => {{
( $( $cs:ident ),* ; $( $gs:ident ),* ; $thunk:expr_2021 ) => {{
run_when(tuple_list!($($cs.clone()),*), move |tuple_list!($($gs),*)| $thunk);
}};
}
Expand Down
6 changes: 3 additions & 3 deletions homework/src/elim_stack/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ use core::mem::ManuallyDrop;
use core::ops::Deref;
use std::time;

use crossbeam_epoch::{pin, Atomic, Guard, Owned};
use rand::{thread_rng, Rng};
use crossbeam_epoch::{Atomic, Guard, Owned, pin};
use rand::{Rng, thread_rng};

pub(crate) const ELIM_SIZE: usize = 16;
pub(crate) const ELIM_DELAY: time::Duration = time::Duration::from_millis(10);

#[inline]
pub(crate) fn get_random_elim_index() -> usize {
thread_rng().gen::<usize>() % ELIM_SIZE
thread_rng().r#gen::<usize>() % ELIM_SIZE
}

/// Concurrent stack types.
Expand Down
2 changes: 1 addition & 1 deletion homework/src/elim_stack/elim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::thread;

use crossbeam_epoch::{Guard, Owned, Shared};

use super::base::{get_random_elim_index, ElimStack, Stack, ELIM_DELAY};
use super::base::{ELIM_DELAY, ElimStack, Stack, get_random_elim_index};

impl<T, S: Stack<T>> Stack<T> for ElimStack<T, S> {
type PushReq = S::PushReq;
Expand Down
16 changes: 13 additions & 3 deletions homework/src/hash_table/growable_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use core::fmt::Debug;
use core::mem::{self, ManuallyDrop};
use core::sync::atomic::Ordering::*;

use crossbeam_epoch::{Atomic, Guard, Owned, Shared};

/// Growable array of `Atomic<T>`.
Expand Down Expand Up @@ -138,9 +139,9 @@ const SEGMENT_LOGSIZE: usize = 10;
/// pointers to `T`. This is determined by the height of this segment in the main array, which one
/// needs to track separately. For example, use the main array root's tag.
///
/// Since destructing `Segment<T>` requires its height information, it is not recommended to
/// implement `Drop` for this union. Rather, have a custom deallocate method that accounts for the
/// height of the segment.
/// Since destructing segments requires its height information, it is not recommended to
/// implement [`Drop`]. Rather, implement and use the custom [`Segment::deallocate`] method that
/// accounts for the height of the segment.
union Segment<T> {
children: ManuallyDrop<[Atomic<Segment<T>>; 1 << SEGMENT_LOGSIZE]>,
elements: ManuallyDrop<[Atomic<T>; 1 << SEGMENT_LOGSIZE]>,
Expand All @@ -156,6 +157,15 @@ impl<T> Segment<T> {
unsafe { mem::zeroed() },
)
}

/// Deallocates a segment of `height`.
///
/// # Safety
///
/// `self` must actually have height `height`.
unsafe fn deallocate(self, height: usize) {
todo!()
}
}

impl<T> Debug for Segment<T> {
Expand Down
7 changes: 6 additions & 1 deletion homework/src/hash_table/split_ordered_list.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! Split-ordered linked list.
use core::mem::{self, MaybeUninit};
use core::sync::atomic::{AtomicUsize, Ordering::*};
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering::*;

use crossbeam_epoch::{Guard, Owned};
use cs431::lockfree::list::{Cursor, List, Node};

Expand Down Expand Up @@ -73,16 +75,19 @@ impl<V> SplitOrderedList<V> {
impl<V> ConcurrentMap<usize, V> for SplitOrderedList<V> {
fn lookup<'a>(&'a self, key: &usize, guard: &'a Guard) -> Option<&'a V> {
Self::assert_valid_key(*key);

todo!()
}

fn insert(&self, key: usize, value: V, guard: &Guard) -> Result<(), V> {
Self::assert_valid_key(key);

todo!()
}

fn delete<'a>(&'a self, key: &usize, guard: &'a Guard) -> Result<&'a V, ()> {
Self::assert_valid_key(*key);

todo!()
}
}
14 changes: 7 additions & 7 deletions homework/src/hazard_pointer/hazard.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use core::ptr::{self, NonNull};
#[cfg(not(feature = "check-loom"))]
use core::sync::atomic::{fence, AtomicBool, AtomicPtr, AtomicUsize, Ordering};
use core::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering, fence};
use std::collections::HashSet;
use std::fmt;

#[cfg(feature = "check-loom")]
use loom::sync::atomic::{fence, AtomicBool, AtomicPtr, AtomicUsize, Ordering};
use loom::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering, fence};

use super::HAZARDS;

Expand Down Expand Up @@ -98,7 +98,7 @@ struct HazardSlot {
// Whether this slot is occupied by a `Shield`.
active: AtomicBool,
// Machine representation of the hazard pointer.
hazard: AtomicUsize,
hazard: AtomicPtr<()>,
// Immutable pointer to the next slot in the bag.
next: *const HazardSlot,
}
Expand Down Expand Up @@ -138,7 +138,7 @@ impl HazardBag {
}

/// Returns all the hazards in the set.
pub fn all_hazards(&self) -> HashSet<usize> {
pub fn all_hazards(&self) -> HashSet<*mut ()> {
todo!()
}
}
Expand All @@ -163,8 +163,8 @@ unsafe impl Sync for HazardSlot {}
mod tests {
use std::collections::HashSet;
use std::ops::Range;
use std::sync::atomic::AtomicPtr;
use std::sync::Arc;
use std::sync::atomic::AtomicPtr;
use std::{mem, thread};

use super::{HazardBag, Shield};
Expand Down Expand Up @@ -193,7 +193,7 @@ mod tests {
.into_iter()
.for_each(|th| th.join().unwrap());
let all = hazard_bag.all_hazards();
let values = VALUES.collect();
let values = VALUES.map(|data| data as *mut ()).collect();
assert!(all.is_superset(&values))
}

Expand All @@ -216,7 +216,7 @@ mod tests {
.into_iter()
.for_each(|th| th.join().unwrap());
let all = hazard_bag.all_hazards();
let values = VALUES.collect();
let values = VALUES.map(|data| data as *mut ()).collect();
let intersection: HashSet<_> = all.intersection(&values).collect();
assert!(intersection.is_empty())
}
Expand Down
14 changes: 8 additions & 6 deletions homework/src/hazard_pointer/retire.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use core::marker::PhantomData;
#[cfg(not(feature = "check-loom"))]
use core::sync::atomic::{fence, Ordering};
use core::sync::atomic::{Ordering, fence};

#[cfg(feature = "check-loom")]
use loom::sync::atomic::{fence, Ordering};
use loom::sync::atomic::{Ordering, fence};

use super::{HazardBag, HAZARDS};
use super::{HAZARDS, HazardBag};

type Retired = (*mut (), unsafe fn(*mut ()));

/// Thread-local list of retired pointers.
#[derive(Debug)]
pub struct RetiredSet<'s> {
hazards: &'s HazardBag,
/// The first element of the pair is the machine representation of the pointer and the second
/// is the function pointer to `free::<T>` where `T` is the type of the object.
inner: Vec<(usize, unsafe fn(usize))>,
inner: Vec<Retired>,
_marker: PhantomData<*const ()>, // !Send + !Sync
}

Expand Down Expand Up @@ -52,8 +54,8 @@ impl<'s> RetiredSet<'s> {
/// unique ownership to `data`.
///
/// [`Box::from_raw`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.from_raw
unsafe fn free<T>(data: usize) {
drop(unsafe { Box::from_raw(data as *mut T) })
unsafe fn free<T>(data: *mut ()) {
drop(unsafe { Box::from_raw(data.cast::<T>()) })
}

todo!()
Expand Down
3 changes: 2 additions & 1 deletion homework/src/hello_server/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ impl Handler {
.captures(&buf)
.and_then(|cap| cap.name("key"))
.map(|key| String::from_utf8_lossy(key.as_bytes()));

// TODO: Might be better to just change the strings to not have "{" and "}" in them.
#[allow(clippy::literal_string_with_formatting_args)]
let resp = if let Some(ref key) = key {
let result = self.cache.get_or_insert_with(
key.to_string(),
Expand Down
5 changes: 2 additions & 3 deletions homework/src/hello_server/tcp.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! TcpListener that can be cancelled.
use std::io;
use std::net::ToSocketAddrs;
use std::net::{TcpListener, TcpStream};
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::sync::atomic::{AtomicBool, Ordering};

/// Like `std::net::tcp::TcpListener`, but `cancel`lable.
Expand Down Expand Up @@ -42,7 +41,7 @@ impl CancellableTcpListener {
todo!()
}

/// Returns an iterator over the connections being received on this listener. The returned
/// Returns an iterator over the connections being received on this listener. The returned
/// iterator will return `None` if the listener is `cancel`led.
pub fn incoming(&self) -> Incoming<'_> {
Incoming { listener: self }
Expand Down
3 changes: 2 additions & 1 deletion homework/src/hello_server/thread_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
// NOTE: Crossbeam channels are MPMC, which means that you don't need to wrap the receiver in
// Arc<Mutex<..>>. Just clone the receiver and give it to each worker thread.
use crossbeam_channel::{unbounded, Sender};
use std::sync::{Arc, Condvar, Mutex};
use std::thread;

use crossbeam_channel::{Sender, unbounded};

struct Job(Box<dyn FnOnce() + Send + 'static>);

#[derive(Debug)]
Expand Down
3 changes: 1 addition & 2 deletions homework/src/list_set/fine_grained.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::cmp::Ordering::*;
use std::mem;
use std::ptr;
use std::sync::{Mutex, MutexGuard};
use std::{mem, ptr};

use crate::ConcurrentSet;

Expand Down
6 changes: 3 additions & 3 deletions homework/src/list_set/optimistic_fine_grained.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::cmp::Ordering::*;
use std::mem::{self, ManuallyDrop};
use std::sync::atomic::Ordering;
use std::sync::atomic::Ordering::*;

use crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared};
use crossbeam_epoch::{Atomic, Guard, Owned, Shared, pin};
use cs431::lock::seqlock::{ReadGuard, SeqLock};

use crate::ConcurrentSet;
Expand Down Expand Up @@ -58,7 +58,7 @@ impl<T> OptimisticFineGrainedListSet<T> {

fn head<'g>(&'g self, guard: &'g Guard) -> Cursor<'g, T> {
let prev = unsafe { self.head.read_lock() };
let curr = prev.load(Ordering::SeqCst, guard);
let curr = prev.load(Acquire, guard);
Cursor { prev, curr }
}
}
Expand Down
15 changes: 8 additions & 7 deletions homework/src/test/adt/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
use core::fmt::Debug;
use core::hash::Hash;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::thread::scope;

use crossbeam_epoch::pin;
use rand::prelude::*;

use crate::test::RandGen;
use crate::ConcurrentMap;
use crate::test::RandGen;

/// Runs many operations in a single thread and tests if it works like a map data structure using
/// `std::collections::HashMap` as reference.
Expand Down Expand Up @@ -69,11 +69,12 @@ pub fn stress_sequential<
println!("iteration {i}: insert({key:?}, {value:?})");

let map_res = map.insert(key.clone(), value.clone(), &pin());
let hmap_res = if let Entry::Vacant(e) = hashmap.entry(key) {
let _ = e.insert(value);
Ok(())
} else {
Err(value)
let hmap_res = match hashmap.entry(key) {
Entry::Vacant(e) => {
let _ = e.insert(value);
Ok(())
}
_ => Err(value),
};
assert_eq!(map_res, hmap_res);
}
Expand Down
Loading

0 comments on commit 035a706

Please sign in to comment.