pub struct Client {
pub(crate) inner: Arc<Client>,
}
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.
Fields§
§inner: Arc<Client>
Implementations§
source§impl Client
impl Client
sourcepub fn new(limit: usize) -> Result<Client, Error>
pub fn new(limit: usize) -> Result<Client, Error>
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 Client::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
Client::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_ext(check_pipe: bool) -> FromEnv
pub unsafe fn from_env_ext(check_pipe: bool) -> FromEnv
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
Client::configure
function is required for a child process to have
access to a job server.
§Return value
FromEnv
contains result and relevant environment variable.
If a jobserver was found in the environment and it looks correct then
result with the connected client will be returned. In other cases
result will contain Err(FromEnvErr)
.
Additionally on Unix this function will configure the file descriptors
with CLOEXEC
so they’re not automatically inherited by spawned
children.
On unix if check_pipe
enabled this function will check if provided
files are actually pipes.
§Safety
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 is ok to call this function any number of times.
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.
Wraps Client::from_env_ext
and discards error details.
§Safety
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 is ok to call this function any number of times.
sourcepub fn acquire(&self) -> Result<Acquired, Error>
pub fn acquire(&self) -> Result<Acquired, Error>
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 try_acquire(&self) -> Result<Option<Acquired>, Error>
pub fn try_acquire(&self) -> Result<Option<Acquired>, Error>
Acquires a token from this jobserver client in a non-blocking way.
§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.
If non-blocking acquire is not supported, the return error will have its kind()
set to io::ErrorKind::Unsupported
.
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 Client::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 configure_make(&self, cmd: &mut Command)
pub fn configure_make(&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 Client::from_env
that
make
uses).
§Platform-specific behavior
On Unix and Windows this will clobber the CARGO_MAKEFLAGS
,
MAKEFLAGS
and MFLAGS
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, Error>
pub fn into_helper_thread<F>(self, f: F) -> Result<HelperThread, Error>
Converts this Client
into a helper thread to deal with a blocking
Client::acquire
function a little more easily.
The fact that the Client::acquire
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 Client::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<(), Error>
pub fn acquire_raw(&self) -> Result<(), Error>
Blocks the current thread until a token is acquired.
This is the same as Client::acquire
, except that it doesn’t return
an RAII helper. If successful the process will need to guarantee that
Client::release_raw
is called in the future.
sourcepub fn release_raw(&self) -> Result<(), Error>
pub fn release_raw(&self) -> Result<(), Error>
Releases a jobserver token back to the original jobserver.
This is intended to be paired with Client::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 DynSend for Client
impl Freeze for Client
impl RefUnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl UnwindSafe for Client
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§impl<T> Pointable for T
impl<T> Pointable for T
source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<'a, T> Captures<'a> for Twhere
T: ?Sized,
Layout§
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...)
attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.
Size: 8 bytes