aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/scheduler.hxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-08-07 08:57:01 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-08-07 09:11:11 +0200
commit600da2b97e937b9c96791c291cb5e08cd8526bdd (patch)
tree400296b94672fca43c181d73705f81661cd4821f /libbuild2/scheduler.hxx
parenta39d7ae1aaa54a57df7f11e4ba12e2529286ea8c (diff)
Add ability to allocate additional active threads to current thread
Diffstat (limited to 'libbuild2/scheduler.hxx')
-rw-r--r--libbuild2/scheduler.hxx71
1 files changed, 70 insertions, 1 deletions
diff --git a/libbuild2/scheduler.hxx b/libbuild2/scheduler.hxx
index b7bc3c5..7e052cd 100644
--- a/libbuild2/scheduler.hxx
+++ b/libbuild2/scheduler.hxx
@@ -159,6 +159,72 @@ namespace build2
static void
active_sleep (const duration&);
+ // Allocate additional active thread count to the current active thread,
+ // for example, to be "passed" to an external program:
+ //
+ // scheduler::alloc_guard ag (ctx.sched, ctx.sched.max_active () / 2);
+ // args.push_back ("-flto=" + to_string (1 + ag.n));
+ // run (args);
+ // ag.deallocate ();
+ //
+ // The allocate() function reserves up to the specified number of
+ // additional threads returning the number actually allocated (which can
+ // be less than requested, including 0). If 0 is specified, then it
+ // allocates all the currently available threads.
+ //
+ // The deallocate() function returns the specified number of previously
+ // allocated threads back to the active thread pool.
+ //
+ // Note that when the thread is deactivated (directly or indirectly via
+ // wait, phase switching, etc), the additionally allocated threads are
+ // considered to be still active (this semantics could be changed if we
+ // have a plausible scenario for where waiting, etc., with allocated
+ // threads is useful).
+ //
+ size_t
+ allocate (size_t);
+
+ void
+ deallocate (size_t);
+
+ struct alloc_guard
+ {
+ size_t n;
+
+ alloc_guard (): n (0), s_ (nullptr) {}
+ alloc_guard (scheduler& s, size_t m): n (s.allocate (m)), s_ (&s) {}
+ alloc_guard (alloc_guard&& x): n (x.n), s_ (x.s_) {x.s_ = nullptr;}
+ alloc_guard& operator= (alloc_guard&& x)
+ {
+ if (&x != this)
+ {
+ n = x.n;
+ s_ = x.s_;
+ x.s_ = nullptr;
+ }
+ return *this;
+ }
+
+ ~alloc_guard ()
+ {
+ if (s_ != nullptr && n != 0)
+ s_->deallocate (n);
+ }
+
+ void
+ deallocate ()
+ {
+ if (n != 0)
+ {
+ s_->deallocate (n);
+ n = 0;
+ }
+ }
+
+ private:
+ scheduler* s_;
+ };
+
// Startup and shutdown.
//
public:
@@ -248,13 +314,16 @@ namespace build2
size_t o_;
};
- // Return true if the scheduler is configured to run tasks serially.
+ // Return scheduler configuration.
//
// Note: can only be called from threads that have observed startup.
//
bool
serial () const {return max_active_ == 1;}
+ size_t
+ max_active () const {return max_active_;}
+
// Wait for all the helper threads to terminate. Throw system_error on
// failure. Note that the initially active threads are not waited for.
// Return scheduling statistics.