aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-04-05 08:07:47 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-04-05 08:07:47 +0200
commit2905180c48e4b8974d4dee1949a00fc8e7bcafc6 (patch)
tree0dde0185bcbe36da05200c64ab12bb3b9af528c6 /libbuild2
parent8b9701d2ad76a9a571c445b318557261a4922758 (diff)
Allow creating context with bare minimum of initializations
This is used by bpkg to detect forwarded configurations without incurring the full context creation overhead.
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/adhoc-rule-cxx.cxx2
-rw-r--r--libbuild2/algorithm.cxx50
-rw-r--r--libbuild2/algorithm.ixx6
-rw-r--r--libbuild2/cc/compile-rule.cxx8
-rw-r--r--libbuild2/cc/link-rule.cxx4
-rw-r--r--libbuild2/context.cxx68
-rw-r--r--libbuild2/context.hxx17
-rw-r--r--libbuild2/context.ixx2
-rw-r--r--libbuild2/diagnostics.cxx14
-rw-r--r--libbuild2/module.cxx12
-rw-r--r--libbuild2/operation.cxx8
-rw-r--r--libbuild2/script/run.cxx2
-rw-r--r--libbuild2/test/rule.cxx32
-rw-r--r--libbuild2/test/script/parser.cxx26
-rw-r--r--libbuild2/variable.cxx4
-rw-r--r--libbuild2/variable.txx4
16 files changed, 153 insertions, 106 deletions
diff --git a/libbuild2/adhoc-rule-cxx.cxx b/libbuild2/adhoc-rule-cxx.cxx
index fbe967e..db5c5ab 100644
--- a/libbuild2/adhoc-rule-cxx.cxx
+++ b/libbuild2/adhoc-rule-cxx.cxx
@@ -302,7 +302,7 @@ namespace build2
//
auto_thread_env penv (nullptr);
context& ctx (*t.ctx.module_context);
- scheduler::phase_guard pg (ctx.sched);
+ scheduler::phase_guard pg (*ctx.sched);
uint16_t verbosity (3); // Project creation command verbosity.
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index 597ab6c..4489e2b 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -278,7 +278,7 @@ namespace build2
// unless we release the phase.
//
phase_unlock u (ct.ctx, true /* unlock */, true /* delay */);
- e = ctx.sched.wait (busy - 1, task_count, u, *wq);
+ e = ctx.sched->wait (busy - 1, task_count, u, *wq);
}
// We don't lock already applied or executed targets.
@@ -327,7 +327,7 @@ namespace build2
// this target.
//
task_count.store (offset + ctx.count_base (), memory_order_release);
- ctx.sched.resume (task_count);
+ ctx.sched->resume (task_count);
}
target&
@@ -1101,7 +1101,7 @@ namespace build2
// Also pass our diagnostics and lock stacks (this is safe since we
// expect the caller to wait for completion before unwinding its stack).
//
- if (ct.ctx.sched.async (
+ if (ct.ctx.sched->async (
start_count,
*task_count,
[a, try_match] (const diag_frame* ds,
@@ -2388,7 +2388,7 @@ namespace build2
target::offset_busy - target::offset_executed,
memory_order_release));
assert (tc == ctx.count_busy ());
- ctx.sched.resume (s.task_count);
+ ctx.sched->resume (s.task_count);
return ts;
}
@@ -2459,7 +2459,7 @@ namespace build2
: s.state;
s.task_count.store (exec, memory_order_release);
- ctx.sched.resume (s.task_count);
+ ctx.sched->resume (s.task_count);
}
else
{
@@ -2470,15 +2470,15 @@ namespace build2
// Pass our diagnostics stack (this is safe since we expect the
// caller to wait for completion before unwinding its diag stack).
//
- if (ctx.sched.async (start_count,
- *task_count,
- [a] (const diag_frame* ds, target& t)
- {
- diag_frame::stack_guard dsg (ds);
- execute_impl (a, t);
- },
- diag_frame::stack (),
- ref (t)))
+ if (ctx.sched->async (start_count,
+ *task_count,
+ [a] (const diag_frame* ds, target& t)
+ {
+ diag_frame::stack_guard dsg (ds);
+ execute_impl (a, t);
+ },
+ diag_frame::stack (),
+ ref (t)))
return target_state::unknown; // Queued.
// Executed synchronously, fall through.
@@ -2527,15 +2527,15 @@ namespace build2
r = execute_impl (a, t);
else
{
- if (ctx.sched.async (start_count,
- *task_count,
- [a] (const diag_frame* ds, target& t)
- {
- diag_frame::stack_guard dsg (ds);
- execute_impl (a, t);
- },
- diag_frame::stack (),
- ref (t)))
+ if (ctx.sched->async (start_count,
+ *task_count,
+ [a] (const diag_frame* ds, target& t)
+ {
+ diag_frame::stack_guard dsg (ds);
+ execute_impl (a, t);
+ },
+ diag_frame::stack (),
+ ref (t)))
return target_state::unknown; // Queued.
// Executed synchronously, fall through.
@@ -2551,7 +2551,7 @@ namespace build2
: s.state;
s.task_count.store (exec, memory_order_release);
- ctx.sched.resume (s.task_count);
+ ctx.sched->resume (s.task_count);
}
}
else
@@ -3096,7 +3096,7 @@ namespace build2
target_state gs (execute_impl (a, g, 0, nullptr));
if (gs == target_state::busy)
- ctx.sched.wait (ctx.count_executed (),
+ ctx.sched->wait (ctx.count_executed (),
g[a].task_count,
scheduler::work_none);
diff --git a/libbuild2/algorithm.ixx b/libbuild2/algorithm.ixx
index b87a535..6029290 100644
--- a/libbuild2/algorithm.ixx
+++ b/libbuild2/algorithm.ixx
@@ -753,7 +753,7 @@ namespace build2
if (r == target_state::busy)
{
- t.ctx.sched.wait (t.ctx.count_executed (),
+ t.ctx.sched->wait (t.ctx.count_executed (),
t[a].task_count,
scheduler::work_none);
@@ -789,7 +789,7 @@ namespace build2
// If the target is still busy, wait for its completion.
//
- ctx.sched.wait (ctx.count_executed (),
+ ctx.sched->wait (ctx.count_executed (),
t[a].task_count,
scheduler::work_none);
@@ -806,7 +806,7 @@ namespace build2
if (r == target_state::busy)
{
- t.ctx.sched.wait (t.ctx.count_executed (),
+ t.ctx.sched->wait (t.ctx.count_executed (),
t[a].task_count,
scheduler::work_none);
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx
index e76cb7c..7a357d9 100644
--- a/libbuild2/cc/compile-rule.cxx
+++ b/libbuild2/cc/compile-rule.cxx
@@ -3449,7 +3449,7 @@ namespace build2
msvc_sanitize_cl (args);
- psrc = ctx.fcache.create (t.path () + pext, !modules);
+ psrc = ctx.fcache->create (t.path () + pext, !modules);
if (fc)
{
@@ -3601,7 +3601,7 @@ namespace build2
// Preprocessor output.
//
- psrc = ctx.fcache.create (t.path () + pext, !modules);
+ psrc = ctx.fcache->create (t.path () + pext, !modules);
args.push_back ("-o");
args.push_back (psrc.path ().string ().c_str ());
}
@@ -3896,7 +3896,7 @@ namespace build2
if (modules && (ctype != compiler_type::msvc ||
md.type != unit_type::module_intf))
{
- result.first = ctx.fcache.create_existing (t.path () + pext);
+ result.first = ctx.fcache->create_existing (t.path () + pext);
result.second = true;
}
@@ -7521,7 +7521,7 @@ namespace build2
// Compressed preprocessed file extension.
//
- string cpext (t.ctx.fcache.compressed_extension (pext));
+ string cpext (t.ctx.fcache->compressed_extension (pext));
clean_extras extras;
switch (ctype)
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx
index f860fdc..490e0b4 100644
--- a/libbuild2/cc/link-rule.cxx
+++ b/libbuild2/cc/link-rule.cxx
@@ -3964,7 +3964,7 @@ namespace build2
auto i (find_option_prefix ("-flto", args.rbegin (), args.rend ()));
if (i != args.rend () && strcmp (*i, "-flto=auto") == 0)
{
- jobs_extra = scheduler::alloc_guard (ctx.sched, 0);
+ jobs_extra = scheduler::alloc_guard (*ctx.sched, 0);
jobs_arg = "-flto=" + to_string (1 + jobs_extra.n);
*i = jobs_arg.c_str ();
}
@@ -3983,7 +3983,7 @@ namespace build2
strcmp (*i, "-flto=thin") == 0 &&
!find_option_prefix ("-flto-jobs=", args))
{
- jobs_extra = scheduler::alloc_guard (ctx.sched, 0);
+ jobs_extra = scheduler::alloc_guard (*ctx.sched, 0);
jobs_arg = "-flto-jobs=" + to_string (1 + jobs_extra.n);
args.insert (i.base (), jobs_arg.c_str ()); // After -flto=thin.
}
diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx
index b7429e0..90c4f6c 100644
--- a/libbuild2/context.cxx
+++ b/libbuild2/context.cxx
@@ -86,9 +86,9 @@ namespace build2
optional<context*> mc,
const loaded_modules_lock* ml)
: data_ (new data (*this)),
- sched (s),
- mutexes (ms),
- fcache (fc),
+ sched (&s),
+ mutexes (&ms),
+ fcache (&fc),
match_only (mo),
no_external_modules (nem),
dry_run_option (dr),
@@ -111,6 +111,8 @@ namespace build2
? optional<unique_ptr<context>> (nullptr)
: nullopt)
{
+ // NOTE: see also the bare minimum version below if adding anything here.
+
tracer trace ("context");
l6 ([&]{trace << "initializing build state";});
@@ -673,6 +675,42 @@ namespace build2
}
context::
+ context ()
+ : data_ (new data (*this)),
+ sched (nullptr),
+ mutexes (nullptr),
+ fcache (nullptr),
+ match_only (false),
+ no_external_modules (true),
+ dry_run_option (false),
+ no_diag_buffer (false),
+ keep_going (false),
+ phase_mutex (*this),
+ scopes (data_->scopes),
+ targets (data_->targets),
+ var_pool (data_->var_pool),
+ var_patterns (data_->var_patterns),
+ var_overrides (data_->var_overrides),
+ functions (data_->functions),
+ global_scope (create_global_scope (data_->scopes)),
+ global_target_types (data_->global_target_types),
+ global_override_cache (data_->global_override_cache),
+ global_var_overrides (data_->global_var_overrides),
+ modules_lock (nullptr),
+ module_context (nullptr)
+ {
+ variable_pool& vp (data_->var_pool);
+
+ var_src_root = &vp.insert<dir_path> ("src_root");
+ var_out_root = &vp.insert<dir_path> ("out_root");
+
+ var_project = &vp.insert<project_name> ("project");
+ var_amalgamation = &vp.insert<dir_path> ("amalgamation");
+
+ load_generation = 1;
+ }
+
+ context::
~context ()
{
// Cannot be inline since context::data is undefined.
@@ -812,11 +850,11 @@ namespace build2
{
++contention; // Protected by m_.
- ctx_.sched.deactivate (false /* external */);
+ ctx_.sched->deactivate (false /* external */);
for (; ctx_.phase != n; v->wait (l)) ;
r = !fail_;
l.unlock (); // Important: activate() can block.
- ctx_.sched.activate (false /* external */);
+ ctx_.sched->activate (false /* external */);
}
else
r = !fail_;
@@ -828,9 +866,9 @@ namespace build2
{
if (!lm_.try_lock ())
{
- ctx_.sched.deactivate (false /* external */);
+ ctx_.sched->deactivate (false /* external */);
lm_.lock ();
- ctx_.sched.activate (false /* external */);
+ ctx_.sched->activate (false /* external */);
++contention_load; // Protected by lm_.
}
@@ -880,9 +918,9 @@ namespace build2
// relock().
//
if (o == run_phase::match && n == run_phase::execute)
- ctx_.sched.push_phase ();
+ ctx_.sched->push_phase ();
else if (o == run_phase::execute && n == run_phase::match)
- ctx_.sched.pop_phase ();
+ ctx_.sched->pop_phase ();
if (v != nullptr)
{
@@ -937,9 +975,9 @@ namespace build2
// unlock().
//
if (o == run_phase::match && n == run_phase::execute)
- ctx_.sched.push_phase ();
+ ctx_.sched->push_phase ();
else if (o == run_phase::execute && n == run_phase::match)
- ctx_.sched.pop_phase ();
+ ctx_.sched->pop_phase ();
// Notify others that could be waiting for this phase.
//
@@ -953,11 +991,11 @@ namespace build2
{
++contention; // Protected by m_.
- ctx_.sched.deactivate (false /* external */);
+ ctx_.sched->deactivate (false /* external */);
for (; ctx_.phase != n; v->wait (l)) ;
r = !fail_;
l.unlock (); // Important: activate() can block.
- ctx_.sched.activate (false /* external */);
+ ctx_.sched->activate (false /* external */);
}
}
@@ -972,9 +1010,9 @@ namespace build2
//
s = false;
- ctx_.sched.deactivate (false /* external */);
+ ctx_.sched->deactivate (false /* external */);
lm_.lock ();
- ctx_.sched.activate (false /* external */);
+ ctx_.sched->activate (false /* external */);
++contention_load; // Protected by lm_.
}
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index c040927..35ba11d 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -211,9 +211,11 @@ namespace build2
unique_ptr<data> data_;
public:
- scheduler& sched;
- global_mutexes& mutexes;
- file_cache& fcache;
+ // These are only NULL for the "bare minimum" context (see below).
+ //
+ scheduler* sched;
+ global_mutexes* mutexes;
+ file_cache* fcache;
// Match only flag (see --match-only but also dist).
//
@@ -677,7 +679,6 @@ namespace build2
reserves (size_t t, size_t v): targets (t), variables (v) {}
};
- explicit
context (scheduler&,
global_mutexes&,
file_cache&,
@@ -691,6 +692,14 @@ namespace build2
optional<context*> module_context = nullptr,
const loaded_modules_lock* inherited_mudules_lock = nullptr);
+ // Special context with bare minimum of initializations. It is only
+ // guaranteed to be sufficiently initialized to call extract_variable().
+ //
+ // Note that for this purpose you may omit calls to init_diag() and
+ // init().
+ //
+ context ();
+
// Reserve elements in containers to avoid re-allocation/re-hashing. Zero
// values are ignored (that is, the corresponding container reserve()
// function is not called). Can only be called in the load phase.
diff --git a/libbuild2/context.ixx b/libbuild2/context.ixx
index 95c5416..7b2a405 100644
--- a/libbuild2/context.ixx
+++ b/libbuild2/context.ixx
@@ -57,7 +57,7 @@ namespace build2
wait ()
{
phase_unlock u (*ctx, phase, true /* delay */);
- ctx->sched.wait (start_count, *task_count, u);
+ ctx->sched->wait (start_count, *task_count, u);
task_count = nullptr;
}
}
diff --git a/libbuild2/diagnostics.cxx b/libbuild2/diagnostics.cxx
index b31ff82..e164f10 100644
--- a/libbuild2/diagnostics.cxx
+++ b/libbuild2/diagnostics.cxx
@@ -18,11 +18,11 @@ using namespace butl;
namespace build2
{
- // Diagnostics state (verbosity level, progress, etc). Keep disabled until
- // set from options.
+ // Diagnostics state (verbosity level, progress, etc). Keep default/disabled
+ // until set from options.
//
- uint16_t verb = 0;
- bool silent = true;
+ uint16_t verb = 1;
+ bool silent = false;
optional<bool> diag_progress_option;
optional<bool> diag_color_option;
@@ -621,7 +621,7 @@ namespace build2
int diag_buffer::
pipe (context& ctx, bool force)
{
- return (ctx.sched.serial () || ctx.no_diag_buffer) && !force ? 2 : -1;
+ return (ctx.sched->serial () || ctx.no_diag_buffer) && !force ? 2 : -1;
}
void diag_buffer::
@@ -629,7 +629,7 @@ namespace build2
{
assert (state_ == state::closed && args0 != nullptr);
- serial = ctx_.sched.serial ();
+ serial = ctx_.sched->serial ();
nobuf = !serial && ctx_.no_diag_buffer;
if (fd != nullfd)
@@ -653,7 +653,7 @@ namespace build2
{
assert (state_ == state::closed && args0 != nullptr);
- serial = ctx_.sched.serial ();
+ serial = ctx_.sched->serial ();
nobuf = !serial && ctx_.no_diag_buffer;
this->args0 = args0;
state_ = state::eof;
diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx
index 234b469..0928307 100644
--- a/libbuild2/module.cxx
+++ b/libbuild2/module.cxx
@@ -81,9 +81,9 @@ namespace build2
// adding a reasonable margin for future growth.
//
ctx.module_context_storage->reset (
- new context (ctx.sched,
- ctx.mutexes,
- ctx.fcache,
+ new context (*ctx.sched,
+ *ctx.mutexes,
+ *ctx.fcache,
false, /* match_only */
false, /* no_external_modules */
false, /* dry_run */
@@ -144,8 +144,8 @@ namespace build2
// keep it in case things change. Actually, we may need it, if the
// scheduler was started up in a tuned state, like in bpkg).
//
- auto sched_tune (ctx.sched.serial ()
- ? scheduler::tune_guard (ctx.sched, 0)
+ auto sched_tune (ctx.sched->serial ()
+ ? scheduler::tune_guard (*ctx.sched, 0)
: scheduler::tune_guard ());
// Remap verbosity level 0 to 1 unless we were requested to be silent.
@@ -429,7 +429,7 @@ namespace build2
//
auto_thread_env penv (nullptr);
context& ctx (*bs.ctx.module_context);
- scheduler::phase_guard pg (ctx.sched);
+ scheduler::phase_guard pg (*ctx.sched);
// Load the imported project in the module context.
//
diff --git a/libbuild2/operation.cxx b/libbuild2/operation.cxx
index 2e5886c..d84db4f 100644
--- a/libbuild2/operation.cxx
+++ b/libbuild2/operation.cxx
@@ -278,11 +278,11 @@ namespace build2
// through a few hoops to make sure we don't overindulge.
//
md.incr = stderr_term // Scale depending on output type.
- ? (ctx.sched.serial () ? 1 : 5)
+ ? (ctx.sched->serial () ? 1 : 5)
: 100;
md.what = " targets to " + diag_do (ctx, a);
- mg = ctx.sched.monitor (
+ mg = ctx.sched->monitor (
ctx.target_count,
md.incr,
[&md] (size_t c) -> size_t
@@ -571,7 +571,7 @@ namespace build2
switch (ctx.current_inner_oif->concurrency)
{
- case 0: sched_tune = tune_guard (ctx.sched, 1); break; // Run serially.
+ case 0: sched_tune = tune_guard (*ctx.sched, 1); break; // Run serially.
case 1: break; // Run as is.
default: assert (false); // Not supported.
}
@@ -594,7 +594,7 @@ namespace build2
{
what = "% of targets " + diag_did (ctx, a);
- mg = ctx.sched.monitor (
+ mg = ctx.sched->monitor (
ctx.target_count,
init - incr,
[init, incr, &what, &ctx] (size_t c) -> size_t
diff --git a/libbuild2/script/run.cxx b/libbuild2/script/run.cxx
index 1106421..6d73a7e 100644
--- a/libbuild2/script/run.cxx
+++ b/libbuild2/script/run.cxx
@@ -2984,7 +2984,7 @@ namespace build2
// If/when required we could probably support the precise sleep
// mode (e.g., via an option).
//
- env.context.sched.sleep (t);
+ env.context.sched->sleep (t);
}
};
diff --git a/libbuild2/test/rule.cxx b/libbuild2/test/rule.cxx
index 2d02d39..81bf50a 100644
--- a/libbuild2/test/rule.cxx
+++ b/libbuild2/test/rule.cxx
@@ -563,22 +563,22 @@ namespace build2
{
scope_state& r (res.back ());
- if (!ctx.sched.async (ctx.count_busy (),
- t[a].task_count,
- [this] (const diag_frame* ds,
- scope_state& r,
- const target& t,
- const testscript& ts,
- const dir_path& wd)
- {
- diag_frame::stack_guard dsg (ds);
- r = perform_script_impl (t, ts, wd, *this);
- },
- diag_frame::stack (),
- ref (r),
- cref (t),
- cref (ts),
- cref (wd)))
+ if (!ctx.sched->async (ctx.count_busy (),
+ t[a].task_count,
+ [this] (const diag_frame* ds,
+ scope_state& r,
+ const target& t,
+ const testscript& ts,
+ const dir_path& wd)
+ {
+ diag_frame::stack_guard dsg (ds);
+ r = perform_script_impl (t, ts, wd, *this);
+ },
+ diag_frame::stack (),
+ ref (r),
+ cref (t),
+ cref (ts),
+ cref (wd)))
{
// Executed synchronously. If failed and we were not asked to
// keep going, bail out.
diff --git a/libbuild2/test/script/parser.cxx b/libbuild2/test/script/parser.cxx
index 60656a1..b712c21 100644
--- a/libbuild2/test/script/parser.cxx
+++ b/libbuild2/test/script/parser.cxx
@@ -1831,19 +1831,19 @@ namespace build2
// UBSan workaround.
//
const diag_frame* df (diag_frame::stack ());
- if (!ctx->sched.async (task_count,
- [] (const diag_frame* ds,
- scope& s,
- script& scr,
- runner& r)
- {
- diag_frame::stack_guard dsg (ds);
- execute_impl (s, scr, r);
- },
- df,
- ref (*chain),
- ref (*script_),
- ref (*runner_)))
+ if (!ctx->sched->async (task_count,
+ [] (const diag_frame* ds,
+ scope& s,
+ script& scr,
+ runner& r)
+ {
+ diag_frame::stack_guard dsg (ds);
+ execute_impl (s, scr, r);
+ },
+ df,
+ ref (*chain),
+ ref (*script_),
+ ref (*runner_)))
{
// Bail out if the scope has failed and we weren't instructed
// to keep going.
diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx
index d55737b..8c52e22 100644
--- a/libbuild2/variable.cxx
+++ b/libbuild2/variable.cxx
@@ -369,8 +369,8 @@ namespace build2
// Typification is kind of like caching so we reuse that mutex shard.
//
shared_mutex& m (
- ctx.mutexes.variable_cache[
- hash<value*> () (&v) % ctx.mutexes.variable_cache_size]);
+ ctx.mutexes->variable_cache[
+ hash<value*> () (&v) % ctx.mutexes->variable_cache_size]);
// Note: v.type is rechecked by typify() under lock.
//
diff --git a/libbuild2/variable.txx b/libbuild2/variable.txx
index 2950ea0..2c1265a 100644
--- a/libbuild2/variable.txx
+++ b/libbuild2/variable.txx
@@ -1019,8 +1019,8 @@ namespace build2
: 0);
shared_mutex& m (
- ctx.mutexes.variable_cache[
- hash<variable_cache*> () (this) % ctx.mutexes.variable_cache_size]);
+ ctx.mutexes->variable_cache[
+ hash<variable_cache*> () (this) % ctx.mutexes->variable_cache_size]);
slock sl (m);
ulock ul (m, defer_lock);