Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-23 09:44:16

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/sys/Environment.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <functional>
0010 #include <iosfwd>
0011 #include <string>
0012 #include <unordered_map>
0013 #include <utility>
0014 #include <vector>
0015 
0016 namespace celeritas
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Interrogate and extend environment variables.
0021  *
0022  * This makes it easier to generate reproducible runs, launch Celeritas
0023  * remotely, or integrate with application drivers. The environment variables
0024  * may be encoded as JSON input to supplement or override system environment
0025  * variables, or set programmatically via this API call. Later the environment
0026  * class can be interrogated to find which environment variables were accessed.
0027  *
0028  * Unlike the standard environment which returns a null pointer for an *unset*
0029  * variable, this returns an empty string.
0030  *
0031  * \note This class is not thread-safe on its own. The \c celeritas::getenv
0032  * free function however is safe, although it should only be used in setup
0033  * (single-thread) steps.
0034  *
0035  * \note Once inserted into the environment map, values cannot be changed.
0036  * Standard practice in the code is to evaluate the environment variable
0037  * exactly \em once and cache the result as a static const variable. If you
0038  * really wanted to, you could call <code> celeritas::environment() = {};
0039  * </code> but that could result in the end-of-run diagnostic reporting
0040  * different values than the ones actually used during the code's setup.
0041  */
0042 class Environment
0043 {
0044   private:
0045     using Container = std::unordered_map<std::string, std::string>;
0046 
0047   public:
0048     //!@{
0049     //! \name Type aliases
0050     using key_type = Container::key_type;
0051     using mapped_type = Container::mapped_type;
0052     using value_type = Container::value_type;
0053     using const_iterator = Container::const_iterator;
0054     using VecKVRef = std::vector<std::reference_wrapper<value_type>>;
0055     //!@}
0056 
0057   public:
0058     // Construct with defaults
0059     Environment() = default;
0060 
0061     // Get an environment variable from current or system environments
0062     inline mapped_type const& operator[](key_type const&);
0063 
0064     // Determine whether a variable has already been set (mostly internal)
0065     inline const_iterator find(key_type const&) const;
0066 
0067     // Insert possibly new environment variables
0068     bool insert(value_type const& value);
0069 
0070     //! Get an ordered (by access) vector of key/value pairs
0071     VecKVRef const& ordered_environment() const { return ordered_; }
0072 
0073     // Remove all entries
0074     void clear();
0075 
0076     // Insert (not overriding!) from another environment
0077     void merge(Environment const& other);
0078 
0079     //!@{
0080     //! Access all entries, unordered, by const iterator
0081     const_iterator begin() const { return vars_.cbegin(); }
0082     const_iterator cbegin() const { return vars_.cbegin(); }
0083     const_iterator end() const { return vars_.cend(); }
0084     const_iterator cend() const { return vars_.cend(); }
0085     //!@}
0086 
0087   private:
0088     std::unordered_map<key_type, mapped_type> vars_;
0089     VecKVRef ordered_;
0090 
0091     mapped_type const& load_from_getenv(key_type const&);
0092 };
0093 
0094 //---------------------------------------------------------------------------//
0095 //! Return result from \c getenv_flag
0096 struct GetenvFlagResult
0097 {
0098     bool value{};  //!< Determined by user or default
0099     bool defaulted{};  //!< True if no valid user value was present
0100 };
0101 
0102 //---------------------------------------------------------------------------//
0103 // FREE FUNCTIONS
0104 //---------------------------------------------------------------------------//
0105 
0106 // Access a static global environment variable
0107 Environment& environment();
0108 
0109 // Thread-safe access to environment variables
0110 std::string const& getenv(std::string const& key);
0111 
0112 // Thread-safe flag access to environment variables
0113 GetenvFlagResult getenv_flag(std::string const& key, bool default_val);
0114 
0115 // Write the accessed environment variables to a stream
0116 std::ostream& operator<<(std::ostream&, Environment const&);
0117 
0118 //---------------------------------------------------------------------------//
0119 // INLINE DEFINITIONS
0120 //---------------------------------------------------------------------------//
0121 /*!
0122  * Determine whether a variable has already been set and get its value if so.
0123  */
0124 auto Environment::find(key_type const& env_var) const -> const_iterator
0125 {
0126     return vars_.find(env_var);
0127 }
0128 
0129 //---------------------------------------------------------------------------//
0130 /*!
0131  * Get an environment variable from current or system environments.
0132  */
0133 auto Environment::operator[](key_type const& env_var) -> mapped_type const&
0134 {
0135     auto iter = vars_.find(env_var);
0136     if (iter == vars_.end())
0137     {
0138         return this->load_from_getenv(env_var);
0139     }
0140     return iter->second;
0141 }
0142 
0143 //---------------------------------------------------------------------------//
0144 }  // namespace celeritas