diff options
Diffstat (limited to 'libbuild2/types.hxx')
-rw-r--r-- | libbuild2/types.hxx | 203 |
1 files changed, 136 insertions, 67 deletions
diff --git a/libbuild2/types.hxx b/libbuild2/types.hxx index 0005e75..ea84701 100644 --- a/libbuild2/types.hxx +++ b/libbuild2/types.hxx @@ -15,6 +15,7 @@ #include <map> #include <set> +#include <list> #include <array> #include <tuple> #include <regex> @@ -29,14 +30,22 @@ #include <functional> // hash, function, reference_wrapper #include <initializer_list> -#include <mutex> #include <atomic> -#include <thread> -#include <condition_variable> -#include <libbutl/ft/shared_mutex.hxx> -#if defined(__cpp_lib_shared_mutex) || defined(__cpp_lib_shared_timed_mutex) -# include <shared_mutex> +#ifndef LIBBUTL_MINGW_STDTHREAD +# include <mutex> +# include <thread> +# include <condition_variable> + +# include <libbutl/ft/shared_mutex.hxx> +# if defined(__cpp_lib_shared_mutex) || defined(__cpp_lib_shared_timed_mutex) +# include <shared_mutex> +# endif +#else +# include <libbutl/mingw-mutex.hxx> +# include <libbutl/mingw-thread.hxx> +# include <libbutl/mingw-condition_variable.hxx> +# include <libbutl/mingw-shared_mutex.hxx> #endif #include <ios> // ios_base::failure @@ -44,21 +53,22 @@ #include <stdexcept> // logic_error, invalid_argument, runtime_error #include <system_error> -#include <libbutl/path.mxx> -#include <libbutl/path-map.mxx> -#include <libbutl/regex.mxx> -#include <libbutl/sha256.mxx> -#include <libbutl/process.mxx> -#include <libbutl/fdstream.mxx> -#include <libbutl/optional.mxx> -#include <libbutl/const-ptr.mxx> -#include <libbutl/timestamp.mxx> -#include <libbutl/vector-view.mxx> -#include <libbutl/small-vector.mxx> -#include <libbutl/project-name.mxx> -#include <libbutl/target-triplet.mxx> -#include <libbutl/semantic-version.mxx> -#include <libbutl/standard-version.mxx> +#include <libbutl/path.hxx> +#include <libbutl/path-map.hxx> +#include <libbutl/regex.hxx> +#include <libbutl/sha256.hxx> +#include <libbutl/process.hxx> +#include <libbutl/fdstream.hxx> +#include <libbutl/optional.hxx> +#include <libbutl/const-ptr.hxx> +#include <libbutl/timestamp.hxx> +#include <libbutl/vector-view.hxx> +#include <libbutl/small-vector.hxx> +#include <libbutl/project-name.hxx> +#include <libbutl/target-triplet.hxx> +#include <libbutl/semantic-version.hxx> +#include <libbutl/standard-version.hxx> +#include <libbutl/move-only-function.hxx> #include <libbuild2/export.hxx> @@ -82,9 +92,12 @@ namespace build2 using std::pair; using std::tuple; using std::string; - using std::function; using std::reference_wrapper; + using std::function; + using butl::move_only_function; + using butl::move_only_function_ex; + using strings = std::vector<string>; using cstrings = std::vector<const char*>; @@ -102,8 +115,9 @@ namespace build2 using std::multiset; using std::array; using std::vector; - using butl::vector_view; // <libbutl/vector-view.mxx> - using butl::small_vector; // <libbutl/small-vector.mxx> + using std::list; + using butl::vector_view; // <libbutl/vector-view.hxx> + using butl::small_vector; // <libbutl/small-vector.hxx> using std::istream; using std::ostream; @@ -112,7 +126,7 @@ namespace build2 // Regex. // - // Note that <libbutl/regex.mxx> includes an ostream insertion operator for + // Note that <libbutl/regex.hxx> includes an ostream insertion operator for // regex_error which prints cleaned up message, if any. // using std::regex; @@ -185,20 +199,27 @@ namespace build2 } #endif +#ifndef LIBBUTL_MINGW_STDTHREAD using std::mutex; using mlock = std::unique_lock<mutex>; using std::condition_variable; -#if defined(__cpp_lib_shared_mutex) + using std::defer_lock; + using std::adopt_lock; + + using std::thread; + namespace this_thread = std::this_thread; + +# if defined(__cpp_lib_shared_mutex) using shared_mutex = std::shared_mutex; using ulock = std::unique_lock<shared_mutex>; using slock = std::shared_lock<shared_mutex>; -#elif defined(__cpp_lib_shared_timed_mutex) +# elif defined(__cpp_lib_shared_timed_mutex) using shared_mutex = std::shared_timed_mutex; using ulock = std::unique_lock<shared_mutex>; using slock = std::shared_lock<shared_mutex>; -#else +# else // Because we have this fallback, we need to be careful not to create // multiple shared locks in the same thread. // @@ -213,13 +234,57 @@ namespace build2 using ulock = std::unique_lock<shared_mutex>; using slock = ulock; -#endif +# endif +#else // LIBBUTL_MINGW_STDTHREAD + using mingw_stdthread::mutex; + using mlock = mingw_stdthread::unique_lock<mutex>; - using std::defer_lock; - using std::adopt_lock; + using mingw_stdthread::condition_variable; - using std::thread; - namespace this_thread = std::this_thread; + using mingw_stdthread::defer_lock; + using mingw_stdthread::adopt_lock; + + using mingw_stdthread::thread; + namespace this_thread = mingw_stdthread::this_thread; + + using shared_mutex = mingw_stdthread::shared_mutex; + using ulock = mingw_stdthread::unique_lock<shared_mutex>; + using slock = mingw_stdthread::shared_lock<shared_mutex>; +#endif + + // Global, MT-safe information cache. Normally used for caching information + // (versions, target triplets, search paths, etc) extracted from other + // programs (compilers, etc). + // + // The key is normally a hash of all the inputs that can affect the output. + // + // Note that insertion is racy and it's possible the cache entry already + // exists, in which case we ignore our value assuming it is the same. + // + template <typename T, typename K = string> + class global_cache + { + public: + const T* + find (const K& k) const + { + mlock l (mutex_); + auto i (cache_.find (k)); + return i != cache_.end () ? &i->second : nullptr; + } + + const T& + insert (K k, T v) + { + mlock l (mutex_); + return cache_.insert (std::make_pair (std::move (k), + std::move (v))).first->second; + } + + private: + map<K, T> cache_; + mutable mutex mutex_; + }; // Exceptions. // @@ -232,17 +297,17 @@ namespace build2 using std::system_error; using io_error = std::ios_base::failure; - // <libbutl/optional.mxx> + // <libbutl/optional.hxx> // using butl::optional; using butl::nullopt; - // <libbutl/const-ptr.mxx> + // <libbutl/const-ptr.hxx> // using butl::const_ptr; - // <libbutl/path.mxx> - // <libbutl/path-map.mxx> + // <libbutl/path.hxx> + // <libbutl/path-map.hxx> // using butl::path; using path_traits = path::traits_type; @@ -258,6 +323,8 @@ namespace build2 using butl::path_map; using butl::dir_path_map; + using butl::path_multimap; + using butl::dir_path_multimap; // Absolute directory path. Note that for now we don't do any checking that // the path is in fact absolute. @@ -281,7 +348,21 @@ namespace build2 using paths = std::vector<path>; using dir_paths = std::vector<dir_path>; - // <libbutl/timestamp.mxx> + // Path printing potentially relative with trailing slash for directories. + // + LIBBUILD2_SYMEXPORT ostream& + operator<< (ostream&, const path&); // utility.cxx + + inline ostream& + operator<< (ostream& os, const dir_path& d) // For overload resolution. + { + return build2::operator<< (os, static_cast<const path&> (d)); + } + + LIBBUILD2_SYMEXPORT ostream& + operator<< (ostream&, const path_name_view&); // utility.cxx + + // <libbutl/timestamp.hxx> // using butl::system_clock; using butl::timestamp; @@ -293,13 +374,15 @@ namespace build2 using butl::to_string; using butl::operator<<; - // <libbutl/sha256.mxx> + // <libbutl/sha256.hxx> // using butl::sha256; - // <libbutl/process.mxx> + // <libbutl/process.hxx> + // using butl::process; using butl::process_env; + using butl::process_exit; using butl::process_path; using butl::process_error; @@ -345,8 +428,14 @@ namespace build2 process_path_ex () = default; }; - // <libbutl/fdstream.mxx> + // Print as recall[@effect]. + // + LIBBUILD2_SYMEXPORT ostream& + operator<< (ostream&, const process_path&); // utility.cxx + + // <libbutl/fdstream.hxx> // + using butl::nullfd; using butl::auto_fd; using butl::fdpipe; using butl::ifdstream; @@ -356,21 +445,21 @@ namespace build2 using butl::fdselect_state; using butl::fdselect_set; - // <libbutl/target-triplet.mxx> + // <libbutl/target-triplet.hxx> // using butl::target_triplet; - // <libbutl/semantic-version.mxx> + // <libbutl/semantic-version.hxx> // using butl::semantic_version; using butl::parse_semantic_version; - // <libbutl/standard-version.mxx> + // <libbutl/standard-version.hxx> // using butl::standard_version; using butl::standard_version_constraint; - // <libbutl/project-name.mxx> + // <libbutl/project-name.hxx> // using butl::project_name; @@ -428,9 +517,9 @@ namespace build2 location_value (const location&); - location_value (location_value&&); + location_value (location_value&&) noexcept; location_value (const location_value&); - location_value& operator= (location_value&&); + location_value& operator= (location_value&&) noexcept; location_value& operator= (const location_value&); }; @@ -442,26 +531,6 @@ namespace build2 operator<< (ostream&, run_phase); // utility.cxx } -// In order to be found (via ADL) these have to be either in std:: or in -// butl::. The latter is a bad idea since libbutl includes the default -// implementation. They are defined in utility.cxx. -// -namespace std -{ - // Path printing potentially relative with trailing slash for directories. - // - LIBBUILD2_SYMEXPORT ostream& - operator<< (ostream&, const ::butl::path&); - - LIBBUILD2_SYMEXPORT ostream& - operator<< (ostream&, const ::butl::path_name_view&); - - // Print as recall[@effect]. - // - LIBBUILD2_SYMEXPORT ostream& - operator<< (ostream&, const ::butl::process_path&); -} - // <libbuild2/name.hxx> // #include <libbuild2/name.hxx> |