Define a custom call_once function, to avoid bugs requiring some Linux distribution to use pthread.

pull/255/head
Pierre Talbot 2 years ago
parent 630ab6a5c2
commit a212606a90
  1. 2
      README.md
  2. 43
      peglib.h

@ -39,8 +39,6 @@ The PEG syntax is well described on page 2 in the [document](http://www.brynosau
This library supports the linear-time parsing known as the [*Packrat*](http://pdos.csail.mit.edu/~baford/packrat/thesis/thesis.pdf) parsing.
IMPORTANT NOTE for some Linux distributions such as Ubuntu and CentOS: Need `-pthread` option when linking. See [#23](https://github.com/yhirose/cpp-peglib/issues/23#issuecomment-261126127), [#46](https://github.com/yhirose/cpp-peglib/issues/46#issuecomment-417870473) and [#62](https://github.com/yhirose/cpp-peglib/issues/62#issuecomment-492032680).
How to use
----------

@ -43,6 +43,23 @@
namespace peg {
/*-----------------------------------------------------------------------------
* call_once / once_flag
*---------------------------------------------------------------------------*/
// This is to avoid a bug where the exception `std::system_error` is thrown when the code is not linked with pthread.
// See issues #23, #46, #62.
using once_flag = bool;
template <class Callable, class... Args>
void call_once(once_flag& flag, Callable&& f) {
if(!flag) {
flag = true;
f();
}
}
/*-----------------------------------------------------------------------------
* scope_exit
*---------------------------------------------------------------------------*/
@ -921,7 +938,7 @@ public:
// Line info
std::pair<size_t, size_t> line_info(const char *cur) const {
std::call_once(source_line_index_init_, [this]() {
call_once(source_line_index_init_, [this]() {
for (size_t pos = 0; pos < l; pos++) {
if (s[pos] == '\n') { source_line_index.push_back(pos); }
}
@ -942,7 +959,7 @@ public:
size_t next_trace_id = 0;
std::vector<size_t> trace_ids;
bool ignore_trace_state = false;
mutable std::once_flag source_line_index_init_;
mutable once_flag source_line_index_init_;
mutable std::vector<size_t> source_line_index;
};
@ -1184,7 +1201,7 @@ public:
std::string lit_;
bool ignore_case_;
mutable std::once_flag init_is_word_;
mutable once_flag init_is_word_;
mutable bool is_word_;
};
@ -1410,7 +1427,7 @@ public:
std::shared_ptr<Ope> ope_;
Definition *outer_;
mutable std::once_flag trace_name_init_;
mutable once_flag trace_name_init_;
mutable std::string trace_name_;
friend class Definition;
@ -2320,7 +2337,7 @@ public:
std::shared_ptr<Ope> get_core_operator() const { return holder_->ope_; }
bool is_token() const {
std::call_once(is_token_init_, [this]() {
call_once(is_token_init_, [this]() {
is_token_ = TokenChecker::is_token(*get_core_operator());
});
return is_token_;
@ -2368,7 +2385,7 @@ private:
Definition &operator=(Definition &&rhs);
void initialize_definition_ids() const {
std::call_once(definition_ids_init_, [&]() {
call_once(definition_ids_init_, [&]() {
AssignIDToDefinition vis;
holder_->accept(vis);
if (whitespaceOpe) { whitespaceOpe->accept(vis); }
@ -2425,10 +2442,10 @@ private:
}
std::shared_ptr<Holder> holder_;
mutable std::once_flag is_token_init_;
mutable once_flag is_token_init_;
mutable bool is_token_ = false;
mutable std::once_flag assign_id_to_definition_init_;
mutable std::once_flag definition_ids_init_;
mutable once_flag assign_id_to_definition_init_;
mutable once_flag definition_ids_init_;
mutable std::unordered_map<void *, size_t> definition_ids_;
};
@ -2438,7 +2455,7 @@ private:
inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs,
Context &c, std::any &dt, const std::string &lit,
std::once_flag &init_is_word, bool &is_word,
once_flag &init_is_word, bool &is_word,
bool ignore_case) {
size_t i = 0;
for (; i < lit.size(); i++) {
@ -2456,7 +2473,7 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs,
auto se =
scope_exit([&]() { c.ignore_trace_state = save_ignore_trace_state; });
std::call_once(init_is_word, [&]() {
call_once(init_is_word, [&]() {
SemanticValues dummy_vs;
Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr,
nullptr, nullptr, false, nullptr);
@ -2810,7 +2827,7 @@ inline std::any Holder::reduce(SemanticValues &vs, std::any &dt) const {
inline const std::string &Holder::name() const { return outer_->name; }
inline const std::string &Holder::trace_name() const {
std::call_once(trace_name_init_,
call_once(trace_name_init_,
[this]() { trace_name_ = "[" + outer_->name + "]"; });
return trace_name_;
}
@ -2868,7 +2885,7 @@ inline size_t BackReference::parse_core(const char *s, size_t n,
const auto &cs = c.capture_scope_stack[index];
if (cs.find(name_) != cs.end()) {
const auto &lit = cs.at(name_);
std::once_flag init_is_word;
once_flag init_is_word;
auto is_word = false;
return parse_literal(s, n, vs, c, dt, lit, init_is_word, is_word, false);
}

Loading…
Cancel
Save