42
42
extern crate alloc;
43
43
44
44
use alloc:: sync:: Arc ;
45
- use core:: { fmt:: Debug , marker:: PhantomData , mem:: MaybeUninit , ops:: Deref , sync:: atomic:: Ordering } ;
45
+ use core:: {
46
+ any:: TypeId , fmt:: Debug , marker:: PhantomData , mem:: MaybeUninit , ops:: Deref ,
47
+ sync:: atomic:: Ordering ,
48
+ } ;
46
49
use iceoryx2_bb_elementary:: zero_copy_send:: ZeroCopySend ;
47
50
use iceoryx2_pal_concurrency_sync:: iox_atomic:: IoxAtomicUsize ;
48
51
49
52
use iceoryx2_bb_log:: { error, fail} ;
50
53
use iceoryx2_bb_posix:: unique_system_id:: UniqueSystemId ;
51
- use iceoryx2_cal:: zero_copy_connection:: { ChannelId , ZeroCopyReceiver , ZeroCopyReleaseError } ;
54
+ use iceoryx2_cal:: {
55
+ shm_allocator:: AllocationStrategy ,
56
+ zero_copy_connection:: { ChannelId , ZeroCopyReceiver , ZeroCopyReleaseError } ,
57
+ } ;
52
58
53
59
use crate :: {
54
60
port:: {
@@ -60,7 +66,10 @@ use crate::{
60
66
raw_sample:: { RawSample , RawSampleMut } ,
61
67
response_mut:: ResponseMut ,
62
68
response_mut_uninit:: ResponseMutUninit ,
63
- service:: { self , builder:: publish_subscribe:: CustomPayloadMarker } ,
69
+ service:: {
70
+ self , builder:: publish_subscribe:: CustomPayloadMarker ,
71
+ static_config:: message_type_details:: TypeVariant ,
72
+ } ,
64
73
} ;
65
74
66
75
/// Represents a one-to-one connection to a [`Client`](crate::port::client::Client)
@@ -217,6 +226,28 @@ impl<
217
226
pub fn origin ( & self ) -> UniqueClientId {
218
227
UniqueClientId ( UniqueSystemId :: from ( self . details . origin ) )
219
228
}
229
+
230
+ fn increment_loan_counter ( & self ) -> Result < ( ) , LoanError > {
231
+ let mut current_loan_count = self . shared_loan_counter . load ( Ordering :: Relaxed ) ;
232
+ loop {
233
+ if self . max_loan_count <= current_loan_count {
234
+ fail ! ( from self ,
235
+ with LoanError :: ExceedsMaxLoans ,
236
+ "Unable to loan memory for Response since it would exceed the maximum number of loans of {}." ,
237
+ self . max_loan_count) ;
238
+ }
239
+
240
+ match self . shared_loan_counter . compare_exchange (
241
+ current_loan_count,
242
+ current_loan_count + 1 ,
243
+ Ordering :: Relaxed ,
244
+ Ordering :: Relaxed ,
245
+ ) {
246
+ Ok ( _) => return Ok ( ( ) ) ,
247
+ Err ( v) => current_loan_count = v,
248
+ }
249
+ }
250
+ }
220
251
}
221
252
222
253
////////////////////////
@@ -259,25 +290,7 @@ impl<
259
290
& self ,
260
291
) -> Result < ResponseMutUninit < Service , MaybeUninit < ResponsePayload > , ResponseHeader > , LoanError >
261
292
{
262
- let mut current_loan_count = self . shared_loan_counter . load ( Ordering :: Relaxed ) ;
263
- loop {
264
- if self . max_loan_count <= current_loan_count {
265
- fail ! ( from self ,
266
- with LoanError :: ExceedsMaxLoans ,
267
- "Unable to loan memory for Response since it would exceed the maximum number of loans of {}." ,
268
- self . max_loan_count) ;
269
- }
270
-
271
- match self . shared_loan_counter . compare_exchange (
272
- current_loan_count,
273
- current_loan_count + 1 ,
274
- Ordering :: Relaxed ,
275
- Ordering :: Relaxed ,
276
- ) {
277
- Ok ( _) => break ,
278
- Err ( v) => current_loan_count = v,
279
- }
280
- }
293
+ self . increment_loan_counter ( ) ?;
281
294
282
295
let chunk = self
283
296
. shared_state
@@ -412,32 +425,100 @@ impl<
412
425
Service : crate :: service:: Service ,
413
426
RequestPayload : Debug + ZeroCopySend + ?Sized ,
414
427
RequestHeader : Debug + ZeroCopySend ,
415
- ResponsePayload : Debug + Default + ZeroCopySend ,
428
+ ResponsePayload : Debug + Default + ZeroCopySend + ' static ,
416
429
ResponseHeader : Debug + ZeroCopySend ,
417
430
> ActiveRequest < Service , RequestPayload , RequestHeader , [ ResponsePayload ] , ResponseHeader >
418
431
{
419
432
pub fn loan_slice (
420
433
& self ,
421
- number_of_elements : usize ,
434
+ slice_len : usize ,
422
435
) -> Result < ResponseMut < Service , [ ResponsePayload ] , ResponseHeader > , LoanError > {
423
- todo ! ( )
436
+ let response = self . loan_slice_uninit ( slice_len) ?;
437
+ Ok ( response. write_from_fn ( |_| ResponsePayload :: default ( ) ) )
424
438
}
425
439
}
426
440
427
441
impl <
428
442
Service : crate :: service:: Service ,
429
443
RequestPayload : Debug + ZeroCopySend + ?Sized ,
430
444
RequestHeader : Debug + ZeroCopySend ,
431
- ResponsePayload : Debug + ZeroCopySend ,
445
+ ResponsePayload : Debug + ZeroCopySend + ' static ,
432
446
ResponseHeader : Debug + ZeroCopySend ,
433
447
> ActiveRequest < Service , RequestPayload , RequestHeader , [ ResponsePayload ] , ResponseHeader >
434
448
{
435
449
pub fn loan_slice_uninit (
436
450
& self ,
437
- number_of_elements : usize ,
451
+ slice_len : usize ,
438
452
) -> Result < ResponseMutUninit < Service , [ MaybeUninit < ResponsePayload > ] , ResponseHeader > , LoanError >
439
453
{
440
- todo ! ( )
454
+ debug_assert ! ( TypeId :: of:: <ResponsePayload >( ) != TypeId :: of:: <CustomPayloadMarker >( ) ) ;
455
+ unsafe { self . loan_slice_uninit_impl ( slice_len, slice_len) }
456
+ }
457
+
458
+ unsafe fn loan_slice_uninit_impl (
459
+ & self ,
460
+ slice_len : usize ,
461
+ underlying_number_of_slice_elements : usize ,
462
+ ) -> Result < ResponseMutUninit < Service , [ MaybeUninit < ResponsePayload > ] , ResponseHeader > , LoanError >
463
+ {
464
+ let max_slice_len = self . shared_state . config . initial_max_slice_len ;
465
+
466
+ if self . shared_state . config . allocation_strategy == AllocationStrategy :: Static
467
+ && max_slice_len < slice_len
468
+ {
469
+ fail ! ( from self , with LoanError :: ExceedsMaxLoanSize ,
470
+ "Unable to loan slice with {} elements since it would exceed the max supported slice length of {}." ,
471
+ slice_len, max_slice_len) ;
472
+ }
473
+
474
+ self . increment_loan_counter ( ) ?;
475
+
476
+ let response_layout = self . shared_state . response_sender . sample_layout ( slice_len) ;
477
+ let chunk = self
478
+ . shared_state
479
+ . response_sender
480
+ . allocate ( response_layout) ?;
481
+
482
+ unsafe {
483
+ ( chunk. header as * mut service:: header:: request_response:: ResponseHeader ) . write (
484
+ service:: header:: request_response:: ResponseHeader {
485
+ server_port_id : UniqueServerId ( UniqueSystemId :: from (
486
+ self . shared_state . response_sender . sender_port_id ,
487
+ ) ) ,
488
+ request_id : self . request_id ,
489
+ number_of_elements : slice_len as _ ,
490
+ } ,
491
+ )
492
+ } ;
493
+
494
+ let ptr = unsafe {
495
+ RawSampleMut :: <
496
+ service:: header:: request_response:: ResponseHeader ,
497
+ ResponseHeader ,
498
+ [ MaybeUninit < ResponsePayload > ] ,
499
+ > :: new_unchecked (
500
+ chunk. header . cast ( ) ,
501
+ chunk. user_header . cast ( ) ,
502
+ core:: slice:: from_raw_parts_mut (
503
+ chunk. payload . cast ( ) ,
504
+ underlying_number_of_slice_elements,
505
+ ) ,
506
+ )
507
+ } ;
508
+
509
+ Ok ( ResponseMutUninit {
510
+ response : ResponseMut {
511
+ ptr,
512
+ shared_loan_counter : self . shared_loan_counter . clone ( ) ,
513
+ shared_state : self . shared_state . clone ( ) ,
514
+ offset_to_chunk : chunk. offset ,
515
+ channel_id : self . channel_id ,
516
+ connection_id : self . connection_id ,
517
+ sample_size : chunk. size ,
518
+ _response_payload : PhantomData ,
519
+ _response_header : PhantomData ,
520
+ } ,
521
+ } )
441
522
}
442
523
}
443
524
@@ -462,7 +543,16 @@ impl<
462
543
ResponseMutUninit < Service , [ MaybeUninit < CustomPayloadMarker > ] , ResponseHeader > ,
463
544
LoanError ,
464
545
> {
465
- todo ! ( )
546
+ // TypeVariant::Dynamic == slice and only here it makes sense to loan more than one element
547
+ debug_assert ! (
548
+ slice_len == 1
549
+ || self . shared_state. response_sender. payload_type_variant( ) == TypeVariant :: Dynamic
550
+ ) ;
551
+
552
+ self . loan_slice_uninit_impl (
553
+ slice_len,
554
+ self . shared_state . response_sender . payload_size ( ) * slice_len,
555
+ )
466
556
}
467
557
}
468
558
////////////////////////
0 commit comments