Repository: GuillaumeGomez/sysinfo
Pull request #677 (2022-01-13 16:43:11)

Turn Pid into a newtype


Patch:
diff --git a/.cirrus.yml b/.cirrus.yml
index 1b5cc8b..8c0368f 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -12,6 +12,7 @@ task:
   test_script:
     - . $HOME/.cargo/env
     - cargo check
+    - cargo check --no-default-features
     - cargo clippy -- -D warnings
     - cargo check --example simple
     - FREEBSD_CI=1 cargo test -j1
@@ -30,6 +31,7 @@ task:
   test_script:
     - . $HOME/.cargo/env
     - cargo check
+    - cargo check --no-default-features
     - cargo clippy -- -D warnings
     - cargo check --example simple
     - FREEBSD_CI=1 cargo test -j1
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 5e596e9..89d0ac0 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -83,6 +83,12 @@ jobs:
           command: check
           args: --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml
           use-cross: ${{ matrix.triple.cross }}
+      - name: Check without multithreading
+        uses: actions-rs/cargo@v1
+        with:
+          command: check
+          args: --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml --no-default-features
+          use-cross: ${{ matrix.triple.cross }}
 
       - name: Check example
         uses: actions-rs/cargo@v1
@@ -98,6 +104,13 @@ jobs:
           command: check
           args: --features apple-sandbox --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml
           use-cross: ${{ matrix.triple.cross }}
+      - name: Check without multithreading (Apple app store restrictions)
+        if: matrix.triple.os == 'macos-latest'
+        uses: actions-rs/cargo@v1
+        with:
+          command: check
+          args: --features apple-sandbox --target=${{ matrix.triple.target }} --manifest-path=Cargo.toml --no-default-features
+          use-cross: ${{ matrix.triple.cross }}
 
   tests:
     needs: [check]
diff --git a/md_doc/pid.md b/md_doc/pid.md
index d461f22..d80e1ab 100644
--- a/md_doc/pid.md
+++ b/md_doc/pid.md
@@ -3,12 +3,18 @@ Process id
 Can be used as an integer type by simple casting. For example:
 
 ```
-use sysinfo::{AsU32, Pid};
+use sysinfo::{PidExt, Pid};
 
-let p: Pid = 0;
+// 0's type will be different depending on the platform!
+let p = Pid::from(0);
+
+// For something more "general":
+let p = Pid::from_u32(0);
 let i: u32 = p.as_u32();
 ```
 
 On glibc systems this is a glibc [`pid_t`](https://www.gnu.org/software/libc/manual/html_node/Process-Identification.html).
 
 On Windows systems this is a [`usize` and represents a windows process identifier](https://docs.microsoft.com/en-us/windows/win32/procthread/process-handles-and-identifiers).
+
+On unsupported systems, this is also a `usize`.
diff --git a/src/apple/app_store/process.rs b/src/apple/app_store/process.rs
index 27eb18b..1e5b0e1 100644
--- a/src/apple/app_store/process.rs
+++ b/src/apple/app_store/process.rs
@@ -26,7 +26,7 @@ impl ProcessExt for Process {
     }
 
     fn pid(&self) -> Pid {
-        0
+        Pid(0)
     }
 
     fn environ(&self) -> &[String] {
diff --git a/src/apple/macos/process.rs b/src/apple/macos/process.rs
index 64e1264..273ba7b 100644
--- a/src/apple/macos/process.rs
+++ b/src/apple/macos/process.rs
@@ -153,7 +153,7 @@ impl Process {
 impl ProcessExt for Process {
     fn kill_with(&self, signal: Signal) -> Option<bool> {
         let c_signal = crate::sys::system::convert_signal(signal)?;
-        unsafe { Some(kill(self.pid, c_signal) == 0) }
+        unsafe { Some(kill(self.pid.0, c_signal) == 0) }
     }
 
     fn name(&self) -> &str {
@@ -292,7 +292,7 @@ unsafe fn get_task_info(pid: Pid) -> libc::proc_taskinfo {
     // If it doesn't work, we just don't have memory information for this process
     // so it's "fine".
     libc::proc_pidinfo(
-        pid,
+        pid.0,
         libc::PROC_PIDTASKINFO,
         0,
         &mut task_info as *mut libc::proc_taskinfo as *mut c_void,
@@ -321,7 +321,7 @@ pub(crate) fn update_process(
             let task_info = get_task_info(pid);
             let mut thread_info = mem::zeroed::<libc::proc_threadinfo>();
             let (user_time, system_time, thread_status) = if libc::proc_pidinfo(
-                pid,
+                pid.0,
                 libc::PROC_PIDTHREADINFO,
                 0,
                 &mut thread_info as *mut libc::proc_threadinfo as *mut c_void,
@@ -351,7 +351,7 @@ pub(crate) fn update_process(
 
         let mut vnodepathinfo = mem::zeroed::<libc::proc_vnodepathinfo>();
         let result = libc::proc_pidinfo(
-            pid,
+            pid.0,
             libc::PROC_PIDVNODEPATHINFO,
             0,
             &mut vnodepathinfo as *mut _ as *mut _,
@@ -370,7 +370,7 @@ pub(crate) fn update_process(
 
         let mut info = mem::zeroed::<libc::proc_bsdinfo>();
         if libc::proc_pidinfo(
-            pid,
+            pid.0,
             libc::PROC_PIDTBSDINFO,
             0,
             &mut info as *mut _ as *mut _,
@@ -379,7 +379,7 @@ pub(crate) fn update_process(
         {
             let mut buffer: Vec<u8> = Vec::with_capacity(libc::PROC_PIDPATHINFO_MAXSIZE as _);
             match libc::proc_pidpath(
-                pid,
+                pid.0,
                 buffer.as_mut_ptr() as *mut _,
                 libc::PROC_PIDPATHINFO_MAXSIZE as _,
             ) {
@@ -400,11 +400,11 @@ pub(crate) fn update_process(
         }
         let parent = match info.pbi_ppid as i32 {
             0 => None,
-            p => Some(p),
+            p => Some(Pid(p)),
         };
 
         let ptr: *mut u8 = proc_args.as_mut_slice().as_mut_ptr();
-        let mut mib = [libc::CTL_KERN, libc::KERN_PROCARGS2, pid as c_int];
+        let mut mib = [libc::CTL_KERN, libc::KERN_PROCARGS2, pid.0 as _];
         /*
          * /---------------\ 0x00000000
          * | ::::::::::::: |
@@ -521,8 +521,8 @@ pub(crate) fn update_process(
             }
 
             let (environ, root) = if exe.is_absolute() {
-                if let Some(parent) = exe.parent() {
-                    get_environ(ptr, cp, size, parent.to_path_buf(), do_nothing)
+                if let Some(parent_path) = exe.parent() {
+                    get_environ(ptr, cp, size, parent_path.to_path_buf(), do_nothing)
                 } else {
                     get_environ(ptr, cp, size, PathBuf::new(), do_something)
                 }
@@ -567,7 +567,7 @@ fn update_proc_disk_activity(p: &mut Process) {
     let mut pidrusage = MaybeUninit::<libc::rusage_info_v2>::uninit();
     let retval = unsafe {
         libc::proc_pid_rusage(
-            p.pid() as c_int,
+            p.pid().0 as _,
             libc::RUSAGE_INFO_V2,
             pidrusage.as_mut_ptr() as _,
         )
diff --git a/src/c_interface.rs b/src/c_interface.rs
index 8cbf2aa..76fecd4 100644
--- a/src/c_interface.rs
+++ b/src/c_interface.rs
@@ -1,6 +1,6 @@
 // Take a look at the license at the top of the repository in the LICENSE file.
 
-use crate::{NetworkExt, NetworksExt, Process, ProcessExt, ProcessorExt, System, SystemExt};
+use crate::{NetworkExt, NetworksExt, Pid, Process, ProcessExt, ProcessorExt, System, SystemExt};
 use libc::{self, c_char, c_float, c_uint, c_void, pid_t, size_t};
 use std::borrow::BorrowMut;
 use std::ffi::CString;
@@ -110,7 +110,7 @@ pub extern "C" fn sysinfo_refresh_process(system: CSystem, pid: pid_t) {
     let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
     {
         let system: &mut System = system.borrow_mut();
-        system.refresh_process(pid);
+        system.refresh_process(Pid(pid));
     }
     Box::into_raw(system);
 }
@@ -276,7 +276,7 @@ pub extern "C" fn sysinfo_get_processes(
         let len = {
             let entries = system.processes();
             for (pid, process) in entries {
-                if !fn_pointer(*pid, process as *const Process as CProcess, data) {
+                if !fn_pointer(pid.0, process as *const Process as CProcess, data) {
                     break;
                 }
             }
@@ -299,7 +299,7 @@ pub extern "C" fn sysinfo_get_processes(
 pub extern "C" fn sysinfo_get_process_by_pid(system: CSystem, pid: pid_t) -> CProcess {
     assert!(!system.is_null());
     let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
-    let ret = if let Some(process) = system.process(pid) {
+    let ret = if let Some(process) = system.process(Pid(pid)) {
         process as *const Process as CProcess
     } else {
         std::ptr::null()
@@ -324,7 +324,7 @@ pub extern "C" fn sysinfo_process_get_tasks(
     if let Some(fn_pointer) = fn_pointer {
         let process = process as *const Process;
         for (pid, process) in unsafe { (*process).tasks.iter() } {
-            if !fn_pointer(*pid, process as *const Process as CProcess, data) {
+            if !fn_pointer(pid.0, process as *const Process as CProcess, data) {
                 break;
             }
         }
@@ -339,7 +339,7 @@ pub extern "C" fn sysinfo_process_get_tasks(
 pub extern "C" fn sysinfo_process_get_pid(process: CProcess) -> pid_t {
     assert!(!process.is_null());
     let process = process as *const Process;
-    unsafe { (*process).pid() }
+    unsafe { (*process).pid().0 }
 }
 
 /// Equivalent of [`Process::parent()`][crate::Process#method.parent].
@@ -349,7 +349,7 @@ pub extern "C" fn sysinfo_process_get_pid(process: CProcess) -> pid_t {
 pub extern "C" fn sysinfo_process_get_parent_pid(process: CProcess) -> pid_t {
     assert!(!process.is_null());
     let process = process as *const Process;
-    unsafe { (*process).parent().unwrap_or(0) }
+    unsafe { (*process).parent().unwrap_or(Pid(0)).0 }
 }
 
 /// Equivalent of [`Process::cpu_usage()`][crate::Process#method.cpu_usage].
diff --git a/src/common.rs b/src/common.rs
index d113d80..2292297 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -2,10 +2,69 @@
 
 use crate::{NetworkData, Networks, NetworksExt, UserExt};
 
-/// Trait to have a common fallback for the [`Pid`][crate::Pid] type.
-pub trait AsU32 {
+use std::convert::From;
+use std::fmt;
+use std::str::FromStr;
+
+/// Trait to have a common conversions for the [`Pid`][crate::Pid] type.
+///
+/// ```
+/// use sysinfo::{Pid, PidExt};
+///
+/// let p = Pid::from_u32(0);
+/// let value: u32 = p.as_u32();
+/// ```
+pub trait PidExt<T>: Copy + From<T> + FromStr + fmt::Display {
     /// Allows to convert [`Pid`][crate::Pid] into [`u32`].
-    fn as_u32(&self) -> u32;
+    ///
+    /// ```
+    /// use sysinfo::{Pid, PidExt};
+    ///
+    /// let p = Pid::from_u32(0);
+    /// let value: u32 = p.as_u32();
+    /// ```
+    fn as_u32(self) -> u32;
+    /// Allows to convert a [`u32`] into [`Pid`][crate::Pid].
+    ///
+    /// ```
+    /// use sysinfo::{Pid, PidExt};
+    ///
+    /// let p = Pid::from_u32(0);
+    /// ```
+    fn from_u32(v: u32) -> Self;
+}
+
+macro_rules! pid_decl {
+    ($typ:ty) => {
+        #[doc = include_str!("../md_doc/pid.md")]
+        #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
+        pub struct Pid(pub(crate) $typ);
+
+        impl From<$typ> for Pid {
+            fn from(v: $typ) -> Self {
+                Self(v)
+            }
+        }
+        impl PidExt<$typ> for Pid {
+            fn as_u32(self) -> u32 {
+                self.0 as u32
+            }
+            fn from_u32(v: u32) -> Self {
+                Self(v as _)
+            }
+        }
+        impl FromStr for Pid {
+            type Err = <$typ as FromStr>::Err;
+            fn from_str(s: &str) -> Result<Self, Self::Err> {
+                Ok(Self(<$typ>::from_str(s)?))
+            }
+        }
+        impl fmt::Display for Pid {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                write!(f, "{}", self.0)
+            }
+        }
+    };
 }
 
 cfg_if::cfg_if! {
@@ -21,23 +80,9 @@ cfg_if::cfg_if! {
     ))] {
         use libc::pid_t;
 
-        #[doc = include_str!("../md_doc/pid.md")]
-        pub type Pid = pid_t;
-
-        impl AsU32 for Pid {
-            fn as_u32(&self) -> u32 {
-                *self as u32
-            }
-        }
+        pid_decl!(pid_t);
     } else {
-        #[doc = include_str!("../md_doc/pid.md")]
-        pub type Pid = usize;
-
-        impl AsU32 for Pid {
-            fn as_u32(&self) -> u32 {
-                *self as u32
-            }
-        }
+        pid_decl!(usize);
     }
 }
 
@@ -775,13 +820,13 @@ pub fn get_current_pid() -> Result<Pid, &'static str> {
             target_os = "ios",
         ))] {
             fn inner() -> Result<Pid, &'static str> {
-                unsafe { Ok(libc::getpid()) }
+                unsafe { Ok(Pid(libc::getpid())) }
             }
         } else if #[cfg(windows)] {
             fn inner() -> Result<Pid, &'static str> {
                 use winapi::um::processthreadsapi::GetCurrentProcessId;
 
-                unsafe { Ok(GetCurrentProcessId() as Pid) }
+                unsafe { Ok(Pid(GetCurrentProcessId() as _)) }
             }
         } else {
             fn inner() -> Result<Pid, &'static str> {
diff --git a/src/freebsd/process.rs b/src/freebsd/process.rs
index d5419de..e5828f2 100644
--- a/src/freebsd/process.rs
+++ b/src/freebsd/process.rs
@@ -68,7 +68,7 @@ pub struct Process {
 impl ProcessExt for Process {
     fn kill_with(&self, signal: Signal) -> Option<bool> {
         let c_signal = super::system::convert_signal(signal)?;
-        unsafe { Some(libc::kill(self.pid, c_signal) == 0) }
+        unsafe { Some(libc::kill(self.pid.0, c_signal) == 0) }
     }
 
     fn name(&self) -> &str {
@@ -158,7 +158,7 @@ pub(crate) unsafe fn get_process_data(
     };
     // Processes can be reparented apparently?
     let parent = if kproc.ki_ppid != 0 {
-        Some(kproc.ki_ppid)
+        Some(Pid(kproc.ki_ppid))
     } else {
         None
     };
@@ -170,7 +170,7 @@ pub(crate) unsafe fn get_process_data(
     // FIXME: This is to get the "real" run time (in micro-seconds).
     // let run_time = (kproc.ki_runtime + 5_000) / 10_000;
 
-    if let Some(proc_) = (*wrap.0.get()).get_mut(&kproc.ki_pid) {
+    if let Some(proc_) = (*wrap.0.get()).get_mut(&Pid(kproc.ki_pid)) {
         proc_.cpu_usage = cpu_usage;
         proc_.parent = parent;
         proc_.status = status;
@@ -218,7 +218,7 @@ pub(crate) unsafe fn get_process_data(
 
     let start_time = kproc.ki_start.tv_sec as u64;
     Some(Process {
-        pid: kproc.ki_pid,
+        pid: Pid(kproc.ki_pid),
         parent,
         uid: kproc.ki_ruid,
         gid: kproc.ki_rgid,
diff --git a/src/freebsd/system.rs b/src/freebsd/system.rs
index 41aca65..def5a62 100644
--- a/src/freebsd/system.rs
+++ b/src/freebsd/system.rs
@@ -169,26 +169,28 @@ impl SystemExt for System {
             #[cfg(feature = "multithread")]
             use rayon::iter::ParallelIterator;
 
-            let iter = crate::utils::into_iter(procs);
-            #[cfg(not(feature = "multithread"))]
-            {
-                iter.find(|kproc| kproc.ki_pid == pid)
+            macro_rules! multi_iter {
+                ($name:ident, $($iter:tt)+) => {
+                    $name = crate::utils::into_iter(procs).$($iter)+.and_then(|kproc| {
+                        super::process::get_process_data(
+                            kproc.0,
+                            &proc_list,
+                            page_size,
+                            fscale,
+                            now,
+                            refresh_kind,
+                        )
+                        .map(|p| (kproc, p))
+                    });
+                }
             }
+
+            let ret;
+            #[cfg(not(feature = "multithread"))]
+            multi_iter!(ret, find(|kproc| kproc.0.ki_pid == pid.0));
             #[cfg(feature = "multithread")]
-            { iter.find_any(|kproc| kproc.0.ki_pid == pid) }
-                // Yep, this `and_then is called on what's returned by the `find` from above...
-                // (I mostly added this comment because rustfmt is acting weird in here.)
-                .and_then(|kproc| {
-                    super::process::get_process_data(
-                        kproc.0,
-                        &proc_list,
-                        page_size,
-                        fscale,
-                        now,
-                        refresh_kind,
-                    )
-                    .map(|p| (kproc, p))
-                })
+            multi_iter!(ret, find_any(|kproc| kproc.0.ki_pid == pid.0));
+            ret
         };
         if let Some((kproc, proc_)) = res {
             unsafe {
diff --git a/src/lib.rs b/src/lib.rs
index 66090bf..16343c8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -59,7 +59,7 @@ cfg_if::cfg_if! {
 }
 
 pub use common::{
-    get_current_pid, AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid,
+    get_current_pid, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, PidExt,
     ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, Uid, User,
 };
 pub use sys::{Component, Disk, NetworkData, Networks, Process, Processor, System};
diff --git a/src/linux/process.rs b/src/linux/process.rs
index fb31e63..4201f7f 100644
--- a/src/linux/process.rs
+++ b/src/linux/process.rs
@@ -124,7 +124,7 @@ impl Process {
             uid: 0,
             gid: 0,
             status: ProcessStatus::Unknown(0),
-            tasks: if pid == 0 {
+            tasks: if pid.0 == 0 {
                 HashMap::with_capacity(1000)
             } else {
                 HashMap::new()
@@ -141,7 +141,7 @@ impl Process {
 impl ProcessExt for Process {
     fn kill_with(&self, signal: Signal) -> Option<bool> {
         let c_signal = super::system::convert_signal(signal)?;
-        unsafe { Some(kill(self.pid, c_signal) == 0) }
+        unsafe { Some(kill(self.pid.0, c_signal) == 0) }
     }
 
     fn name(&self) -> &str {
@@ -352,11 +352,11 @@ pub(crate) fn _get_process_data(
     let parts = parse_stat_file(&data)?;
     let name = parts[1];
 
-    let parent_pid = if proc_list.pid != 0 {
+    let parent_pid = if proc_list.pid.0 != 0 {
         Some(proc_list.pid)
     } else {
         match Pid::from_str(parts[3]) {
-            Ok(p) if p != 0 => Some(p),
+            Ok(p) if p.0 != 0 => Some(p),
             _ => None,
         }
     };
@@ -376,7 +376,7 @@ pub(crate) fn _get_process_data(
         }
     }
 
-    if proc_list.pid != 0 {
+    if proc_list.pid.0 != 0 {
         // If we're getting information for a child, no need to get those info since we
         // already have them...
         p.cmd = proc_list.cmd.clone();
@@ -498,7 +498,7 @@ pub(crate) fn refresh_procs(
                 }
             })
             .collect::<Vec<_>>();
-        if pid == 0 {
+        if pid.0 == 0 {
             let proc_list = Wrap(UnsafeCell::new(proc_list));
 
             #[cfg(feature = "multithread")]
diff --git a/src/linux/system.rs b/src/linux/system.rs
index ad2209b..fbd32b1 100644
--- a/src/linux/system.rs
+++ b/src/linux/system.rs
@@ -312,7 +312,7 @@ impl SystemExt for System {
 
     fn new_with_specifics(refreshes: RefreshKind) -> System {
         let mut s = System {
-            process_list: Process::new(0, None, 0),
+            process_list: Process::new(Pid(0), None, 0),
             mem_total: 0,
             mem_free: 0,
             mem_available: 0,
@@ -390,7 +390,7 @@ impl SystemExt for System {
             &mut self.process_list,
             Path::new("/proc"),
             self.page_size_kb,
-            0,
+            Pid(0),
             uptime,
             self.clock_cycle,
             refresh_kind,
@@ -406,7 +406,7 @@ impl SystemExt for System {
             &Path::new("/proc/").join(pid.to_string()),
             &mut self.process_list,
             self.page_size_kb,
-            0,
+            Pid(0),
             uptime,
             self.clock_cycle,
             refresh_kind,
diff --git a/src/traits.rs b/src/traits.rs
index 2bb5467..d51bd50 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -133,10 +133,10 @@ pub trait ProcessExt: Debug {
     /// [`SystemExt::SUPPORTED_SIGNALS`].
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     process.kill();
     /// }
     /// ```
@@ -154,10 +154,10 @@ pub trait ProcessExt: Debug {
     /// [`SystemExt::SUPPORTED_SIGNALS`].
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, Signal, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, Signal, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     if process.kill_with(Signal::Kill).is_none() {
     ///         eprintln!("This signal isn't supported on this platform");
     ///     }
@@ -177,10 +177,10 @@ pub trait ProcessExt: Debug {
     /// cases it's better to use [`ProcessExt::exe`] instead (which can be empty sometimes!).
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{}", process.name());
     /// }
     /// ```
@@ -189,10 +189,10 @@ pub trait ProcessExt: Debug {
     /// Returns the command line.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{:?}", process.cmd());
     /// }
     /// ```
@@ -201,10 +201,10 @@ pub trait ProcessExt: Debug {
     /// Returns the path to the process.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{}", process.exe().display());
     /// }
     /// ```
@@ -213,10 +213,10 @@ pub trait ProcessExt: Debug {
     /// Returns the pid of the process.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{}", process.pid());
     /// }
     /// ```
@@ -225,10 +225,10 @@ pub trait ProcessExt: Debug {
     /// Returns the environment variables of the process.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{:?}", process.environ());
     /// }
     /// ```
@@ -237,10 +237,10 @@ pub trait ProcessExt: Debug {
     /// Returns the current working directory.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{}", process.cwd().display());
     /// }
     /// ```
@@ -249,10 +249,10 @@ pub trait ProcessExt: Debug {
     /// Returns the path of the root directory.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{}", process.root().display());
     /// }
     /// ```
@@ -261,10 +261,10 @@ pub trait ProcessExt: Debug {
     /// Returns the memory usage (in KB).
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{} KB", process.memory());
     /// }
     /// ```
@@ -273,10 +273,10 @@ pub trait ProcessExt: Debug {
     /// Returns the virtual memory usage (in KB).
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{} KB", process.virtual_memory());
     /// }
     /// ```
@@ -285,10 +285,10 @@ pub trait ProcessExt: Debug {
     /// Returns the parent pid.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{:?}", process.parent());
     /// }
     /// ```
@@ -297,10 +297,10 @@ pub trait ProcessExt: Debug {
     /// Returns the status of the processus.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{:?}", process.status());
     /// }
     /// ```
@@ -309,10 +309,10 @@ pub trait ProcessExt: Debug {
     /// Returns the time where the process was started (in seconds) from epoch.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("Started at {} seconds", process.start_time());
     /// }
     /// ```
@@ -321,10 +321,10 @@ pub trait ProcessExt: Debug {
     /// Returns for how much time the process has been running (in seconds).
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("Running since {} seconds", process.run_time());
     /// }
     /// ```
@@ -340,10 +340,10 @@ pub trait ProcessExt: Debug {
     /// between two calls of this method (200 ms for example).
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{}%", process.cpu_usage());
     /// }
     /// ```
@@ -354,10 +354,10 @@ pub trait ProcessExt: Debug {
     /// ⚠️ On Windows and FreeBSD, this method actually returns **ALL** I/O read and written bytes.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     let disk_usage = process.disk_usage();
     ///     println!("read bytes   : new/total => {}/{}",
     ///         disk_usage.read_bytes,
@@ -666,10 +666,10 @@ pub trait SystemExt: Sized + Debug + Default + Send + Sync {
     /// `sys.refresh_process_specifics(pid, ProcessRefreshKind::everything())`.
     ///
     /// ```no_run
-    /// use sysinfo::{System, SystemExt};
+    /// use sysinfo::{Pid, System, SystemExt};
     ///
     /// let mut s = System::new_all();
-    /// s.refresh_process(1337);
+    /// s.refresh_process(Pid::from(1337));
     /// ```
     fn refresh_process(&mut self, pid: Pid) -> bool {
         self.refresh_process_specifics(pid, ProcessRefreshKind::everything())
@@ -679,10 +679,10 @@ pub trait SystemExt: Sized + Debug + Default + Send + Sync {
     /// exist. If it isn't listed yet, it'll be added.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessRefreshKind, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessRefreshKind, System, SystemExt};
     ///
     /// let mut s = System::new_all();
-    /// s.refresh_process_specifics(1337, ProcessRefreshKind::new());
+    /// s.refresh_process_specifics(Pid::from(1337), ProcessRefreshKind::new());
     /// ```
     fn refresh_process_specifics(&mut self, pid: Pid, refresh_kind: ProcessRefreshKind) -> bool;
 
@@ -798,10 +798,10 @@ pub trait SystemExt: Sized + Debug + Default + Send + Sync {
     /// Returns the process corresponding to the given pid or `None` if no such process exists.
     ///
     /// ```no_run
-    /// use sysinfo::{ProcessExt, System, SystemExt};
+    /// use sysinfo::{Pid, ProcessExt, System, SystemExt};
     ///
     /// let s = System::new_all();
-    /// if let Some(process) = s.process(1337) {
+    /// if let Some(process) = s.process(Pid::from(1337)) {
     ///     println!("{}", process.name());
     /// }
     /// ```
diff --git a/src/windows/process.rs b/src/windows/process.rs
index 91d76e0..0346941 100644
--- a/src/windows/process.rs
+++ b/src/windows/process.rs
@@ -53,11 +53,11 @@ impl fmt::Display for ProcessStatus {
 }
 
 fn get_process_handler(pid: Pid) -> Option<HANDLE> {
-    if pid == 0 {
+    if pid.0 == 0 {
         return None;
     }
     let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
-    let process_handler = unsafe { OpenProcess(options, FALSE, pid as DWORD) };
+    let process_handler = unsafe { OpenProcess(options, FALSE, pid.0 as DWORD) };
     if process_handler.is_null() {
         None
     } else {
@@ -175,7 +175,7 @@ unsafe fn get_exe(process_handler: HANDLE, h_mod: *mut c_void) -> PathBuf {
 impl Process {
     #[allow(clippy::uninit_assumed_init)]
     pub(crate) fn new_from_pid(pid: Pid, now: u64) -> Option<Process> {
-        let process_handler = unsafe { OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as _) };
+        let process_handler = unsafe { OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid.0 as _) };
         if process_handler.is_null() {
             return None;
         }
@@ -196,7 +196,7 @@ impl Process {
         Some(Process::new_with_handle(
             pid,
             if info.InheritedFromUniqueProcessId as usize != 0 {
-                Some(info.InheritedFromUniqueProcessId as usize)
+                Some(Pid(info.InheritedFromUniqueProcessId as _))
             } else {
                 None
             },
diff --git a/src/windows/system.rs b/src/windows/system.rs
index 11d0d55..605c278 100644
--- a/src/windows/system.rs
+++ b/src/windows/system.rs
@@ -47,7 +47,7 @@ declare_signals! {
 
 #[doc = include_str!("../../md_doc/system.md")]
 pub struct System {
-    process_list: HashMap<usize, Process>,
+    process_list: HashMap<Pid, Process>,
     mem_total: u64,
     mem_available: u64,
     swap_total: u64,
@@ -265,7 +265,7 @@ impl SystemExt for System {
                 let processes = into_iter(process_ids)
                     .filter_map(|pi| unsafe {
                         let pi = *pi.0;
-                        let pid = pi.UniqueProcessId as usize;
+                        let pid = Pid(pi.UniqueProcessId as _);
                         if let Some(proc_) = (*process_list.0.get()).get_mut(&pid) {
                             proc_.memory = (pi.WorkingSetSize as u64) / 1_000;
                             proc_.virtual_memory = (pi.VirtualSize as u64) / 1_000;
@@ -276,7 +276,7 @@ impl SystemExt for System {
                         let mut p = Process::new_full(
                             pid,
                             if pi.InheritedFromUniqueProcessId as usize != 0 {
-                                Some(pi.InheritedFromUniqueProcessId as usize)
+                                Some(Pid(pi.InheritedFromUniqueProcessId as _))
                             } else {
                                 None
                             },
@@ -325,7 +325,7 @@ impl SystemExt for System {
     }
 
     fn process(&self, pid: Pid) -> Option<&Process> {
-        self.process_list.get(&(pid as usize))
+        self.process_list.get(&pid)
     }
 
     fn global_processor_info(&self) -> &Processor {
@@ -467,7 +467,7 @@ fn is_proc_running(handle: HANDLE) -> bool {
 }
 
 fn refresh_existing_process(s: &mut System, pid: Pid, refresh_kind: ProcessRefreshKind) -> bool {
-    if let Some(ref mut entry) = s.process_list.get_mut(&(pid as usize)) {
+    if let Some(ref mut entry) = s.process_list.get_mut(&pid) {
         if !is_proc_running(get_handle(entry)) {
             return false;
         }
@@ -481,10 +481,10 @@ fn refresh_existing_process(s: &mut System, pid: Pid, refresh_kind: ProcessRefre
 
 #[allow(clippy::size_of_in_element_count)]
 //^ needed for "name.Length as usize / std::mem::size_of::<u16>()"
-pub(crate) fn get_process_name(process: &SYSTEM_PROCESS_INFORMATION, process_id: usize) -> String {
+pub(crate) fn get_process_name(process: &SYSTEM_PROCESS_INFORMATION, process_id: Pid) -> String {
     let name = &process.ImageName;
     if name.Buffer.is_null() {
-        match process_id {
+        match process_id.0 {
             0 => "Idle".to_owned(),
             4 => "System".to_owned(),
             _ => format!("<no name> Process {}", process_id),


Test patch:
diff --git a/tests/process.rs b/tests/process.rs
index 3ec105c..7c689fa 100644
--- a/tests/process.rs
+++ b/tests/process.rs
@@ -1,7 +1,6 @@
 // Take a look at the license at the top of the repository in the LICENSE file.
 
-use sysinfo::ProcessExt;
-use sysinfo::SystemExt;
+use sysinfo::{Pid, PidExt, ProcessExt, SystemExt};
 
 #[test]
 fn test_process() {
@@ -40,7 +39,7 @@ fn test_cwd() {
             .unwrap()
     };
 
-    let pid = p.id() as sysinfo::Pid;
+    let pid = Pid::from_u32(p.id() as u32);
     std::thread::sleep(std::time::Duration::from_secs(1));
     let mut s = sysinfo::System::new();
     s.refresh_processes();
@@ -83,7 +82,7 @@ fn test_cmd() {
     s.refresh_processes();
     p.kill().expect("Unable to kill process.");
     assert!(!s.processes().is_empty());
-    if let Some(process) = s.process(p.id() as sysinfo::Pid) {
+    if let Some(process) = s.process(Pid::from_u32(p.id() as u32)) {
         if cfg!(target_os = "windows") {
             // Sometimes, we get the full path instead for some reasons... So just in case,
             // we check for the command independently that from the arguments.
@@ -122,7 +121,7 @@ fn test_environ() {
             .unwrap()
     };
 
-    let pid = p.id() as sysinfo::Pid;
+    let pid = Pid::from_u32(p.id() as u32);
     std::thread::sleep(std::time::Duration::from_secs(1));
     let mut s = sysinfo::System::new();
     s.refresh_processes();
@@ -265,7 +264,7 @@ fn test_process_times() {
             .unwrap()
     };
 
-    let pid = p.id() as sysinfo::Pid;
+    let pid = Pid::from_u32(p.id() as u32);
     std::thread::sleep(std::time::Duration::from_secs(1));
     let mut s = sysinfo::System::new();
     s.refresh_processes();