Skip to content

Commit 76e2c64

Browse files
authored
Implement Sync for IpcSender (#415)
* Implement Sync for `IpcSender` Our queue is a multi-producer queue, which by definition must support concurrent sending. Both crossbeam and the std::sync::mpsc queue (since Rust 1.72) implement Sync, hence there is no reason not to implement this anymore. Related zulip discussion: https://servo.zulipchat.com/#narrow/channel/263398-general/topic/Implement.20Sync.20for.20.60IpcSender.60/with/539930964 * fix unused_import
1 parent c8d07cf commit 76e2c64

File tree

8 files changed

+37
-48
lines changed

8 files changed

+37
-48
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ipc-channel"
3-
version = "0.20.1"
3+
version = "0.20.2"
44
description = "A multiprocess drop-in replacement for Rust channels"
55
authors = ["The Servo Project Developers"]
66
license = "MIT OR Apache-2.0"

src/platform/inprocess/mod.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use std::ptr::eq;
2121
use std::slice;
2222
use std::sync::{Arc, LazyLock, Mutex};
2323
use std::time::Duration;
24-
use usize;
2524
use uuid::Uuid;
2625

2726
#[derive(Clone)]
@@ -124,23 +123,19 @@ impl OsIpcReceiver {
124123

125124
#[derive(Clone, Debug)]
126125
pub struct OsIpcSender {
127-
sender: RefCell<Sender<ChannelMessage>>,
126+
sender: Sender<ChannelMessage>,
128127
}
129128

130129
impl PartialEq for OsIpcSender {
131130
fn eq(&self, other: &OsIpcSender) -> bool {
132-
eq(
133-
&*self.sender.borrow() as *const _,
134-
&*other.sender.borrow() as *const _,
135-
)
131+
// FIXME: this implementation is wrong: https://github.com/servo/ipc-channel/issues/414
132+
eq(&self.sender as *const _, &other.sender as *const _)
136133
}
137134
}
138135

139136
impl OsIpcSender {
140137
fn new(sender: Sender<ChannelMessage>) -> OsIpcSender {
141-
OsIpcSender {
142-
sender: RefCell::new(sender),
143-
}
138+
OsIpcSender { sender }
144139
}
145140

146141
pub fn connect(name: String) -> Result<OsIpcSender, ChannelError> {
@@ -162,7 +157,6 @@ impl OsIpcSender {
162157
let os_ipc_channels = ports.into_iter().map(OsOpaqueIpcChannel::new).collect();
163158
let ipc_message = IpcMessage::new(data.to_vec(), os_ipc_channels, shared_memory_regions);
164159
self.sender
165-
.borrow()
166160
.send(ChannelMessage(ipc_message))
167161
.map_err(|_| ChannelError::BrokenPipeError)
168162
}

src/platform/macos/mod.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use std::error::Error as StdError;
2323
use std::ffi::CString;
2424
use std::fmt::{self, Debug, Formatter};
2525
use std::io;
26-
use std::marker::PhantomData;
2726
use std::mem;
2827
use std::ops::Deref;
2928
use std::ptr;
@@ -392,12 +391,6 @@ impl<'a> SendData<'a> {
392391
#[derive(PartialEq, Debug)]
393392
pub struct OsIpcSender {
394393
port: mach_port_t,
395-
// Make sure this is `!Sync`, to match `crossbeam_channel::Sender`; and to discourage sharing
396-
// references.
397-
//
398-
// (Rather, senders should just be cloned, as they are shared internally anyway --
399-
// another layer of sharing only adds unnecessary overhead...)
400-
nosync_marker: PhantomData<Cell<()>>,
401394
}
402395

403396
impl Drop for OsIpcSender {
@@ -419,19 +412,13 @@ impl Clone for OsIpcSender {
419412
Err(error) => panic!("mach_port_mod_refs(1, {}) failed: {:?}", cloned_port, error),
420413
}
421414
}
422-
OsIpcSender {
423-
port: cloned_port,
424-
nosync_marker: PhantomData,
425-
}
415+
OsIpcSender { port: cloned_port }
426416
}
427417
}
428418

429419
impl OsIpcSender {
430420
fn from_name(port: mach_port_t) -> OsIpcSender {
431-
OsIpcSender {
432-
port,
433-
nosync_marker: PhantomData,
434-
}
421+
OsIpcSender { port }
435422
}
436423

437424
pub fn connect(name: String) -> Result<OsIpcSender, MachError> {
@@ -597,7 +584,6 @@ impl OsOpaqueIpcChannel {
597584
pub fn to_sender(&mut self) -> OsIpcSender {
598585
OsIpcSender {
599586
port: mem::replace(&mut self.port, MACH_PORT_NULL),
600-
nosync_marker: PhantomData,
601587
}
602588
}
603589

src/platform/test.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,11 +1098,18 @@ fn try_recv_large_delayed() {
10981098

10991099
mod sync_test {
11001100
use crate::platform;
1101-
use static_assertions::assert_not_impl_any;
1101+
use static_assertions::{assert_impl_all, assert_not_impl_any};
11021102

11031103
#[test]
11041104
fn receiver_not_sync() {
1105-
assert_not_impl_any!(platform::OsIpcSender : Sync);
1105+
// A single-consumer queue is not Sync.
1106+
assert_not_impl_any!(platform::OsIpcReceiver : Sync);
1107+
}
1108+
1109+
#[test]
1110+
fn sender_is_sync() {
1111+
// A multi-producer queue must be Sync.
1112+
assert_impl_all!(platform::OsIpcSender : Sync);
11061113
}
11071114
}
11081115

src/platform/unix/mod.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use std::ffi::{c_uint, CString};
2929
use std::fmt::{self, Debug, Formatter};
3030
use std::hash::BuildHasherDefault;
3131
use std::io;
32-
use std::marker::PhantomData;
3332
use std::mem;
3433
use std::ops::{Deref, RangeFrom};
3534
use std::os::fd::RawFd;
@@ -185,18 +184,12 @@ impl Drop for SharedFileDescriptor {
185184
#[derive(PartialEq, Debug, Clone)]
186185
pub struct OsIpcSender {
187186
fd: Arc<SharedFileDescriptor>,
188-
// Make sure this is `!Sync`, to match `mpsc::Sender`; and to discourage sharing references.
189-
//
190-
// (Rather, senders should just be cloned, as they are shared internally anyway --
191-
// another layer of sharing only adds unnecessary overhead...)
192-
nosync_marker: PhantomData<Cell<()>>,
193187
}
194188

195189
impl OsIpcSender {
196190
fn from_fd(fd: c_int) -> OsIpcSender {
197191
OsIpcSender {
198192
fd: Arc::new(SharedFileDescriptor(fd)),
199-
nosync_marker: PhantomData,
200193
}
201194
}
202195

src/platform/windows/mod.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ use bincode;
1212
use serde;
1313

1414
use std::{
15-
cell::{Cell, RefCell},
15+
cell::RefCell,
1616
cmp::PartialEq,
1717
convert::TryInto,
1818
env,
1919
ffi::CString,
2020
fmt, io,
21-
marker::{PhantomData, Send, Sync},
21+
marker::{Send, Sync},
2222
mem,
2323
ops::{Deref, DerefMut, RangeFrom},
2424
ptr, slice,
@@ -1291,11 +1291,6 @@ impl OsIpcReceiver {
12911291
#[derive(Debug, PartialEq)]
12921292
pub struct OsIpcSender {
12931293
handle: WinHandle,
1294-
// Make sure this is `!Sync`, to match `mpsc::Sender`; and to discourage sharing references.
1295-
//
1296-
// (Rather, senders should just be cloned, as they are shared internally anyway --
1297-
// another layer of sharing only adds unnecessary overhead...)
1298-
nosync_marker: PhantomData<Cell<()>>,
12991294
}
13001295

13011296
impl Clone for OsIpcSender {
@@ -1315,10 +1310,7 @@ impl OsIpcSender {
13151310
}
13161311

13171312
fn from_handle(handle: WinHandle) -> OsIpcSender {
1318-
OsIpcSender {
1319-
handle,
1320-
nosync_marker: PhantomData,
1321-
}
1313+
OsIpcSender { handle }
13221314
}
13231315

13241316
/// Connect to a pipe server.

src/test.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,3 +750,20 @@ fn test_receiver_stream() {
750750
_ => panic!("Stream should have 5"),
751751
};
752752
}
753+
754+
mod sync_test {
755+
use crate::ipc::{IpcReceiver, IpcSender};
756+
use static_assertions::{assert_impl_all, assert_not_impl_any};
757+
758+
#[test]
759+
fn ipc_receiver_not_sync() {
760+
// A single-consumer queue is not Sync.
761+
assert_not_impl_any!(IpcReceiver<usize> : Sync);
762+
}
763+
764+
#[test]
765+
fn ipc_sender_is_sync() {
766+
// A multi-producer queue must be Sync.
767+
assert_impl_all!(IpcSender<usize> : Sync);
768+
}
769+
}

tests/integration_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::{env, process};
1515
// These integration tests may be run on their own by issuing:
1616
// cargo test --test '*'
1717

18-
/// Test spawing a process which then acts as a client to a
18+
/// Test spawning a process which then acts as a client to a
1919
/// one-shot server in the parent process.
2020
#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))]
2121
#[test]

0 commit comments

Comments
 (0)