// file : libbuild2/types.hxx -*- C++ -*- // copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef LIBBUILD2_TYPES_HXX #define LIBBUILD2_TYPES_HXX // Include unprocessed file during bootstrap. See // for details. // #ifdef BUILD2_BOOTSTRAP # include #else # include #endif #include #include #include #include #include // unique_ptr, shared_ptr #include // pair, move() #include // size_t, nullptr_t #include // uint{8,16,32,64}_t, *_MIN, *_MAX #include #include #include // hash, function, reference_wrapper #include #include #include #include #include #include #if defined(__cpp_lib_shared_mutex) || defined(__cpp_lib_shared_timed_mutex) # include #endif #include // ios_base::failure #include // exception #include // logic_error, invalid_argument, runtime_error #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace build2 { // Commonly-used types. // using std::uint8_t; using std::uint16_t; using std::uint32_t; using std::uint64_t; using std::uintptr_t; using uint64s = std::vector; using std::size_t; using std::nullptr_t; using std::pair; using std::tuple; using std::string; using std::function; using std::reference_wrapper; using strings = std::vector; using cstrings = std::vector; using std::hash; using std::initializer_list; using std::unique_ptr; using std::shared_ptr; using std::weak_ptr; using std::array; using std::vector; using butl::vector_view; // using butl::small_vector; // using std::istream; using std::ostream; using std::endl; using std::streamsize; // C++'s ssize_t. // Concurrency. // using std::atomic; using std::memory_order; using std::memory_order_relaxed; using std::memory_order_consume; using std::memory_order_acquire; using std::memory_order_release; using std::memory_order_acq_rel; using std::memory_order_seq_cst; using atomic_count = atomic; // Matches scheduler::atomic_count. // Like std::atomic except implicit conversion and assignment use relaxed // memory ordering. // template struct relaxed_atomic: atomic { using atomic::atomic; // Delegate. relaxed_atomic (const relaxed_atomic& a) noexcept : atomic (a.load (memory_order_relaxed)) {} operator T () const noexcept {return this->load (memory_order_relaxed);} T operator= (T v) noexcept { this->store (v, memory_order_relaxed); return v;} T operator= (const relaxed_atomic& a) noexcept { return *this = a.load (memory_order_relaxed);} }; template struct relaxed_atomic: atomic { using atomic::atomic; // Delegate. relaxed_atomic (const relaxed_atomic& a) noexcept : atomic (a.load (memory_order_relaxed)) {} operator T* () const noexcept {return this->load (memory_order_relaxed);} T& operator* () const noexcept {return *this->load (memory_order_relaxed);} T* operator-> () const noexcept {return this->load (memory_order_relaxed);} T* operator= (T* v) noexcept { this->store (v, memory_order_relaxed); return v;} T* operator= (const relaxed_atomic& a) noexcept { return *this = a.load (memory_order_relaxed);} }; // VC 14 has issues. // #if defined(_MSC_VER) && _MSC_VER <= 1900 template inline bool operator== (const relaxed_atomic& x, const P& y) { return static_cast (x) == y; } template inline bool operator!= (const relaxed_atomic& x, const P& y) { return static_cast (x) != y; } #endif using std::mutex; using mlock = std::unique_lock; using std::condition_variable; #if defined(__cpp_lib_shared_mutex) using shared_mutex = std::shared_mutex; using ulock = std::unique_lock; using slock = std::shared_lock; #elif defined(__cpp_lib_shared_timed_mutex) using shared_mutex = std::shared_timed_mutex; using ulock = std::unique_lock; using slock = std::shared_lock; #else // Because we have this fallback, we need to be careful not to create // multiple shared locks in the same thread. // struct shared_mutex: mutex { using mutex::mutex; void lock_shared () { lock (); } void try_lock_shared () { try_lock (); } void unlock_shared () { unlock (); } }; using ulock = std::unique_lock; using slock = ulock; #endif using std::defer_lock; using std::adopt_lock; using std::thread; namespace this_thread = std::this_thread; // Exceptions. // // While is included, there is no using for std::exception -- // use qualified. // using std::logic_error; using std::invalid_argument; using std::runtime_error; using std::system_error; using io_error = std::ios_base::failure; // // using butl::optional; using butl::nullopt; // // using butl::const_ptr; // // // using butl::path; using butl::dir_path; using butl::path_cast; using butl::basic_path; using butl::invalid_path; using butl::path_abnormality; using butl::path_map; using butl::dir_path_map; // Absolute directory path. Note that for now we don't do any checking that // the path is in fact absolute. // // The idea is to have a different type that we automatically complete when // a (variable) value of this type gets initialized from untyped names. See // value_type for details. // // Note that currently we also normalize and actualize the path. And we // leave empty path as is. // struct abs_dir_path: dir_path { using dir_path::dir_path; explicit abs_dir_path (dir_path d): dir_path (std::move (d)) {} abs_dir_path () = default; }; using paths = std::vector; using dir_paths = std::vector; // // using butl::system_clock; using butl::timestamp; using butl::duration; using butl::timestamp_unknown; using butl::timestamp_unknown_rep; using butl::timestamp_nonexistent; using butl::to_string; using butl::operator<<; // // using butl::sha256; // // // using butl::process; using butl::process_env; using butl::process_path; using butl::process_error; using butl::auto_fd; using butl::ifdstream; using butl::ofdstream; using butl::fdopen_mode; using butl::fdstream_mode; using butl::fdselect_state; using butl::fdselect_set; // // using butl::target_triplet; // // using butl::semantic_version; using butl::parse_semantic_version; // // using butl::standard_version; using butl::standard_version_constraint; // // using butl::project_name; // Diagnostics location. // class location { public: // Note that location maintains a shallow reference to path. Zero lines // or columns are not printed. // explicit location (const path* f = nullptr, uint64_t l = 0, uint64_t c = 0) : file (f), line (l), column (c) {} bool empty () const {return file == nullptr;} const path* file; uint64_t line; uint64_t column; }; // See context. // enum class run_phase {load, match, execute}; LIBBUILD2_SYMEXPORT ostream& operator<< (ostream&, run_phase); // utility.cxx LIBBUILD2_SYMEXPORT extern run_phase phase; } // 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 with trailing slash for directories. // LIBBUILD2_SYMEXPORT ostream& operator<< (ostream&, const ::butl::path&); // Print as recall[@effect]. // LIBBUILD2_SYMEXPORT ostream& operator<< (ostream&, const ::butl::process_path&); } // // #include #endif // LIBBUILD2_TYPES_HXX