From 977d07a3ae47ef204665d1eda2d642e5064724f3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 24 Jun 2019 12:01:19 +0200 Subject: Split build system into library and driver --- build2/variable.txx | 670 ---------------------------------------------------- 1 file changed, 670 deletions(-) delete mode 100644 build2/variable.txx (limited to 'build2/variable.txx') diff --git a/build2/variable.txx b/build2/variable.txx deleted file mode 100644 index 1aba99d..0000000 --- a/build2/variable.txx +++ /dev/null @@ -1,670 +0,0 @@ -// file : build2/variable.txx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -namespace build2 -{ - template - bool lookup:: - belongs (const T& x, bool t) const - { - if (vars == &x.vars) - return true; - - if (t) - { - for (const auto& p1: x.target_vars) // variable_type_map - { - for (const auto& p2: p1.second) // variable_pattern_map - { - if (vars == &p2.second) - return true; - } - } - } - - return false; - } - - // This one will be SFINAE'd out unless T is a simple value. - // - template - auto - convert (names&& ns) -> - decltype (value_traits::convert (move (ns[0]), nullptr)) - { - size_t n (ns.size ()); - - if (n == 0) - { - if (value_traits::empty_value) - return T (); - } - else if (n == 1) - { - return convert (move (ns[0])); - } - else if (n == 2 && ns[0].pair != '\0') - { - return convert (move (ns[0]), move (ns[1])); - } - - throw invalid_argument ( - string ("invalid ") + value_traits::type_name + - (n == 0 ? " value: empty" : " value: multiple names")); - } - - template - T - convert (value&& v) - { - if (v.type == nullptr) - return convert (move (v).as ()); - else if (v.type == &value_traits::value_type) - return move (v).as (); - - throw invalid_argument ( - string ("invalid ") + value_traits::value_type.name + - " value: conversion from " + v.type->name); - } - - template - void - default_dtor (value& v) - { - v.as ().~T (); - } - - template - void - default_copy_ctor (value& l, const value& r, bool m) - { - if (m) - new (&l.data_) T (move (const_cast (r).as ())); - else - new (&l.data_) T (r.as ()); - } - - template - void - default_copy_assign (value& l, const value& r, bool m) - { - if (m) - l.as () = move (const_cast (r).as ()); - else - l.as () = r.as (); - } - - template - bool - default_empty (const value& v) - { - return value_traits::empty (v.as ()); - } - - template - void - simple_assign (value& v, names&& ns, const variable* var) - { - size_t n (ns.size ()); - - if (value_traits::empty_value ? n <= 1 : n == 1) - { - try - { - value_traits::assign ( - v, - (n == 0 - ? T () - : value_traits::convert (move (ns.front ()), nullptr))); - - return; - } - catch (const invalid_argument&) {} // Fall through. - } - - diag_record dr (fail); - - dr << "invalid " << value_traits::value_type.name - << " value '" << ns << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - - template - void - simple_append (value& v, names&& ns, const variable* var) - { - size_t n (ns.size ()); - - if (value_traits::empty_value ? n <= 1 : n == 1) - { - try - { - value_traits::append ( - v, - (n == 0 - ? T () - : value_traits::convert (move (ns.front ()), nullptr))); - - return; - } - catch (const invalid_argument&) {} // Fall through. - } - - diag_record dr (fail); - - dr << "invalid " << value_traits::value_type.name - << " value '" << ns << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - - template - void - simple_prepend (value& v, names&& ns, const variable* var) - { - size_t n (ns.size ()); - - if (value_traits::empty_value ? n <= 1 : n == 1) - { - try - { - value_traits::prepend ( - v, - (n == 0 - ? T () - : value_traits::convert (move (ns.front ()), nullptr))); - - return; - } - catch (const invalid_argument&) {} // Fall through. - } - - diag_record dr (fail); - - dr << "invalid " << value_traits::value_type.name - << " value '" << ns << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - - template - names_view - simple_reverse (const value& v, names& s) - { - const T& x (v.as ()); - - // Represent an empty simple value as empty name sequence rather than - // a single empty name. This way, for example, during serialization we - // end up with a much saner looking: - // - // config.import.foo = - // - // Rather than: - // - // config.import.foo = {} - // - if (!value_traits::empty (x)) - s.emplace_back (value_traits::reverse (x)); - - return s; - } - - template - int - simple_compare (const value& l, const value& r) - { - return value_traits::compare (l.as (), r.as ()); - } - - // vector value - // - - template - vector value_traits>:: - convert (names&& ns) - { - vector v; - - // Similar to vector_append() below except we throw instead of issuing - // diagnostics. - // - for (auto i (ns.begin ()); i != ns.end (); ++i) - { - name& n (*i); - name* r (nullptr); - - if (n.pair) - { - r = &*++i; - - if (n.pair != '@') - throw invalid_argument ( - string ("invalid pair character: '") + n.pair + "'"); - } - - v.push_back (value_traits::convert (move (n), r)); - } - - return v; - } - - template - void - vector_append (value& v, names&& ns, const variable* var) - { - vector& p (v - ? v.as> () - : *new (&v.data_) vector ()); - - // Convert each element to T while merging pairs. - // - for (auto i (ns.begin ()); i != ns.end (); ++i) - { - name& n (*i); - name* r (nullptr); - - if (n.pair) - { - r = &*++i; - - if (n.pair != '@') - { - diag_record dr (fail); - - dr << "unexpected pair style for " - << value_traits::value_type.name << " value " - << "'" << n << "'" << n.pair << "'" << *r << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - } - - try - { - p.push_back (value_traits::convert (move (n), r)); - } - catch (const invalid_argument&) - { - diag_record dr (fail); - - dr << "invalid " << value_traits::value_type.name; - - if (n.pair) - dr << " element pair '" << n << "'@'" << *r << "'"; - else - dr << " element '" << n << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - } - } - - template - void - vector_assign (value& v, names&& ns, const variable* var) - { - if (v) - v.as> ().clear (); - - vector_append (v, move (ns), var); - } - - template - void - vector_prepend (value& v, names&& ns, const variable* var) - { - // Reduce to append. - // - vector t; - vector* p; - - if (v) - { - p = &v.as> (); - p->swap (t); - } - else - p = new (&v.data_) vector (); - - vector_append (v, move (ns), var); - - p->insert (p->end (), - make_move_iterator (t.begin ()), - make_move_iterator (t.end ())); - } - - template - static names_view - vector_reverse (const value& v, names& s) - { - auto& vv (v.as> ()); - s.reserve (vv.size ()); - - for (const T& x: vv) - s.push_back (value_traits::reverse (x)); - - return s; - } - - template - static int - vector_compare (const value& l, const value& r) - { - auto& lv (l.as> ()); - auto& rv (r.as> ()); - - auto li (lv.begin ()), le (lv.end ()); - auto ri (rv.begin ()), re (rv.end ()); - - for (; li != le && ri != re; ++li, ++ri) - if (int r = value_traits::compare (*li, *ri)) - return r; - - if (li == le && ri != re) // l shorter than r. - return -1; - - if (ri == re && li != le) // r shorter than l. - return 1; - - return 0; - } - - template - value_traits>::value_type_ex:: - value_type_ex (value_type&& v) - : value_type (move (v)) - { - type_name = value_traits::type_name; - type_name += 's'; - name = type_name.c_str (); - } - - template - const vector value_traits>::empty_instance; - - template - const typename value_traits>::value_type_ex - value_traits>::value_type = build2::value_type // VC14 wants =. - { - nullptr, // Patched above. - sizeof (vector), - nullptr, // No base. - &value_traits::value_type, - &default_dtor>, - &default_copy_ctor>, - &default_copy_assign>, - &vector_assign, - &vector_append, - &vector_prepend, - &vector_reverse, - nullptr, // No cast (cast data_ directly). - &vector_compare, - &default_empty> - }; - - // map value - // - template - void - map_append (value& v, names&& ns, const variable* var) - { - using std::map; - - map& p (v - ? v.as> () - : *new (&v.data_) map ()); - - // Verify we have a sequence of pairs and convert each lhs/rhs to K/V. - // - for (auto i (ns.begin ()); i != ns.end (); ++i) - { - name& l (*i); - - if (!l.pair) - { - diag_record dr (fail); - - dr << value_traits>::value_type.name << " key-value " - << "pair expected instead of '" << l << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - - name& r (*++i); // Got to have the second half of the pair. - - if (l.pair != '@') - { - diag_record dr (fail); - - dr << "unexpected pair style for " - << value_traits>::value_type.name << " key-value " - << "'" << l << "'" << l.pair << "'" << r << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - - try - { - K k (value_traits::convert (move (l), nullptr)); - - try - { - V v (value_traits::convert (move (r), nullptr)); - - p.emplace (move (k), move (v)); - } - catch (const invalid_argument&) - { - diag_record dr (fail); - - dr << "invalid " << value_traits::value_type.name - << " element value '" << r << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - } - catch (const invalid_argument&) - { - diag_record dr (fail); - - dr << "invalid " << value_traits::value_type.name - << " element key '" << l << "'"; - - if (var != nullptr) - dr << " in variable " << var->name; - } - } - } - - template - void - map_assign (value& v, names&& ns, const variable* var) - { - using std::map; - - if (v) - v.as> ().clear (); - - map_append (v, move (ns), var); - } - - template - static names_view - map_reverse (const value& v, names& s) - { - using std::map; - - auto& vm (v.as> ()); - s.reserve (2 * vm.size ()); - - for (const auto& p: vm) - { - s.push_back (value_traits::reverse (p.first)); - s.back ().pair = '@'; - s.push_back (value_traits::reverse (p.second)); - } - - return s; - } - - template - static int - map_compare (const value& l, const value& r) - { - using std::map; - - auto& lm (l.as> ()); - auto& rm (r.as> ()); - - auto li (lm.begin ()), le (lm.end ()); - auto ri (rm.begin ()), re (rm.end ()); - - for (; li != le && ri != re; ++li, ++ri) - { - int r; - if ((r = value_traits::compare (li->first, ri->first)) != 0 || - (r = value_traits::compare (li->second, ri->second)) != 0) - return r; - } - - if (li == le && ri != re) // l shorter than r. - return -1; - - if (ri == re && li != le) // r shorter than l. - return 1; - - return 0; - } - - template - value_traits>::value_type_ex:: - value_type_ex (value_type&& v) - : value_type (move (v)) - { - type_name = value_traits::type_name; - type_name += '_'; - type_name += value_traits::type_name; - type_name += "_map"; - name = type_name.c_str (); - } - - template - const std::map value_traits>::empty_instance; - - template - const typename value_traits>::value_type_ex - value_traits>::value_type = build2::value_type // VC14 wants = - { - nullptr, // Patched above. - sizeof (map), - nullptr, // No base. - nullptr, // No element. - &default_dtor>, - &default_copy_ctor>, - &default_copy_assign>, - &map_assign, - &map_append, - &map_append, // Prepend is the same as append. - &map_reverse, - nullptr, // No cast (cast data_ directly). - &map_compare, - &default_empty> - }; - - // variable_cache - // - template - pair variable_cache:: - insert (K k, const lookup& stem, size_t ver, const variable& var) - { - using value_data = variable_map::value_data; - - const variable_map* svars (stem.vars); // NULL if undefined. - size_t sver (stem.defined () - ? static_cast (stem.value)->version - : 0); - - shared_mutex& m ( - variable_cache_mutex_shard[ - hash () (this) % variable_cache_mutex_shard_size]); - - slock sl (m); - ulock ul (m, defer_lock); - - auto i (m_.find (k)); - - // Cache hit. - // - if (i != m_.end () && - i->second.version == ver && - i->second.stem_vars == svars && - i->second.stem_version == sver && - (var.type == nullptr || i->second.value.type == var.type)) - return pair (i->second.value, move (ul)); - - // Relock for exclusive access. Note that it is entirely possible - // that between unlock and lock someone else has updated the entry. - // - sl.unlock (); - ul.lock (); - - // Note that the cache entries are never removed so we can reuse the - // iterator. - // - pair p (i, i == m_.end ()); - - if (p.second) - p = m_.emplace (move (k), - entry_type {value_data (nullptr), ver, svars, sver}); - - entry_type& e (p.first->second); - - if (p.second) - { - // Cache miss. - // - e.value.version++; // New value. - } - else if (e.version != ver || - e.stem_vars != svars || - e.stem_version != sver) - { - // Cache invalidation. - // - assert (e.version <= ver); - e.version = ver; - - if (e.stem_vars != svars) - e.stem_vars = svars; - else - assert (e.stem_version <= sver); - - e.stem_version = sver; - - e.value.version++; // Value changed. - } - else - { - // Cache hit. - // - if (var.type != nullptr && e.value.type != var.type) - typify (e.value, *var.type, &var); - - ul.unlock (); - } - - return pair (e.value, move (ul)); - } -} -- cgit v1.1