aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-05-13 09:02:17 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-05-13 09:02:17 +0200
commitad9cdb9b172ecd7acf5e55b60f3f77626d72f14f (patch)
treebf26ce2bad2efdae443a03cbe7874621f4dc31cc
parenta77a968800ba36cb04fb58c73e768f5ec137b45c (diff)
Do lazy allocation of shadow task queues
-rw-r--r--libbuild2/scheduler.cxx12
-rw-r--r--libbuild2/scheduler.hxx3
-rw-r--r--libbuild2/scheduler.txx3
3 files changed, 11 insertions, 7 deletions
diff --git a/libbuild2/scheduler.cxx b/libbuild2/scheduler.cxx
index 8c0ea17..bdd703d 100644
--- a/libbuild2/scheduler.cxx
+++ b/libbuild2/scheduler.cxx
@@ -571,7 +571,8 @@ namespace build2
// phase helpers. The way we are going to do it is to temporarily (until
// pop) replace such queues with empty ones. This should be ok since a
// thread with such a "shadowed" queue won't wake up until we return to
- // the old phase.
+ // the old phase (but the shadow queue may be used if the thread in
+ // question is also switching to the new phase).
//
// Note also that the assumption here is that while we may still have
// "phase-less" threads milling around (e.g., transitioning from active to
@@ -589,13 +590,10 @@ namespace build2
if (tq.size != 0)
{
- queued_task_count_.fetch_sub (tq.size, memory_order_release);
-
- // @@ TODO: should we make task_queue::data allocation lazy? On the
- // other hand, we don't seem to get many non-empty queues here on
- // real-world projects.
+ // Note that task_queue::data will be allocated lazily (there is a
+ // good chance this queue is not going to be used in the new phase).
//
- j->data.reset (new task_data[task_queue_depth_]);
+ queued_task_count_.fetch_sub (tq.size, memory_order_release);
tq.swap (*j);
}
}
diff --git a/libbuild2/scheduler.hxx b/libbuild2/scheduler.hxx
index b85d353..da3f0c0 100644
--- a/libbuild2/scheduler.hxx
+++ b/libbuild2/scheduler.hxx
@@ -700,6 +700,9 @@ namespace build2
// tail, if enabled. If the mark is hit, then it is disabled until the
// queue becomes empty or it is reset by a push.
//
+ // Note also that the data array can be NULL (lazy allocation) and one
+ // must make sure it's allocated before calling push().
+ //
struct task_queue_data
{
size_t head = 0;
diff --git a/libbuild2/scheduler.txx b/libbuild2/scheduler.txx
index 9cfc411..5c6b339 100644
--- a/libbuild2/scheduler.txx
+++ b/libbuild2/scheduler.txx
@@ -54,6 +54,9 @@ namespace build2
if (tq->shutdown)
throw_generic_error (ECANCELED);
+ if (tq->data == nullptr)
+ tq->data.reset (new task_data[task_queue_depth_]);
+
if (task_data* td = push (*tq))
{
// Package the task (under lock).