HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
envSetting.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_ENV_SETTING_H
8 #define PXR_BASE_TF_ENV_SETTING_H
9 
10 /// \file tf/envSetting.h
11 /// Environment setting variable.
12 ///
13 /// A \c TfEnvSetting<T> is used to access an environment variable that
14 /// controls program execution according to the value set in the environment.
15 /// Currently, the legal types for T are bool, int, and string.
16 ///
17 /// The TfEnvSetting facility is used to enable new features in the code that
18 /// are still in "experimental" mode, and warn the user and/or QA that they
19 /// are pushing the edge of the envelope by setting a non-standard value for
20 /// these variables. Accordingly, the \c TfEnvSetting construct should be
21 /// used as sparingly as possible in code.
22 ///
23 /// In contrast, a variable that allows the user to customize program
24 /// execution but is not an in-development code path should simply use
25 /// TfGetenv() to access the variable. An example would be supplying a
26 /// variable to override a default font or fontsize, for users who don't like
27 /// the default program choice (and when there is no other way to set the
28 /// preference).
29 ///
30 /// Here is how to use the TfEnvSetting facility.
31 ///
32 /// 1. First, define your variable in a single .cpp file:
33 ///
34 /// \code
35 /// #include "pxr/base/tf/envSetting.h"
36 ///
37 /// TF_DEFINE_ENV_SETTING(TDS_FILE_VERSION, 12,
38 /// "Default file format to use");
39 /// \endcode
40 ///
41 /// The first argument is the name of your variable; it is also the name for
42 /// the variable you can set in your shell to set the value at runtime. The
43 /// second argument is the default value. To create a bool variable, pass
44 /// either true or false. To create a string variable, pass an explicit
45 /// string(), i.e.
46 ///
47 /// \code
48 /// TF_DEFINE_ENV_SETTING(TDS_FILE_SUFFIX, string(".tid"),
49 /// "Default file-name suffix");
50 /// \endcode
51 ///
52 /// 2. If you need to access this variable outside the .cpp file that defines
53 /// the variable, put the following in a common header file:
54 ///
55 /// \code
56 /// extern TfEnvSetting<int> TDS_FILE_VERSION;
57 /// extern TfEnvSetting<string> TDS_FILE_SUFFIX;
58 /// \endcode
59 ///
60 /// 3. At runtime, access your variable using TfGetEnvSetting(). For example:
61 ///
62 /// \code
63 /// int version = TfGetEnvSetting(TDS_FILE_VERSION);
64 /// string const& suffix =TfGetEnvSetting(TDS_FILE_SUFFIX);
65 /// \endcode
66 ///
67 /// You can also access a variable's value from Python:
68 ///
69 /// \code{.py}
70 /// from pxr import Tf
71 /// suffix = Tf.GetEnvSetting("TDS_FILE_SUFFIX")
72 /// \endcode
73 ///
74 /// \c Tf.GetEnvSetting() returns the value for the TfEnvSetting variable, or
75 /// None if no such variable is defined in the currently loaded C++ code.
76 ///
77 /// If a user's environment has a value for a TfEnvSetting variable that
78 /// differs from the default, when the program starts or the module defining
79 /// the TfEnvSetting variable is loaded, a warning messages is printed.
80 ///
81 /// Additionally, at program startup time (or when lib/tf is first loaded),
82 /// the environment variable PIXAR_TF_ENV_SETTING_FILE is examined. If this
83 /// variable indicates a file that can be read, then the file is parsed, and
84 /// should contain lines of the form key=value. For each line read, the
85 /// environment variable key is set to value. For example:
86 ///
87 /// \code{.sh}
88 /// $ setenv PIXAR_TF_ENV_SETTING_FILE /usr/anim/<UNIT>/admin/env-settings
89 ///
90 /// $ cat /usr/anim/<UNIT>/admin/env-settings
91 /// TDS_DEF_VERSION=30
92 /// TDS_BLAH=
93 /// TDS_LONG_STRING=i am some long string with spaces
94 /// \endcode
95 ///
96 /// Blank lines in the file and lines where the first character is '#' are
97 /// ignored. If the file itself cannot be read, no error is printed; however,
98 /// if the file is malformed, errors are printed to stderr.
99 
100 #include "pxr/pxr.h"
101 #include "pxr/base/arch/hints.h"
103 
104 #include <atomic>
105 #include <string>
106 
108 
109 // POD, statically initialized.
110 //
111 // We store the atomic_value separately and refer to it via pointer because we
112 // cannot use aggregate-initialization on a struct holding an atomic, but we
113 // can value-initialize a single std::atomic.
114 template <class T>
116 {
117  std::atomic<T*> *_value;
119  char const * _name;
120  char const * _description;
121 };
122 
123 // Specialize for string, default is stored as char const * (pointing to a
124 // literal).
125 template <>
126 struct TfEnvSetting<std::string>
127 {
128  std::atomic<std::string*> *_value;
129  char const * _default;
130  char const * _name;
131  char const * _description;
132 };
133 
134 template <class T>
136 
137 /// Returns the value of the specified env setting, registered using
138 /// \c TF_DEFINE_ENV_SETTING.
139 template <class T>
140 inline T const &
142  T *val = setting._value->load();
143  if (ARCH_UNLIKELY(!val)) {
144  Tf_InitializeEnvSetting(&setting);
145  val = setting._value->load();
146  }
147  return *val;
148 }
149 
150 // Ensure that we only allow bool, int, and string, and map char * and char
151 // array to string.
152 
153 bool Tf_ChooseEnvSettingType(bool);
154 int Tf_ChooseEnvSettingType(int);
155 std::string Tf_ChooseEnvSettingType(char const *);
156 
157 class Tf_EnvSettingRegistry;
158 
159 /// Define an env setting named \p envVar with default value \p defValue and a
160 /// descriptive string \p description.
161 /// \hideinitializer
162 #define TF_DEFINE_ENV_SETTING(envVar, defValue, description) \
163  std::atomic< decltype(Tf_ChooseEnvSettingType(defValue))*> \
164  envVar##_value; \
165  TfEnvSetting<decltype(Tf_ChooseEnvSettingType(defValue))> envVar = { \
166  &envVar##_value, defValue, #envVar, description }; \
167  TF_REGISTRY_FUNCTION_WITH_TAG(Tf_EnvSettingRegistry, envVar) { \
168  (void)TfGetEnvSetting(envVar); \
169  }
170 
172 
173 #endif // PXR_BASE_TF_ENV_SETTING_H
void Tf_InitializeEnvSetting(TfEnvSetting< T > *)
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
T const & TfGetEnvSetting(TfEnvSetting< T > &setting)
Definition: envSetting.h:141
std::atomic< T * > * _value
Definition: envSetting.h:117
char const * _description
Definition: envSetting.h:120
std::atomic< std::string * > * _value
Definition: envSetting.h:128
#define ARCH_UNLIKELY(x)
Definition: hints.h:30
bool Tf_ChooseEnvSettingType(bool)
char const * _name
Definition: envSetting.h:119
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74