pub struct Client { /* private fields */ }
Expand description
A client of a jobserver
This structure is the main type exposed by this library, and is where interaction to a jobserver is configured through. Clients are either created from scratch in which case the internal semphore is initialied on the spot, or a client is created from the environment to connect to a jobserver already created.
Some usage examples can be found in the crate documentation for using a client.
Note that a Client
implements the Clone
trait, and all instances of a
Client
refer to the same jobserver instance.
Implementations
sourceimpl Client
impl Client
sourcepub fn new(limit: usize) -> Result<Client>
pub fn new(limit: usize) -> Result<Client>
Creates a new jobserver initialized with the given parallelism limit.
A client to the jobserver created will be returned. This client will
allow at most limit
tokens to be acquired from it in parallel. More
calls to acquire
will cause the calling thread to block.
Note that the created Client
is not automatically inherited into
spawned child processes from this program. Manual usage of the
configure
function is required for a child process to have access to a
job server.
Examples
use jobserver::Client;
let client = Client::new(4).expect("failed to create jobserver");
Errors
Returns an error if any I/O error happens when attempting to create the jobserver client.
sourcepub unsafe fn from_env() -> Option<Client>
pub unsafe fn from_env() -> Option<Client>
Attempts to connect to the jobserver specified in this process’s environment.
When the a make
executable calls a child process it will configure the
environment of the child to ensure that it has handles to the jobserver
it’s passing down. This function will attempt to look for these details
and connect to the jobserver.
Note that the created Client
is not automatically inherited into
spawned child processes from this program. Manual usage of the
configure
function is required for a child process to have access to a
job server.
Return value
If a jobserver was found in the environment and it looks correct then
Some
of the connected client will be returned. If no jobserver was
found then None
will be returned.
Note that on Unix the Client
returned takes ownership of the file
descriptors specified in the environment. Jobservers on Unix are
implemented with pipe
file descriptors, and they’re inherited from
parent processes. This Client
returned takes ownership of the file
descriptors for this process and will close the file descriptors after
this value is dropped.
Additionally on Unix this function will configure the file descriptors
with CLOEXEC
so they’re not automatically inherited by spawned
children.
Unsafety
This function is unsafe
to call on Unix specifically as it
transitively requires usage of the from_raw_fd
function, which is
itself unsafe in some circumstances.
It’s recommended to call this function very early in the lifetime of a program before any other file descriptors are opened. That way you can make sure to take ownership properly of the file descriptors passed down, if any.
It’s generally unsafe to call this function twice in a program if the
previous invocation returned Some
.
Note, though, that on Windows it should be safe to call this function any number of times.
sourcepub fn acquire(&self) -> Result<Acquired>
pub fn acquire(&self) -> Result<Acquired>
Acquires a token from this jobserver client.
This function will block the calling thread until a new token can be acquired from the jobserver.
Return value
On successful acquisition of a token an instance of Acquired
is
returned. This structure, when dropped, will release the token back to
the jobserver. It’s recommended to avoid leaking this value.
Errors
If an I/O error happens while acquiring a token then this function will return immediately with the error. If an error is returned then a token was not acquired.
sourcepub fn configure(&self, cmd: &mut Command)
pub fn configure(&self, cmd: &mut Command)
Configures a child process to have access to this client’s jobserver as well.
This function is required to be called to ensure that a jobserver is
properly inherited to a child process. If this function is not called
then this Client
will not be accessible in the child process. In other
words, if not called, then Client::from_env
will return None
in the
child process (or the equivalent of Child::from_env
that make
uses).
Platform-specific behavior
On Unix and Windows this will clobber the CARGO_MAKEFLAGS
environment
variables for the child process, and on Unix this will also allow the
two file descriptors for this client to be inherited to the child.
On platforms other than Unix and Windows this panics.
sourcepub fn into_helper_thread<F>(self, f: F) -> Result<HelperThread> where
F: FnMut(Result<Acquired>) + Send + 'static,
pub fn into_helper_thread<F>(self, f: F) -> Result<HelperThread> where
F: FnMut(Result<Acquired>) + Send + 'static,
Converts this Client
into a helper thread to deal with a blocking
acquire
function a little more easily.
The fact that the acquire
function on Client
blocks isn’t always
the easiest to work with. Typically you’re using a jobserver to
manage running other events in parallel! This means that you need to
either (a) wait for an existing job to finish or (b) wait for a
new token to become available.
Unfortunately the blocking in acquire
happens at the implementation
layer of jobservers. On Unix this requires a blocking call to read
and on Windows this requires one of the WaitFor*
functions. Both
of these situations aren’t the easiest to deal with:
-
On Unix there’s basically only one way to wake up a
read
early, and that’s through a signal. This is what themake
implementation itself uses, relying onSIGCHLD
to wake up a blocking acquisition of a new job token. Unfortunately nonblocking I/O is not an option here, so it means that “waiting for one of two events” means that the latter event must generate a signal! This is not always the case on unix for all jobservers. -
On Windows you’d have to basically use the
WaitForMultipleObjects
which means that you’ve got to canonicalize all your event sources into aHANDLE
which also isn’t the easiest thing to do unfortunately.
This function essentially attempts to ease these limitations by
converting this Client
into a helper thread spawned into this
process. The application can then request that the helper thread
acquires tokens and the provided closure will be invoked for each token
acquired.
The intention is that this function can be used to translate the event of a token acquisition into an arbitrary user-defined event.
Arguments
This function will consume the Client
provided to be transferred to
the helper thread that is spawned. Additionally a closure f
is
provided to be invoked whenever a token is acquired.
This closure is only invoked after calls to
HelperThread::request_token
have been made and a token itself has
been acquired. If an error happens while acquiring the token then
an error will be yielded to the closure as well.
Return Value
This function will return an instance of the HelperThread
structure
which is used to manage the helper thread associated with this client.
Through the HelperThread
you’ll request that tokens are acquired.
When acquired, the closure provided here is invoked.
When the HelperThread
structure is returned it will be gracefully
torn down, and the calling thread will be blocked until the thread is
torn down (which should be prompt).
Errors
This function may fail due to creation of the helper thread or auxiliary I/O objects to manage the helper thread. In any of these situations the error is propagated upwards.
Platform-specific behavior
On Windows this function behaves pretty normally as expected, but on
Unix the implementation is… a little heinous. As mentioned above
we’re forced into blocking I/O for token acquisition, namely a blocking
call to read
. We must be able to unblock this, however, to tear down
the helper thread gracefully!
Essentially what happens is that we’ll send a signal to the helper
thread spawned and rely on EINTR
being returned to wake up the helper
thread. This involves installing a global SIGUSR1
handler that does
nothing along with sending signals to that thread. This may cause
odd behavior in some applications, so it’s recommended to review and
test thoroughly before using this.
sourcepub fn acquire_raw(&self) -> Result<()>
pub fn acquire_raw(&self) -> Result<()>
Blocks the current thread until a token is acquired.
This is the same as acquire
, except that it doesn’t return an RAII
helper. If successful the process will need to guarantee that
release_raw
is called in the future.
sourcepub fn release_raw(&self) -> Result<()>
pub fn release_raw(&self) -> Result<()>
Releases a jobserver token back to the original jobserver.
This is intended to be paired with acquire_raw
if it was called, but
in some situations it could also be called to relinquish a process’s
implicit token temporarily which is then re-acquired later.
Trait Implementations
Auto Trait Implementations
impl RefUnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl UnwindSafe for Client
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more