@@ -39,6 +39,7 @@ struct THMapAllocatorContext_ {
3939 char * filename ; /* file name */
4040 int flags ;
4141 long size ; /* mapped size */
42+ int fd ;
4243};
4344
4445#define TH_ALLOC_ALIGNMENT 64
@@ -47,21 +48,35 @@ typedef struct {
4748 int refcount ;
4849} THMapInfo ;
4950
51+ char * unknown_filename = "filename not specified" ;
52+
5053THMapAllocatorContext * THMapAllocatorContext_new (const char * filename , int flags )
5154{
5255 THMapAllocatorContext * ctx = THAlloc (sizeof (THMapAllocatorContext ));
5356
54-
5557 if (!(flags & TH_ALLOCATOR_MAPPED_SHARED ) && !(flags & TH_ALLOCATOR_MAPPED_SHAREDMEM ))
5658 flags &= ~TH_ALLOCATOR_MAPPED_NOCREATE ;
5759 if ((flags ^ TH_ALLOCATOR_MAPPED_EXCLUSIVE ) == 0 )
5860 THError ("TH_ALLOCATOR_MAPPED_EXCLUSIVE flag requires opening the file "
5961 "in shared mode" );
6062
61- ctx -> filename = THAlloc (strlen (filename )+ 1 );
62- strcpy (ctx -> filename , filename );
63+ if (filename ) {
64+ ctx -> filename = THAlloc (strlen (filename )+ 1 );
65+ strcpy (ctx -> filename , filename );
66+ } else {
67+ ctx -> filename = unknown_filename ;
68+ }
6369 ctx -> flags = flags ;
6470 ctx -> size = 0 ;
71+ ctx -> fd = -1 ;
72+
73+ return ctx ;
74+ }
75+
76+ THMapAllocatorContext * THMapAllocatorContext_newWithFd (const char * filename , int fd , int flags )
77+ {
78+ THMapAllocatorContext * ctx = THMapAllocatorContext_new (filename , flags );
79+ ctx -> fd = fd ;
6580
6681 return ctx ;
6782}
@@ -71,14 +86,20 @@ char * THMapAllocatorContext_filename(THMapAllocatorContext *ctx)
7186 return ctx -> filename ;
7287}
7388
89+ int THMapAllocatorContext_fd (THMapAllocatorContext * ctx )
90+ {
91+ return ctx -> fd ;
92+ }
93+
7494long THMapAllocatorContext_size (THMapAllocatorContext * ctx )
7595{
7696 return ctx -> size ;
7797}
7898
7999void THMapAllocatorContext_free (THMapAllocatorContext * ctx )
80100{
81- THFree (ctx -> filename );
101+ if (ctx -> filename != unknown_filename )
102+ THFree (ctx -> filename );
82103 THFree (ctx );
83104}
84105
@@ -98,6 +119,10 @@ static void *_map_alloc(void* ctx_, long size)
98119 THError ("exclusive file mapping is not supported on Windows" );
99120 if (ctx -> flags & TH_ALLOCATOR_MAPPED_NOCREATE )
100121 THError ("file mapping without creation is not supported on Windows" );
122+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_KEEPFD )
123+ THError ("TH_ALLOCATOR_MAPPED_KEEPFD not supported on Windows" );
124+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_FROMFD )
125+ THError ("TH_ALLOCATOR_MAPPED_FROMFD not supported on Windows" );
101126
102127 /* open file */
103128 /* FILE_FLAG_RANDOM_ACCESS ? */
@@ -193,9 +218,9 @@ static void *_map_alloc(void* ctx_, long size)
193218 /* open file */
194219 int fd ;
195220 int flags ;
196- long fdsz ;
221+ struct stat file_stat ;
197222
198- if (ctx -> flags )
223+ if (ctx -> flags & ( TH_ALLOCATOR_MAPPED_SHARED | TH_ALLOCATOR_MAPPED_SHAREDMEM ) )
199224 flags = O_RDWR | O_CREAT ;
200225 else
201226 flags = O_RDONLY ;
@@ -205,35 +230,40 @@ static void *_map_alloc(void* ctx_, long size)
205230 if (ctx -> flags & TH_ALLOCATOR_MAPPED_NOCREATE )
206231 flags &= ~O_CREAT ;
207232
208- if (ctx -> flags & TH_ALLOCATOR_MAPPED_SHARED )
209- {
210- if ((fd = open (ctx -> filename , flags , (mode_t )0600 )) == -1 )
211- THError ("unable to open file <%s> in read-write mode" , ctx -> filename );
212- }
213- else if (ctx -> flags & TH_ALLOCATOR_MAPPED_SHAREDMEM )
214- {
233+ if (!(ctx -> flags & TH_ALLOCATOR_MAPPED_FROMFD )) {
234+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_SHARED )
235+ {
236+ if ((fd = open (ctx -> filename , flags , (mode_t )0600 )) == -1 )
237+ THError ("unable to open file <%s> in read-write mode" , ctx -> filename );
238+ }
239+ else if (ctx -> flags & TH_ALLOCATOR_MAPPED_SHAREDMEM )
240+ {
215241#ifdef HAVE_SHM_OPEN
216- if ((fd = shm_open (ctx -> filename , flags , (mode_t )0600 )) == -1 )
217- THError ("unable to open shared memory object <%s> in read-write mode" , ctx -> filename );
242+ if ((fd = shm_open (ctx -> filename , flags , (mode_t )0600 )) == -1 )
243+ THError ("unable to open shared memory object <%s> in read-write mode" , ctx -> filename );
218244#else
219- THError ("unable to open file <%s> in sharedmem mode, shm_open unavailable on this platform" );
245+ THError ("unable to open file <%s> in sharedmem mode, shm_open unavailable on this platform" );
220246#endif
221- }
222- else
223- {
224- if ((fd = open (ctx -> filename , O_RDONLY )) == -1 )
225- THError ("unable to open file <%s> in read-only mode" , ctx -> filename );
247+ }
248+ else
249+ {
250+ if ((fd = open (ctx -> filename , O_RDONLY )) == -1 )
251+ THError ("unable to open file <%s> in read-only mode" , ctx -> filename );
252+ }
253+ } else {
254+ fd = ctx -> fd ;
226255 }
227256
228- if (( fdsz = lseek ( fd , 0 , SEEK_END ) ) == -1 )
257+ if (fstat ( fd , & file_stat ) == -1 )
229258 {
230- close (fd );
231- THError ("unable to seek at end of file <%s>" , ctx -> filename );
259+ if (!(ctx -> flags & TH_ALLOCATOR_MAPPED_FROMFD ))
260+ close (fd );
261+ THError ("unable to stat the file <%s>" , ctx -> filename );
232262 }
233263
234264 if (size > 0 )
235265 {
236- if (size > fdsz )
266+ if (size > file_stat . st_size )
237267 {
238268 if (ctx -> flags )
239269 {
@@ -243,7 +273,7 @@ static void *_map_alloc(void* ctx_, long size)
243273 if (ftruncate (fd , size ) == -1 )
244274 THError ("unable to resize shared memory file <%s> to the right size" , ctx -> filename );
245275 }
246- if (( fdsz = lseek ( fd , size - 1 , SEEK_SET )) == -1 )
276+ if (fstat ( fd , & file_stat ) == -1 || file_stat . st_size < size )
247277 {
248278 close (fd );
249279 THError ("unable to stretch file <%s> to the right size" , ctx -> filename );
@@ -262,18 +292,40 @@ static void *_map_alloc(void* ctx_, long size)
262292 }
263293 }
264294 else
265- size = fdsz ;
295+ size = file_stat . st_size ;
266296
267297 ctx -> size = size ; /* if we are here, it must be the right size */
268298
269299 /* map it */
270- if (ctx -> flags )
300+ if (ctx -> flags & ( TH_ALLOCATOR_MAPPED_SHARED | TH_ALLOCATOR_MAPPED_SHAREDMEM ) )
271301 data = mmap (NULL , ctx -> size , PROT_READ |PROT_WRITE , MAP_SHARED , fd , 0 );
272302 else
273303 data = mmap (NULL , ctx -> size , PROT_READ |PROT_WRITE , MAP_PRIVATE , fd , 0 );
274304
275- if (close (fd ) == -1 )
276- THError ("Error closing file <%s>" , ctx -> filename );
305+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_KEEPFD ) {
306+ ctx -> fd = fd ;
307+ } else {
308+ if (close (fd ) == -1 )
309+ THError ("Error closing file <%s>" , ctx -> filename );
310+ ctx -> fd = -1 ;
311+ }
312+
313+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_UNLINK ) {
314+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_SHAREDMEM )
315+ {
316+ #ifdef HAVE_SHM_UNLINK
317+ if (shm_unlink (ctx -> filename ) == -1 )
318+ THError ("could not unlink the shared memory file %s" , ctx -> filename );
319+ #else
320+ THError ("could not unlink the shared memory file %s, shm_unlink not available on platform" , ctx -> filename );
321+ #endif
322+ }
323+ else
324+ {
325+ if (unlink (ctx -> filename ) == -1 )
326+ THError ("could not unlink file %s" , ctx -> filename );
327+ }
328+ }
277329
278330 if (data == MAP_FAILED )
279331 {
@@ -302,16 +354,25 @@ static void THMapAllocator_free(void* ctx_, void* data) {
302354 if (!UnmapViewOfFile ((LPINT )data ))
303355 THError ("could not unmap the shared memory file" );
304356#else /* _WIN32 */
357+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_KEEPFD ) {
358+ if (close (ctx -> fd ) == -1 )
359+ THError ("could not close file descriptor %d" , ctx -> fd );
360+ }
361+
305362 if (munmap (data , ctx -> size ))
306363 THError ("could not unmap the shared memory file" );
307- if (ctx -> flags & TH_ALLOCATOR_MAPPED_SHAREDMEM )
364+
365+ if (!(ctx -> flags & (TH_ALLOCATOR_MAPPED_FROMFD | TH_ALLOCATOR_MAPPED_UNLINK )))
308366 {
367+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_SHAREDMEM )
368+ {
309369#ifdef HAVE_SHM_UNLINK
310- if (shm_unlink (ctx -> filename ) == -1 )
311- THError ("could not unlink the shared memory file %s" , ctx -> filename );
370+ if (shm_unlink (ctx -> filename ) == -1 )
371+ THError ("could not unlink the shared memory file %s" , ctx -> filename );
312372#else
313- THError ("could not unlink the shared memory file %s, shm_unlink not available on platform" , ctx -> filename );
373+ THError ("could not unlink the shared memory file %s, shm_unlink not available on platform" , ctx -> filename );
314374#endif
375+ }
315376 }
316377#endif /* _WIN32 */
317378
@@ -350,8 +411,14 @@ static void THMapAllocator_free(void* ctx, void* data) {
350411static void * THRefcountedMapAllocator_alloc (void * _ctx , long size ) {
351412 THMapAllocatorContext * ctx = _ctx ;
352413
414+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_FROMFD )
415+ THError ("THRefcountedMapAllocator doesn't support TH_ALLOCATOR_MAPPED_FROMFD flag" );
416+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_KEEPFD )
417+ THError ("THRefcountedMapAllocator doesn't support TH_ALLOCATOR_MAPPED_KEEPFD flag" );
418+ if (ctx -> flags & TH_ALLOCATOR_MAPPED_UNLINK )
419+ THError ("THRefcountedMapAllocator doesn't support TH_ALLOCATOR_MAPPED_UNLINK flag" );
353420 if (!(ctx -> flags & TH_ALLOCATOR_MAPPED_SHAREDMEM ))
354- THError ("THRefcountedMapAllcator requires SHAREDMEM flag" );
421+ THError ("THRefcountedMapAllocator requires TH_ALLOCATOR_MAPPED_SHAREDMEM flag" );
355422
356423 size = size + TH_ALLOC_ALIGNMENT ;
357424 void * ptr = _map_alloc (ctx , size );
0 commit comments