aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/types.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/types.hxx')
-rw-r--r--libbuild2/types.hxx246
1 files changed, 175 insertions, 71 deletions
diff --git a/libbuild2/types.hxx b/libbuild2/types.hxx
index 60101b3..ea84701 100644
--- a/libbuild2/types.hxx
+++ b/libbuild2/types.hxx
@@ -13,8 +13,12 @@
# include <libbuild2/config.hxx>
#endif
+#include <map>
+#include <set>
+#include <list>
#include <array>
#include <tuple>
+#include <regex>
#include <vector>
#include <string>
#include <memory> // unique_ptr, shared_ptr
@@ -26,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
@@ -41,20 +53,22 @@
#include <stdexcept> // logic_error, invalid_argument, runtime_error
#include <system_error>
-#include <libbutl/path.mxx>
-#include <libbutl/path-map.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>
@@ -78,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*>;
@@ -92,16 +109,30 @@ namespace build2
using std::shared_ptr;
using std::weak_ptr;
+ using std::map;
+ using std::multimap;
+ using std::set;
+ 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;
using std::endl;
using std::streamsize; // C++'s ssize_t.
+ // Regex.
+ //
+ // Note that <libbutl/regex.hxx> includes an ostream insertion operator for
+ // regex_error which prints cleaned up message, if any.
+ //
+ using std::regex;
+ using std::regex_error;
+ using regex_match_results = std::match_results<string::const_iterator>;
+
// Concurrency.
//
using std::atomic;
@@ -168,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.
//
@@ -196,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.
//
@@ -215,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;
@@ -241,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.
@@ -264,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;
@@ -276,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;
@@ -290,28 +390,52 @@ namespace build2
//
// See also {import,export}.metadata.
//
+ // Note that the environment checksum is calculated in the (potentially
+ // hermetic) project environment which makes instances of process_path_ex
+ // project-specific. (We could potentially store the original list of
+ // environment variables and calculate the checksum on the fly in the
+ // current context thus making it project-independent. But this will
+ // complicate things without, currently, much real benefit since all our
+ // use-cases fit well with the project-specific restriction. We could
+ // probably even support both variants if desirable.)
+ //
struct process_path_ex: process_path
{
- optional<string> name; // Stable name for diagnostics.
- optional<string> checksum; // Checksum for change tracking.
+ optional<string> name; // Stable name for diagnostics.
+ optional<string> checksum; // Executable checksum for change tracking.
+ optional<string> env_checksum; // Environment checksum for change tracking.
using process_path::process_path;
- process_path_ex (const process_path& p, string n, optional<string> c = {})
+ process_path_ex (const process_path& p,
+ string n,
+ optional<string> c = {},
+ optional<string> ec = {})
: process_path (p, false /* init */),
name (std::move (n)),
- checksum (std::move (c)) {}
+ checksum (std::move (c)),
+ env_checksum (std::move (ec)) {}
- process_path_ex (process_path&& p, string n, optional<string> c = {})
+ process_path_ex (process_path&& p,
+ string n,
+ optional<string> c = {},
+ optional<string> ec = {})
: process_path (std::move (p)),
name (std::move (n)),
- checksum (std::move (c)) {}
+ checksum (std::move (c)),
+ env_checksum (std::move (ec)) {}
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;
@@ -321,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;
@@ -393,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&);
};
@@ -407,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>