[personal profile] sassa_nf
https://doc.rust-lang.org/stable/book/ is good to start with, but slow.

So I tried to see how to use pselect for a practical purpose. There is https://gist.github.com/AGWA/b0931a912a8b22b2d6178a3155e171f3, of course, with a lot of interesting juggling there. But if we are learning, we won't copy-paste, and instead do the other way around - rewrite the things that are wrapped in FdSet (which is probably a good idea, but we are learning) as functions that use references to libc::fd_set, and rewrite the functions to_fdset_ptr and to_ptr that do raw translations as a new trait implementation.

The goal:
pub trait Nullable {
   type N;
   fn or_null(&self) -> *const Self::N;
}

impl<T> Nullable for Option<&T> {
...
}


pub trait MutNullable {
   type N;
   fn or_null_mut(&self) -> *mut Self::N;
}

impl<T> MutNullable for Option<&mut T> {
...
}

fn pselect(nfds: usize,
           read: Option<&mut libc::fd_set>,
           write: Option<&mut libc::fd_set>,
           err: Option<&mut libc::fd_set>,
           timeout: Option<&libc::timespec>,
           sigmask: Option<&libc::sigset_t>) -> std::io::Result<usize> {
   unsafe {
      let i = libc::pselect(
                    nfds as libc::c_int,
                    read.or_null_mut(),
                    write.or_null_mut(),
                    err.or_null_mut(),
                    timeout.or_null(),
                    sigmask.or_null()
               );
      if i < 0 {
         return Err(io::Error::last_os_error());
      }

      Ok(i as usize)
   }
}

The thing is,
libc::pselect(
                    nfds as libc::c_int,
                    read.map(|r| r as *mut libc::fd_set).unwrap_or_else(ptr::null_mut),
 ...
               );
works,
impl<T> Nullable for Option<&T> {
   type N = T;

   fn or_null(&self) -> *const T {
      self.map(|v| v as *const T).unwrap_or_else(ptr::null)
   }
}
also works, but
impl<T> MutNullable for Option<&mut T> {
   type N = T;

   fn or_null_mut(&self) -> *mut T {
      self.map(|r| r as *mut T).unwrap_or_else(ptr::null_mut)
   }
}
doesn't. Curious, eh?

I have a solution that works, and I think I know why it works, and the "straightforward" solution doesn't. In essence, https://doc.rust-lang.org/std/option/enum.Option.html#method.take is very important. (There's also a curious as_mut() method). The implementation of Iterators is very informative: https://doc.rust-lang.org/nomicon/borrow-splitting.html

Date: 2019-09-05 05:32 pm (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi
OMFG how hard it is to combine FP with mutability.

Date: 2019-09-05 07:03 pm (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi
Yep. Mind-boggling. I'm not ready to get the theoretical basis under it. Temporal linear logic?

Date: 2019-09-06 01:50 pm (UTC)
xacid: (Default)
From: [personal profile] xacid
Is it just NOP in runtime?

Profile

sassa_nf

January 2026

S M T W T F S
    123
45678910
111213141516 17
18192021222324
25262728293031

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 22nd, 2026 08:15 am
Powered by Dreamwidth Studios