Skip to content

Commit 148dec9

Browse files
authored
[OpenMP][NFC] Separate Envar (environment variable) handling (llvm#73994)
1 parent 4bf8a68 commit 148dec9

File tree

8 files changed

+212
-196
lines changed

8 files changed

+212
-196
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
//===-- Shared/EnvironmentVar.h - Environment variable handling -*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#ifndef OMPTARGET_SHARED_ENVIRONMENT_VAR_H
12+
#define OMPTARGET_SHARED_ENVIRONMENT_VAR_H
13+
14+
#include "Debug.h"
15+
16+
#include "llvm/ADT/StringRef.h"
17+
#include "llvm/Support/Error.h"
18+
19+
#include <sstream>
20+
#include <string>
21+
22+
/// Utility class for parsing strings to other types.
23+
struct StringParser {
24+
/// Parse a string to another type.
25+
template <typename Ty> static bool parse(const char *Value, Ty &Result);
26+
};
27+
28+
/// Class for reading and checking environment variables. Currently working with
29+
/// integer, floats, std::string and bool types.
30+
template <typename Ty> class Envar {
31+
Ty Data;
32+
bool IsPresent;
33+
bool Initialized;
34+
35+
public:
36+
/// Auxiliary function to safely create envars. This static function safely
37+
/// creates envars using fallible constructors. See the constructors to know
38+
/// more details about the creation parameters.
39+
template <typename... ArgsTy>
40+
static llvm::Expected<Envar> create(ArgsTy &&...Args) {
41+
llvm::Error Err = llvm::Error::success();
42+
Envar Envar(std::forward<ArgsTy>(Args)..., Err);
43+
if (Err)
44+
return std::move(Err);
45+
return std::move(Envar);
46+
}
47+
48+
/// Create an empty envar. Cannot be consulted. This constructor is merely
49+
/// for convenience. This constructor is not fallible.
50+
Envar() : Data(Ty()), IsPresent(false), Initialized(false) {}
51+
52+
/// Create an envar with a name and an optional default. The Envar object will
53+
/// take the value read from the environment variable, or the default if it
54+
/// was not set or not correct. This constructor is not fallible.
55+
Envar(llvm::StringRef Name, Ty Default = Ty())
56+
: Data(Default), IsPresent(false), Initialized(true) {
57+
58+
if (const char *EnvStr = getenv(Name.data())) {
59+
// Check whether the envar is defined and valid.
60+
IsPresent = StringParser::parse<Ty>(EnvStr, Data);
61+
62+
if (!IsPresent) {
63+
DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data());
64+
Data = Default;
65+
}
66+
}
67+
}
68+
69+
Envar<Ty> &operator=(const Ty &V) {
70+
Data = V;
71+
Initialized = true;
72+
return *this;
73+
}
74+
75+
/// Get the definitive value.
76+
const Ty &get() const {
77+
// Throw a runtime error in case this envar is not initialized.
78+
if (!Initialized)
79+
FATAL_MESSAGE0(1, "Consulting envar before initialization");
80+
81+
return Data;
82+
}
83+
84+
/// Get the definitive value.
85+
operator Ty() const { return get(); }
86+
87+
/// Indicate whether the environment variable was defined and valid.
88+
bool isPresent() const { return IsPresent; }
89+
90+
private:
91+
/// This constructor should never fail but we provide it for convenience. This
92+
/// way, the constructor can be used by the Envar::create() static function
93+
/// to safely create this kind of envars.
94+
Envar(llvm::StringRef Name, Ty Default, llvm::Error &Err)
95+
: Envar(Name, Default) {
96+
llvm::ErrorAsOutParameter EAO(&Err);
97+
Err = llvm::Error::success();
98+
}
99+
100+
/// Create an envar with a name, getter function and a setter function. The
101+
/// Envar object will take the value read from the environment variable if
102+
/// this value is accepted by the setter function. Otherwise, the getter
103+
/// function will be executed to get the default value. The getter should be
104+
/// of the form Error GetterFunctionTy(Ty &Value) and the setter should
105+
/// be of the form Error SetterFunctionTy(Ty Value). This constructor has a
106+
/// private visibility because is a fallible constructor. Please use the
107+
/// Envar::create() static function to safely create this object instead.
108+
template <typename GetterFunctor, typename SetterFunctor>
109+
Envar(llvm::StringRef Name, GetterFunctor Getter, SetterFunctor Setter,
110+
llvm::Error &Err)
111+
: Data(Ty()), IsPresent(false), Initialized(true) {
112+
llvm::ErrorAsOutParameter EAO(&Err);
113+
Err = init(Name, Getter, Setter);
114+
}
115+
116+
template <typename GetterFunctor, typename SetterFunctor>
117+
llvm::Error init(llvm::StringRef Name, GetterFunctor Getter,
118+
SetterFunctor Setter);
119+
};
120+
121+
/// Define some common envar types.
122+
using IntEnvar = Envar<int>;
123+
using Int32Envar = Envar<int32_t>;
124+
using Int64Envar = Envar<int64_t>;
125+
using UInt32Envar = Envar<uint32_t>;
126+
using UInt64Envar = Envar<uint64_t>;
127+
using StringEnvar = Envar<std::string>;
128+
using BoolEnvar = Envar<bool>;
129+
130+
template <>
131+
inline bool StringParser::parse(const char *ValueStr, bool &Result) {
132+
std::string Value(ValueStr);
133+
134+
// Convert the string to lowercase.
135+
std::transform(Value.begin(), Value.end(), Value.begin(),
136+
[](unsigned char c) { return std::tolower(c); });
137+
138+
// May be implemented with fancier C++ features, but let's keep it simple.
139+
if (Value == "true" || Value == "yes" || Value == "on" || Value == "1")
140+
Result = true;
141+
else if (Value == "false" || Value == "no" || Value == "off" || Value == "0")
142+
Result = false;
143+
else
144+
return false;
145+
146+
// Parsed correctly.
147+
return true;
148+
}
149+
150+
template <typename Ty>
151+
inline bool StringParser::parse(const char *Value, Ty &Result) {
152+
assert(Value && "Parsed value cannot be null");
153+
154+
std::istringstream Stream(Value);
155+
Stream >> Result;
156+
157+
return !Stream.fail();
158+
}
159+
160+
template <typename Ty>
161+
template <typename GetterFunctor, typename SetterFunctor>
162+
inline llvm::Error Envar<Ty>::init(llvm::StringRef Name, GetterFunctor Getter,
163+
SetterFunctor Setter) {
164+
// Get the default value.
165+
Ty Default;
166+
if (llvm::Error Err = Getter(Default))
167+
return Err;
168+
169+
if (const char *EnvStr = getenv(Name.data())) {
170+
IsPresent = StringParser::parse<Ty>(EnvStr, Data);
171+
if (IsPresent) {
172+
// Check whether the envar value is actually valid.
173+
llvm::Error Err = Setter(Data);
174+
if (Err) {
175+
// The setter reported an invalid value. Mark the user-defined value as
176+
// not present and reset to the getter value (default).
177+
IsPresent = false;
178+
Data = Default;
179+
DP("Setter of envar %s failed, resetting to %s\n", Name.data(),
180+
std::to_string(Data).data());
181+
consumeError(std::move(Err));
182+
}
183+
} else {
184+
DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data());
185+
Data = Default;
186+
}
187+
} else {
188+
Data = Default;
189+
}
190+
191+
return llvm::Error::success();
192+
}
193+
194+
#endif // OMPTARGET_SHARED_ENVIRONMENT_VAR_H

openmp/libomptarget/include/Shared/Utils.h

Lines changed: 0 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -15,131 +15,18 @@
1515
#define OMPTARGET_SHARED_UTILS_H
1616

1717
#include "llvm/ADT/StringRef.h"
18-
#include "llvm/Support/Error.h"
1918

2019
#include "Debug.h"
2120

22-
#include <algorithm>
2321
#include <atomic>
2422
#include <cassert>
25-
#include <cstddef>
26-
#include <cstdint>
27-
#include <cstdlib>
28-
#include <functional>
2923
#include <limits>
3024
#include <memory>
31-
#include <sstream>
32-
#include <string>
3325

3426
namespace llvm {
3527
namespace omp {
3628
namespace target {
3729

38-
/// Utility class for parsing strings to other types.
39-
struct StringParser {
40-
/// Parse a string to another type.
41-
template <typename Ty> static bool parse(const char *Value, Ty &Result);
42-
};
43-
44-
/// Class for reading and checking environment variables. Currently working with
45-
/// integer, floats, std::string and bool types.
46-
template <typename Ty> class Envar {
47-
Ty Data;
48-
bool IsPresent;
49-
bool Initialized;
50-
51-
public:
52-
/// Auxiliary function to safely create envars. This static function safely
53-
/// creates envars using fallible constructors. See the constructors to know
54-
/// more details about the creation parameters.
55-
template <typename... ArgsTy>
56-
static Expected<Envar> create(ArgsTy &&...Args) {
57-
Error Err = Error::success();
58-
Envar Envar(std::forward<ArgsTy>(Args)..., Err);
59-
if (Err)
60-
return std::move(Err);
61-
return std::move(Envar);
62-
}
63-
64-
/// Create an empty envar. Cannot be consulted. This constructor is merely
65-
/// for convenience. This constructor is not fallible.
66-
Envar() : Data(Ty()), IsPresent(false), Initialized(false) {}
67-
68-
/// Create an envar with a name and an optional default. The Envar object will
69-
/// take the value read from the environment variable, or the default if it
70-
/// was not set or not correct. This constructor is not fallible.
71-
Envar(StringRef Name, Ty Default = Ty())
72-
: Data(Default), IsPresent(false), Initialized(true) {
73-
74-
if (const char *EnvStr = getenv(Name.data())) {
75-
// Check whether the envar is defined and valid.
76-
IsPresent = StringParser::parse<Ty>(EnvStr, Data);
77-
78-
if (!IsPresent) {
79-
DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data());
80-
Data = Default;
81-
}
82-
}
83-
}
84-
85-
Envar<Ty> &operator=(const Ty &V) {
86-
Data = V;
87-
Initialized = true;
88-
return *this;
89-
}
90-
91-
/// Get the definitive value.
92-
const Ty &get() const {
93-
// Throw a runtime error in case this envar is not initialized.
94-
if (!Initialized)
95-
FATAL_MESSAGE0(1, "Consulting envar before initialization");
96-
97-
return Data;
98-
}
99-
100-
/// Get the definitive value.
101-
operator Ty() const { return get(); }
102-
103-
/// Indicate whether the environment variable was defined and valid.
104-
bool isPresent() const { return IsPresent; }
105-
106-
private:
107-
/// This constructor should never fail but we provide it for convenience. This
108-
/// way, the constructor can be used by the Envar::create() static function
109-
/// to safely create this kind of envars.
110-
Envar(StringRef Name, Ty Default, Error &Err) : Envar(Name, Default) {
111-
ErrorAsOutParameter EAO(&Err);
112-
Err = Error::success();
113-
}
114-
115-
/// Create an envar with a name, getter function and a setter function. The
116-
/// Envar object will take the value read from the environment variable if
117-
/// this value is accepted by the setter function. Otherwise, the getter
118-
/// function will be executed to get the default value. The getter should be
119-
/// of the form Error GetterFunctionTy(Ty &Value) and the setter should
120-
/// be of the form Error SetterFunctionTy(Ty Value). This constructor has a
121-
/// private visibility because is a fallible constructor. Please use the
122-
/// Envar::create() static function to safely create this object instead.
123-
template <typename GetterFunctor, typename SetterFunctor>
124-
Envar(StringRef Name, GetterFunctor Getter, SetterFunctor Setter, Error &Err)
125-
: Data(Ty()), IsPresent(false), Initialized(true) {
126-
ErrorAsOutParameter EAO(&Err);
127-
Err = init(Name, Getter, Setter);
128-
}
129-
130-
template <typename GetterFunctor, typename SetterFunctor>
131-
Error init(StringRef Name, GetterFunctor Getter, SetterFunctor Setter);
132-
};
133-
134-
/// Define some common envar types.
135-
using IntEnvar = Envar<int>;
136-
using Int32Envar = Envar<int32_t>;
137-
using Int64Envar = Envar<int64_t>;
138-
using UInt32Envar = Envar<uint32_t>;
139-
using UInt64Envar = Envar<uint64_t>;
140-
using StringEnvar = Envar<std::string>;
141-
using BoolEnvar = Envar<bool>;
142-
14330
/// Utility class for thread-safe reference counting. Any class that needs
14431
/// objects' reference counting can inherit from this entity or have it as a
14532
/// class data member.
@@ -170,70 +57,6 @@ struct RefCountTy {
17057
std::atomic<Ty> Refs;
17158
};
17259

173-
template <>
174-
inline bool StringParser::parse(const char *ValueStr, bool &Result) {
175-
std::string Value(ValueStr);
176-
177-
// Convert the string to lowercase.
178-
std::transform(Value.begin(), Value.end(), Value.begin(),
179-
[](unsigned char c) { return std::tolower(c); });
180-
181-
// May be implemented with fancier C++ features, but let's keep it simple.
182-
if (Value == "true" || Value == "yes" || Value == "on" || Value == "1")
183-
Result = true;
184-
else if (Value == "false" || Value == "no" || Value == "off" || Value == "0")
185-
Result = false;
186-
else
187-
return false;
188-
189-
// Parsed correctly.
190-
return true;
191-
}
192-
193-
template <typename Ty>
194-
inline bool StringParser::parse(const char *Value, Ty &Result) {
195-
assert(Value && "Parsed value cannot be null");
196-
197-
std::istringstream Stream(Value);
198-
Stream >> Result;
199-
200-
return !Stream.fail();
201-
}
202-
203-
template <typename Ty>
204-
template <typename GetterFunctor, typename SetterFunctor>
205-
inline Error Envar<Ty>::init(StringRef Name, GetterFunctor Getter,
206-
SetterFunctor Setter) {
207-
// Get the default value.
208-
Ty Default;
209-
if (Error Err = Getter(Default))
210-
return Err;
211-
212-
if (const char *EnvStr = getenv(Name.data())) {
213-
IsPresent = StringParser::parse<Ty>(EnvStr, Data);
214-
if (IsPresent) {
215-
// Check whether the envar value is actually valid.
216-
Error Err = Setter(Data);
217-
if (Err) {
218-
// The setter reported an invalid value. Mark the user-defined value as
219-
// not present and reset to the getter value (default).
220-
IsPresent = false;
221-
Data = Default;
222-
DP("Setter of envar %s failed, resetting to %s\n", Name.data(),
223-
std::to_string(Data).data());
224-
consumeError(std::move(Err));
225-
}
226-
} else {
227-
DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data());
228-
Data = Default;
229-
}
230-
} else {
231-
Data = Default;
232-
}
233-
234-
return Error::success();
235-
}
236-
23760
/// Return the difference (in bytes) between \p Begin and \p End.
23861
template <typename Ty = char>
23962
ptrdiff_t getPtrDiff(const void *End, const void *Begin) {

0 commit comments

Comments
 (0)