diff --git a/src/engine/filesys.cpp b/src/engine/filesys.cpp index b930d70d09..d6728e0a93 100644 --- a/src/engine/filesys.cpp +++ b/src/engine/filesys.cpp @@ -1,6 +1,6 @@ /* * Copyright 2001-2004 David Abrahams. - * Copyright 2005 Rene Rivera. + * Copyright 2005-2023 René Ferdinand Rivera Morell. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) */ @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef OS_NT #define WIN32_LEAN_AND_MEAN @@ -69,14 +70,20 @@ void file_archive_query_( file_archive_info_t * const ); static void file_archivescan_impl( OBJECT * path, archive_scanback func, void * closure ); static void file_dirscan_impl( OBJECT * dir, scanback func, void * closure ); -static void free_file_archive_info( void * xarchive, void * data ); -static void free_file_info( void * xfile, void * data ); static void remove_files_atexit( void ); +static b2::core::concurrent_hash & filecache() +{ + static b2::core::concurrent_hash cache("file_info"); + return cache; +} -static struct hash * filecache_hash; -static struct hash * archivecache_hash; +static b2::core::concurrent_hash & archivecache() +{ + static b2::core::concurrent_hash cache("file_archive_info"); + return cache; +} /* @@ -90,24 +97,11 @@ static struct hash * archivecache_hash; file_archive_info_t * file_archive_info( OBJECT * const path, int * found ) { OBJECT * path_key = path_as_key( path ); - file_archive_info_t * archive; - - if ( !archivecache_hash ) - archivecache_hash = hashinit( sizeof( file_archive_info_t ), - "file_archive_info" ); - - archive = (file_archive_info_t *)hash_insert( archivecache_hash, path_key, - found ); - - if ( !*found ) - { - archive->name = path_key; - archive->file = 0; - archive->members = FL0; - } - else + auto info = archivecache().get( path_key, file_archive_info_t(path_key) ); + file_archive_info_t * archive = info.first; + if ( info.second ) object_free( path_key ); - + *found = info.second ? 1 : 0; return archive; } @@ -202,17 +196,8 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure ) void file_done() { remove_files_atexit(); - if ( filecache_hash ) - { - hashenumerate( filecache_hash, free_file_info, (void *)0 ); - hashdone( filecache_hash ); - } - - if ( archivecache_hash ) - { - hashenumerate( archivecache_hash, free_file_archive_info, (void *)0 ); - hashdone( archivecache_hash ); - } + filecache().reset(); + archivecache().reset(); } @@ -227,21 +212,11 @@ void file_done() file_info_t * file_info( OBJECT * const path, int * found ) { OBJECT * path_key = path_as_key( path ); - file_info_t * finfo; - - if ( !filecache_hash ) - filecache_hash = hashinit( sizeof( file_info_t ), "file_info" ); - - finfo = (file_info_t *)hash_insert( filecache_hash, path_key, found ); - if ( !*found ) - { - finfo->name = path_key; - finfo->files = L0; - } - else + auto info = filecache().get( path_key, file_info_t(path_key) ); + if ( info.second ) object_free( path_key ); - - return finfo; + *found = info.second ? 1 : 0; + return info.first; } @@ -493,22 +468,6 @@ static void file_dirscan_impl( OBJECT * dir, scanback func, void * closure ) } -static void free_file_archive_info( void * xarchive, void * data ) -{ - file_archive_info_t * const archive = (file_archive_info_t *)xarchive; - - if ( archive ) filelist_free( archive->members ); -} - - -static void free_file_info( void * xfile, void * data ) -{ - file_info_t * const file = (file_info_t *)xfile; - object_free( file->name ); - list_free( file->files ); -} - - static void remove_files_atexit( void ) { LISTITER iter = list_begin( files_to_remove ); @@ -590,7 +549,6 @@ FILELIST * filelist_push_front( FILELIST * list, OBJECT * path ) item->value = b2::jam::make_ptr(); file = item->value; - memset( file, 0, sizeof( *file ) ); file->name = path; file->files = L0; @@ -621,10 +579,7 @@ FILELIST * filelist_pop_front( FILELIST * list ) if ( item ) { if ( item->value ) - { - free_file_info( item->value, 0 ); b2::jam::free_ptr( item->value ); - } list->head = item->next; list->size--; @@ -655,7 +610,7 @@ void filelist_free( FILELIST * list ) int filelist_empty( FILELIST * list ) { - return ( list == FL0 ); + return ( list == nullptr ); } diff --git a/src/engine/filesys.h b/src/engine/filesys.h index 136c446169..682bbfb5c1 100644 --- a/src/engine/filesys.h +++ b/src/engine/filesys.h @@ -4,10 +4,11 @@ * This file is part of Jam - see jam.c for Copyright information. */ -/* This file is ALSO: - * Copyright 2001-2004 David Abrahams. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) +/* This file is ALSO: + * Copyright 2023 René Ferdinand Rivera Morell. + * Copyright 2001-2004 David Abrahams. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) */ /* @@ -24,123 +25,139 @@ #include "pathsys.h" #include "timestamp.h" -#include #include +#include - -typedef struct file_info_t +struct file_info_t { - OBJECT * name; - char is_file; - char is_dir; - char exists; - timestamp time; - LIST * files; -} file_info_t; + OBJECT * name = nullptr; + char is_file = 0; + char is_dir = 0; + char exists = 0; + timestamp time; + LIST * files = L0; + file_info_t() = default; + file_info_t(const file_info_t &) = default; + file_info_t(OBJECT * n) + : name(n) + {} + inline ~file_info_t() + { + if (name != nullptr) object_free(name); + list_free(files); + } +}; typedef struct file_item FILEITEM; struct file_item { - file_info_t * value; /* expected to be equivalent with &FILEITEM */ - FILEITEM * next; + file_info_t * value; /* expected to be equivalent with &FILEITEM */ + FILEITEM * next; }; typedef struct file_list { - FILEITEM * head; - FILEITEM * tail; - int size; + FILEITEM * head; + FILEITEM * tail; + int size; } FILELIST; -typedef file_info_t * * FILELISTITER; /* also &FILEITEM equivalent */ +typedef file_info_t ** FILELISTITER; /* also &FILEITEM equivalent */ - -typedef struct file_archive_info_t +struct file_archive_info_t { - OBJECT * name; - file_info_t * file; - FILELIST * members; -} file_archive_info_t; - - -typedef void (*archive_scanback)( void * closure, OBJECT * path, LIST * symbols, - int found, timestamp const * const ); -typedef void (*scanback)( void * closure, OBJECT * path, int found, - timestamp const * const ); - - -void file_archscan( char const * arch, scanback func, void * closure ); -void file_archivescan( OBJECT * path, archive_scanback func, void * closure ); -void file_build1( PATHNAME * const f, string * file ) ; -void file_dirscan( OBJECT * dir, scanback func, void * closure ); -file_info_t * file_info( OBJECT * const path, int * found ); -int file_is_file( OBJECT * const path ); -int file_mkdir( char const * const path ); -file_info_t * file_query( OBJECT * const path ); -void file_remove_atexit( OBJECT * const path ); -void file_supported_fmt_resolution( timestamp * const ); -int file_time( OBJECT * const path, timestamp * const ); + OBJECT * name = nullptr; + file_info_t * file = nullptr; + FILELIST * members = nullptr; + file_archive_info_t() = default; + file_archive_info_t(const file_archive_info_t &) = default; + file_archive_info_t(OBJECT * n) + : name(n) + {} + inline ~file_archive_info_t(); +}; -namespace b2 { namespace filesys { +typedef void (*archive_scanback)(void * closure, + OBJECT * path, + LIST * symbols, + int found, + timestamp const * const); +typedef void (*scanback)( + void * closure, OBJECT * path, int found, timestamp const * const); + +void file_archscan(char const * arch, scanback func, void * closure); +void file_archivescan(OBJECT * path, archive_scanback func, void * closure); +void file_build1(PATHNAME * const f, string * file); +void file_dirscan(OBJECT * dir, scanback func, void * closure); +file_info_t * file_info(OBJECT * const path, int * found); +int file_is_file(OBJECT * const path); +int file_mkdir(char const * const path); +file_info_t * file_query(OBJECT * const path); +void file_remove_atexit(OBJECT * const path); +void file_supported_fmt_resolution(timestamp * const); +int file_time(OBJECT * const path, timestamp * const); - inline bool is_file(const std::string &path) - { - OBJECT * path_o = object_new(path.c_str()); - bool result = file_is_file(path_o) == 1; - object_free(path_o); - return result; - } +namespace b2 { namespace filesys { -}} +inline bool is_file(const std::string & path) +{ + OBJECT * path_o = object_new(path.c_str()); + bool result = file_is_file(path_o) == 1; + object_free(path_o); + return result; +} +}} // namespace b2::filesys /* Archive/library file support */ -file_archive_info_t * file_archive_info( OBJECT * const path, int * found ); -file_archive_info_t * file_archive_query( OBJECT * path ); +file_archive_info_t * file_archive_info(OBJECT * const path, int * found); +file_archive_info_t * file_archive_query(OBJECT * path); /* FILELIST linked-list */ -FILELIST * filelist_new( OBJECT * path ); -FILELIST * filelist_push_back( FILELIST * list, OBJECT * path ); -FILELIST * filelist_push_front( FILELIST * list, OBJECT * path ); -FILELIST * filelist_pop_front( FILELIST * list ); -int filelist_length( FILELIST * list ); -void filelist_free( FILELIST * list ); - -FILELISTITER filelist_begin( FILELIST * list ); -FILELISTITER filelist_end( FILELIST * list ); -FILELISTITER filelist_next( FILELISTITER it ); -file_info_t * filelist_item( FILELISTITER it ); -file_info_t * filelist_front( FILELIST * list ); -file_info_t * filelist_back( FILELIST * list ); - -int filelist_empty( FILELIST * list ); - -#define FL0 ((FILELIST *)0) - +FILELIST * filelist_new(OBJECT * path); +FILELIST * filelist_push_back(FILELIST * list, OBJECT * path); +FILELIST * filelist_push_front(FILELIST * list, OBJECT * path); +FILELIST * filelist_pop_front(FILELIST * list); +int filelist_length(FILELIST * list); +void filelist_free(FILELIST * list); + +FILELISTITER filelist_begin(FILELIST * list); +FILELISTITER filelist_end(FILELIST * list); +FILELISTITER filelist_next(FILELISTITER it); +file_info_t * filelist_item(FILELISTITER it); +file_info_t * filelist_front(FILELIST * list); +file_info_t * filelist_back(FILELIST * list); + +int filelist_empty(FILELIST * list); + +inline file_archive_info_t::~file_archive_info_t() +{ + if (members != nullptr) filelist_free(members); +} /* Internal utility worker functions. */ -void file_query_posix_( file_info_t * const ); +void file_query_posix_(file_info_t * const); void file_done(); namespace b2 { namespace filesys { class file_buffer { - public: - bool is_memory_mapped = false; + public: + bool is_memory_mapped = false; - file_buffer(const std::string & filepath); - ~file_buffer(); + file_buffer(const std::string & filepath); + ~file_buffer(); - inline std::size_t size() const { return data_size; } - inline const char * begin() const { return data_c.get(); } - inline const char * end() const { return data_c.get()+size(); } + inline std::size_t size() const { return data_size; } + inline const char * begin() const { return data_c.get(); } + inline const char * end() const { return data_c.get() + size(); } - private: - std::unique_ptr data_c; - std::size_t data_size = 0; - FILE * file = nullptr; + private: + std::unique_ptr data_c; + std::size_t data_size = 0; + FILE * file = nullptr; }; -}} +}} // namespace b2::filesys #endif