11
11
// SPDX-License-Identifier: Apache-2.0 OR MIT
12
12
13
13
use std:: alloc:: Layout ;
14
+ use std:: cell:: UnsafeCell ;
14
15
use std:: sync:: atomic:: Ordering ;
15
16
use std:: time:: Duration ;
16
17
use std:: { fmt:: Debug , marker:: PhantomData } ;
17
18
18
- use crate :: shared_memory:: ShmPointer ;
19
+ use crate :: shared_memory:: { AllocationStrategy , ShmPointer } ;
19
20
use crate :: shared_memory:: {
20
21
PointerOffset , SharedMemory , SharedMemoryBuilder , SharedMemoryCreateError ,
21
22
SharedMemoryOpenError , ShmAllocator ,
@@ -41,6 +42,8 @@ struct BuilderConfig<Allocator: ShmAllocator, Shm: SharedMemory<Allocator>> {
41
42
base_name : FileName ,
42
43
shm : Shm :: Configuration ,
43
44
allocator_config_hint : Allocator :: Configuration ,
45
+ allocation_strategy : AllocationStrategy ,
46
+ has_ownership : bool ,
44
47
shm_builder_timeout : Duration ,
45
48
max_number_of_chunks_hint : usize ,
46
49
}
@@ -50,7 +53,6 @@ pub struct DynamicBuilder<Allocator: ShmAllocator, Shm: SharedMemory<Allocator>>
50
53
where
51
54
Allocator : Debug ,
52
55
{
53
- builder : Shm :: Builder ,
54
56
config : BuilderConfig < Allocator , Shm > ,
55
57
}
56
58
@@ -63,9 +65,10 @@ impl<Allocator: ShmAllocator, Shm: SharedMemory<Allocator>>
63
65
. push_bytes ( b"__0" )
64
66
. expect ( "Adding __0 results in a valid file name" ) ;
65
67
Self {
66
- builder : Shm :: Builder :: new ( name) ,
67
68
config : BuilderConfig {
68
69
base_name : * name,
70
+ has_ownership : true ,
71
+ allocation_strategy : AllocationStrategy :: default ( ) ,
69
72
shm_builder_timeout : Duration :: ZERO ,
70
73
allocator_config_hint : Allocator :: Configuration :: default ( ) ,
71
74
shm : Shm :: Configuration :: default ( ) ,
92
95
Shm :: Builder : Debug ,
93
96
{
94
97
fn has_ownership ( mut self , value : bool ) -> Self {
95
- self . builder = self . builder . has_ownership ( value) ;
98
+ self . config . has_ownership = value;
96
99
self
97
100
}
98
101
@@ -106,6 +109,11 @@ where
106
109
self
107
110
}
108
111
112
+ fn allocation_strategy ( mut self , value : AllocationStrategy ) -> Self {
113
+ self . config . allocation_strategy = value;
114
+ self
115
+ }
116
+
109
117
fn timeout ( mut self , value : Duration ) -> Self {
110
118
self . config . shm_builder_timeout = value;
111
119
self
@@ -118,10 +126,7 @@ where
118
126
) ;
119
127
120
128
let origin = format ! ( "{:?}" , self ) ;
121
- let shm = fail ! ( from origin, when self
122
- . builder
123
- . size( initial_size)
124
- . create( & self . config. allocator_config_hint) ,
129
+ let shm = fail ! ( from origin, when DynamicMemory :: create_segment( & self . config, 0 , initial_size) ,
125
130
"Unable to create ResizableSharedMemory since the underlying shared memory could not be created." ) ;
126
131
127
132
let mut shared_memory_map = SlotMap :: new ( MAX_DATASEGMENTS ) ;
@@ -130,19 +135,19 @@ where
130
135
. expect ( "MAX_DATASEGMENTS is greater or equal 1" ) ;
131
136
132
137
Ok ( DynamicMemory {
133
- builder_config : self . config ,
134
- shared_memory_map,
135
- current_idx,
138
+ state : UnsafeCell :: new ( InternalState {
139
+ builder_config : self . config ,
140
+ shared_memory_map,
141
+ current_idx,
142
+ } ) ,
136
143
has_ownership : IoxAtomicBool :: new ( true ) ,
137
144
_data : PhantomData ,
138
145
} )
139
146
}
140
147
141
148
fn open ( self ) -> Result < DynamicView < Allocator , Shm > , SharedMemoryOpenError > {
142
149
let origin = format ! ( "{:?}" , self ) ;
143
- let shm = fail ! ( from origin, when self
144
- . builder
145
- . open( ) ,
150
+ let shm = fail ! ( from origin, when DynamicMemory :: open_segment( & self . config, 0 ) ,
146
151
"Unable to open ResizableSharedMemoryView since the underlying shared memory could not be opened." ) ;
147
152
148
153
let mut shared_memory_map = SlotMap :: new ( MAX_DATASEGMENTS ) ;
@@ -191,10 +196,15 @@ impl<Allocator: ShmAllocator, Shm: SharedMemory<Allocator>>
191
196
}
192
197
193
198
#[ derive( Debug ) ]
194
- pub struct DynamicMemory < Allocator : ShmAllocator , Shm : SharedMemory < Allocator > > {
199
+ struct InternalState < Allocator : ShmAllocator , Shm : SharedMemory < Allocator > > {
195
200
builder_config : BuilderConfig < Allocator , Shm > ,
196
201
shared_memory_map : SlotMap < Shm > ,
197
202
current_idx : SlotMapKey ,
203
+ }
204
+
205
+ #[ derive( Debug ) ]
206
+ pub struct DynamicMemory < Allocator : ShmAllocator , Shm : SharedMemory < Allocator > > {
207
+ state : UnsafeCell < InternalState < Allocator , Shm > > ,
198
208
has_ownership : IoxAtomicBool ,
199
209
_data : PhantomData < Allocator > ,
200
210
}
@@ -203,7 +213,7 @@ impl<Allocator: ShmAllocator, Shm: SharedMemory<Allocator>> NamedConcept
203
213
for DynamicMemory < Allocator , Shm >
204
214
{
205
215
fn name ( & self ) -> & FileName {
206
- & self . builder_config . base_name
216
+ unsafe { & ( & * self . state . get ( ) ) . builder_config . base_name }
207
217
}
208
218
}
209
219
@@ -236,8 +246,62 @@ impl<Allocator: ShmAllocator, Shm: SharedMemory<Allocator>> NamedConceptMgmt
236
246
}
237
247
238
248
impl < Allocator : ShmAllocator , Shm : SharedMemory < Allocator > > DynamicMemory < Allocator , Shm > {
239
- fn create_new_segment ( & self , layout : Layout ) -> Result < ( ) , SharedMemoryCreateError > {
240
- todo ! ( )
249
+ fn state_mut ( & self ) -> & mut InternalState < Allocator , Shm > {
250
+ unsafe { & mut * self . state . get ( ) }
251
+ }
252
+
253
+ fn create_segment (
254
+ config : & BuilderConfig < Allocator , Shm > ,
255
+ segment_id : u8 ,
256
+ payload_size : usize ,
257
+ ) -> Result < Shm , SharedMemoryCreateError > {
258
+ Self :: segment_builder ( config, segment_id)
259
+ . size ( payload_size)
260
+ . create ( & config. allocator_config_hint )
261
+ }
262
+
263
+ fn open_segment (
264
+ config : & BuilderConfig < Allocator , Shm > ,
265
+ segment_id : u8 ,
266
+ ) -> Result < Shm , SharedMemoryOpenError > {
267
+ Self :: segment_builder ( config, segment_id) . open ( )
268
+ }
269
+
270
+ fn segment_builder ( config : & BuilderConfig < Allocator , Shm > , segment_id : u8 ) -> Shm :: Builder {
271
+ let msg = "This should never happen! Unable to create additional shared memory segment since it would result in an invalid shared memory name." ;
272
+ let mut adjusted_name = config. base_name ;
273
+ fatal_panic ! ( from config, when adjusted_name. push_bytes( b"__" ) , "{msg}" ) ;
274
+ fatal_panic ! ( from config, when adjusted_name. push_bytes( segment_id. to_string( ) . as_bytes( ) ) , "{msg}" ) ;
275
+ Shm :: Builder :: new ( & adjusted_name)
276
+ . has_ownership ( config. has_ownership )
277
+ . timeout ( config. shm_builder_timeout )
278
+ . config ( & config. shm )
279
+ }
280
+
281
+ fn create_resized_segment (
282
+ & self ,
283
+ shm : & Shm ,
284
+ layout : Layout ,
285
+ segment_id : u8 ,
286
+ ) -> Result < ( ) , SharedMemoryCreateError > {
287
+ let state = self . state_mut ( ) ;
288
+ let adjusted_segment_setup = shm
289
+ . allocator ( )
290
+ . resize_hint ( layout, state. builder_config . allocation_strategy ) ;
291
+ let segment_id = segment_id + 1 ;
292
+
293
+ state. builder_config . allocator_config_hint = adjusted_segment_setup. config ;
294
+ let shm = Self :: create_segment (
295
+ & state. builder_config ,
296
+ segment_id,
297
+ adjusted_segment_setup. payload_size ,
298
+ ) ?;
299
+
300
+ let key = SlotMapKey :: new ( segment_id as usize ) ;
301
+ state. shared_memory_map . insert_at ( key, shm) ;
302
+ state. current_idx = key;
303
+
304
+ Ok ( ( ) )
241
305
}
242
306
}
243
307
@@ -250,12 +314,18 @@ where
250
314
type View = DynamicView < Allocator , Shm > ;
251
315
252
316
fn allocate ( & self , layout : Layout ) -> Result < ShmPointer , ResizableShmAllocationError > {
317
+ let state = self . state_mut ( ) ;
318
+
253
319
loop {
254
- match self . shared_memory_map . get ( self . current_idx ) {
255
- Some ( shm) => match shm. allocate ( layout) {
320
+ match state . shared_memory_map . get ( state . current_idx ) {
321
+ Some ( ref shm) => match shm. allocate ( layout) {
256
322
Ok ( ptr) => return Ok ( ptr) ,
257
323
Err ( ShmAllocationError :: AllocationError ( AllocationError :: OutOfMemory ) ) => {
258
- self . create_new_segment ( layout) ?;
324
+ self . create_resized_segment (
325
+ shm,
326
+ layout,
327
+ state. current_idx . value ( ) as u8 + 1 ,
328
+ ) ?;
259
329
}
260
330
Err ( e) => return Err ( e. into ( ) ) ,
261
331
} ,
@@ -266,7 +336,8 @@ where
266
336
}
267
337
268
338
unsafe fn deallocate ( & self , offset : PointerOffset , layout : Layout ) {
269
- match self . shared_memory_map . get ( self . current_idx ) {
339
+ let state = self . state_mut ( ) ;
340
+ match state. shared_memory_map . get ( state. current_idx ) {
270
341
Some ( shm) => shm. deallocate ( offset, layout) ,
271
342
None => fatal_panic ! ( from self ,
272
343
"This should never happen! Current shared memory segment is not available!" ) ,
0 commit comments