Make rcl_client_t have stable location
This prevents another client initializing at the same location. Therefore preventing conflicts in a trace.
This commit is contained in:
parent
23672cfdb8
commit
e371130cf1
|
|
@ -318,11 +318,10 @@ impl Client_ for UntypedClient_ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_client_helper(
|
pub unsafe fn create_client_helper(
|
||||||
node: *mut rcl_node_t, service_name: &str, service_ts: *const rosidl_service_type_support_t,
|
client_handle: &mut rcl_client_t, node: *mut rcl_node_t, service_name: &str,
|
||||||
qos_profile: QosProfile,
|
service_ts: *const rosidl_service_type_support_t, qos_profile: QosProfile,
|
||||||
) -> Result<rcl_client_t> {
|
) -> Result<()> {
|
||||||
let mut client_handle = unsafe { rcl_get_zero_initialized_client() };
|
|
||||||
let service_name_c_string =
|
let service_name_c_string =
|
||||||
CString::new(service_name).map_err(|_| Error::RCL_RET_INVALID_ARGUMENT)?;
|
CString::new(service_name).map_err(|_| Error::RCL_RET_INVALID_ARGUMENT)?;
|
||||||
|
|
||||||
|
|
@ -330,15 +329,16 @@ pub fn create_client_helper(
|
||||||
let mut client_options = rcl_client_get_default_options();
|
let mut client_options = rcl_client_get_default_options();
|
||||||
client_options.qos = qos_profile.into();
|
client_options.qos = qos_profile.into();
|
||||||
rcl_client_init(
|
rcl_client_init(
|
||||||
&mut client_handle,
|
client_handle,
|
||||||
node,
|
node,
|
||||||
service_ts,
|
service_ts,
|
||||||
service_name_c_string.as_ptr(),
|
service_name_c_string.as_ptr(),
|
||||||
&client_options,
|
&client_options,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if result == RCL_RET_OK as i32 {
|
if result == RCL_RET_OK as i32 {
|
||||||
Ok(client_handle)
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::from_rcl_error(result))
|
Err(Error::from_rcl_error(result))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -849,19 +849,30 @@ impl Node {
|
||||||
where
|
where
|
||||||
T: WrappedServiceTypeSupport,
|
T: WrappedServiceTypeSupport,
|
||||||
{
|
{
|
||||||
let client_handle = create_client_helper(
|
// SAFETY: The `rcl_handle` is zero initialized (partial initialization) in this block.
|
||||||
self.node_handle.as_mut(),
|
let mut client_arc = Arc::new(Mutex::new(TypedClient::<T> {
|
||||||
service_name,
|
rcl_handle: unsafe { rcl_get_zero_initialized_client() },
|
||||||
T::get_ts(),
|
|
||||||
qos_profile,
|
|
||||||
)?;
|
|
||||||
let ws = TypedClient::<T> {
|
|
||||||
rcl_handle: client_handle,
|
|
||||||
response_channels: Vec::new(),
|
response_channels: Vec::new(),
|
||||||
poll_available_channels: Vec::new(),
|
poll_available_channels: Vec::new(),
|
||||||
|
}));
|
||||||
|
let client_ref = Arc::get_mut(&mut client_arc)
|
||||||
|
.unwrap() // No other Arc should exist. The Arc was just created.
|
||||||
|
.get_mut()
|
||||||
|
.unwrap(); // The mutex was just created. It should not be poisoned.
|
||||||
|
|
||||||
|
// SAFETY:
|
||||||
|
// The client was zero initialized above.
|
||||||
|
// Full initialization happens in `create_client_helper`.
|
||||||
|
unsafe {
|
||||||
|
create_client_helper(
|
||||||
|
&mut client_ref.rcl_handle,
|
||||||
|
self.node_handle.as_mut(),
|
||||||
|
service_name,
|
||||||
|
T::get_ts(),
|
||||||
|
qos_profile,
|
||||||
|
)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_arc = Arc::new(Mutex::new(ws));
|
|
||||||
let c = make_client(Arc::downgrade(&client_arc));
|
let c = make_client(Arc::downgrade(&client_arc));
|
||||||
self.clients.push(client_arc);
|
self.clients.push(client_arc);
|
||||||
Ok(c)
|
Ok(c)
|
||||||
|
|
@ -877,20 +888,32 @@ impl Node {
|
||||||
&mut self, service_name: &str, service_type: &str, qos_profile: QosProfile,
|
&mut self, service_name: &str, service_type: &str, qos_profile: QosProfile,
|
||||||
) -> Result<ClientUntyped> {
|
) -> Result<ClientUntyped> {
|
||||||
let service_type = UntypedServiceSupport::new_from(service_type)?;
|
let service_type = UntypedServiceSupport::new_from(service_type)?;
|
||||||
let client_handle = create_client_helper(
|
|
||||||
self.node_handle.as_mut(),
|
// SAFETY: The `rcl_handle` is zero initialized (partial initialization) in this block.
|
||||||
service_name,
|
let mut client_arc = Arc::new(Mutex::new(UntypedClient_ {
|
||||||
service_type.ts,
|
|
||||||
qos_profile,
|
|
||||||
)?;
|
|
||||||
let client = UntypedClient_ {
|
|
||||||
service_type,
|
service_type,
|
||||||
rcl_handle: client_handle,
|
rcl_handle: unsafe { rcl_get_zero_initialized_client() },
|
||||||
response_channels: Vec::new(),
|
response_channels: Vec::new(),
|
||||||
poll_available_channels: Vec::new(),
|
poll_available_channels: Vec::new(),
|
||||||
|
}));
|
||||||
|
let client_ref = Arc::get_mut(&mut client_arc)
|
||||||
|
.unwrap() // No other Arc should exist. The Arc was just created.
|
||||||
|
.get_mut()
|
||||||
|
.unwrap(); // The mutex was just created. It should not be poisoned.
|
||||||
|
|
||||||
|
// SAFETY:
|
||||||
|
// The client was zero initialized above.
|
||||||
|
// Full initialization happens in `create_client_helper`.
|
||||||
|
unsafe {
|
||||||
|
create_client_helper(
|
||||||
|
&mut client_ref.rcl_handle,
|
||||||
|
self.node_handle.as_mut(),
|
||||||
|
service_name,
|
||||||
|
client_ref.service_type.ts,
|
||||||
|
qos_profile,
|
||||||
|
)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_arc = Arc::new(Mutex::new(client));
|
|
||||||
let c = make_untyped_client(Arc::downgrade(&client_arc));
|
let c = make_untyped_client(Arc::downgrade(&client_arc));
|
||||||
self.clients.push(client_arc);
|
self.clients.push(client_arc);
|
||||||
Ok(c)
|
Ok(c)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue