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 Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_TF_ENV_SETTING_H
25 #define PXR_BASE_TF_ENV_SETTING_H
26 
27 /// \file tf/envSetting.h
28 /// Environment setting variable.
29 ///
30 /// A \c TfEnvSetting<T> is used to access an environment variable that
31 /// controls program execution according to the value set in the environment.
32 /// Currently, the legal types for T are bool, int, and string.
33 ///
34 /// The TfEnvSetting facility is used to enable new features in the code that
35 /// are still in "experimental" mode, and warn the user and/or QA that they
36 /// are pushing the edge of the envelope by setting a non-standard value for
37 /// these variables. Accordingly, the \c TfEnvSetting construct should be
38 /// used as sparingly as possible in code.
39 ///
40 /// In contrast, a variable that allows the user to customize program
41 /// execution but is not an in-development code path should simply use
42 /// TfGetenv() to access the variable. An example would be supplying a
43 /// variable to override a default font or fontsize, for users who don't like
44 /// the default program choice (and when there is no other way to set the
45 /// preference).
46 ///
47 /// Here is how to use the TfEnvSetting facility.
48 ///
49 /// 1. First, define your variable in a single .cpp file:
50 ///
51 /// \code
52 /// #include "pxr/base/tf/envSetting.h"
53 ///
54 /// TF_DEFINE_ENV_SETTING(TDS_FILE_VERSION, 12,
55 /// "Default file format to use");
56 /// \endcode
57 ///
58 /// The first argument is the name of your variable; it is also the name for
59 /// the variable you can set in your shell to set the value at runtime. The
60 /// second argument is the default value. To create a bool variable, pass
61 /// either true or false. To create a string variable, pass an explicit
62 /// string(), i.e.
63 ///
64 /// \code
65 /// TF_DEFINE_ENV_SETTING(TDS_FILE_SUFFIX, string(".tid"),
66 /// "Default file-name suffix");
67 /// \endcode
68 ///
69 /// 2. If you need to access this variable outside the .cpp file that defines
70 /// the variable, put the following in a common header file:
71 ///
72 /// \code
73 /// extern TfEnvSetting<int> TDS_FILE_VERSION;
74 /// extern TfEnvSetting<string> TDS_FILE_SUFFIX;
75 /// \endcode
76 ///
77 /// 3. At runtime, access your variable using TfGetEnvSetting(). For example:
78 ///
79 /// \code
80 /// int version = TfGetEnvSetting(TDS_FILE_VERSION);
81 /// string const& suffix =TfGetEnvSetting(TDS_FILE_SUFFIX);
82 /// \endcode
83 ///
84 /// You can also access a variable's value from Python:
85 ///
86 /// \code{.py}
87 /// from pxr import Tf
88 /// suffix = Tf.GetEnvSetting("TDS_FILE_SUFFIX")
89 /// \endcode
90 ///
91 /// \c Tf.GetEnvSetting() returns the value for the TfEnvSetting variable, or
92 /// None if no such variable is defined in the currently loaded C++ code.
93 ///
94 /// If a user's environment has a value for a TfEnvSetting variable that
95 /// differs from the default, when the program starts or the module defining
96 /// the TfEnvSetting variable is loaded, a warning messages is printed.
97 ///
98 /// Additionally, at program startup time (or when lib/tf is first loaded),
99 /// the environment variable PIXAR_TF_ENV_SETTING_FILE is examined. If this
100 /// variable indicates a file that can be read, then the file is parsed, and
101 /// should contain lines of the form key=value. For each line read, the
102 /// environment variable key is set to value. For example:
103 ///
104 /// \code{.sh}
105 /// $ setenv PIXAR_TF_ENV_SETTING_FILE /usr/anim/<UNIT>/admin/env-settings
106 ///
107 /// $ cat /usr/anim/<UNIT>/admin/env-settings
108 /// TDS_DEF_VERSION=30
109 /// TDS_BLAH=
110 /// TDS_LONG_STRING=i am some long string with spaces
111 /// \endcode
112 ///
113 /// Blank lines in the file and lines where the first character is '#' are
114 /// ignored. If the file itself cannot be read, no error is printed; however,
115 /// if the file is malformed, errors are printed to stderr.
116 
117 #include "pxr/pxr.h"
118 #include "pxr/base/arch/hints.h"
120 
121 #include <atomic>
122 #include <string>
123 
125 
126 // POD, statically initialized.
127 //
128 // We store the atomic_value separately and refer to it via pointer because we
129 // cannot use aggregate-initialization on a struct holding an atomic, but we
130 // can value-initialize a single std::atomic.
131 template <class T>
133 {
134  std::atomic<T*> *_value;
136  char const * _name;
137  char const * _description;
138 };
139 
140 // Specialize for string, default is stored as char const * (pointing to a
141 // literal).
142 template <>
143 struct TfEnvSetting<std::string>
144 {
145  std::atomic<std::string*> *_value;
146  char const * _default;
147  char const * _name;
148  char const * _description;
149 };
150 
151 template <class T>
153 
154 /// Returns the value of the specified env setting, registered using
155 /// \c TF_DEFINE_ENV_SETTING.
156 template <class T>
157 inline T const &
159  T *val = setting._value->load();
160  if (ARCH_UNLIKELY(!val)) {
161  Tf_InitializeEnvSetting(&setting);
162  val = setting._value->load();
163  }
164  return *val;
165 }
166 
167 // Ensure that we only allow bool, int, and string, and map char * and char
168 // array to string.
169 
170 bool Tf_ChooseEnvSettingType(bool);
171 int Tf_ChooseEnvSettingType(int);
173 
174 class Tf_EnvSettingRegistry;
175 
176 /// Define an env setting named \p envVar with default value \p defValue and a
177 /// descriptive string \p description.
178 /// \hideinitializer
179 #define TF_DEFINE_ENV_SETTING(envVar, defValue, description) \
180  std::atomic< decltype(Tf_ChooseEnvSettingType(defValue))*> \
181  envVar##_value; \
182  TfEnvSetting<decltype(Tf_ChooseEnvSettingType(defValue))> envVar = { \
183  &envVar##_value, defValue, #envVar, description }; \
184  TF_REGISTRY_FUNCTION_WITH_TAG(Tf_EnvSettingRegistry, envVar) { \
185  (void)TfGetEnvSetting(envVar); \
186  }
187 
189 
190 #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:158
std::atomic< T * > * _value
Definition: envSetting.h:134
char const * _description
Definition: envSetting.h:137
std::atomic< std::string * > * _value
Definition: envSetting.h:145
#define ARCH_UNLIKELY(x)
Definition: hints.h:47
bool Tf_ChooseEnvSettingType(bool)
char const * _name
Definition: envSetting.h:136
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91