## [Scheduling](#Scheduling)
Add a [`Task`](#Core.Task) to the scheduler's queue. This causes the task to run constantly when the system is otherwise idle, unless the task performs a blocking operation such as [`wait`](#Base.wait).
If a second argument `val` is provided, it will be passed to the task (via the return value of [`yieldto`](#Base.yieldto)) when it runs again. If `error` is `true`, the value is raised as an exception in the woken task.
It is incorrect to use `schedule` on an arbitrary `Task` that has already been started. See [the API reference](#low-level-schedule-wait) for more information.
By default tasks will have the sticky bit set to true `t.sticky`. This models the historic default for [`@async`](#Base.@async). Sticky tasks can only be run on the worker thread they are first scheduled on, and when scheduled will make the task that they were scheduled from sticky. To obtain the behavior of [`Threads.@spawn`](../multi-threading/#Base.Threads.@spawn) set the sticky bit manually to `false`.
**Examples**
```julia-repl
julia> a5() = sum(i for i in 1:1000);

julia> b = Task(a5);

julia> istaskstarted(b)
false

julia> schedule(b);

julia> yield();

julia> istaskstarted(b)
true

julia> istaskdone(b)
true
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/task.jl#L835-L875)


## [Synchronization](#lib-task-sync)
```julia
errormonitor(t::Task)
```
Print an error log to `stderr` if task `t` fails.
**Examples**
```julia-repl
julia> Base._wait(errormonitor(Threads.@spawn error("task failed")))
Unhandled Task ERROR: task failed
Stacktrace:
[...]
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/task.jl#L579-L591)
```julia
@sync
```
Wait until all lexically-enclosed uses of [`@async`](#Base.@async), [`@spawn`](../multi-threading/#Base.Threads.@spawn), `Distributed.@spawnat` and `Distributed.@distributed` are complete. All exceptions thrown by enclosed async operations are collected and thrown as a [`CompositeException`](../base/#Base.CompositeException).
**Examples**
```julia-repl
julia> Threads.nthreads()
4

julia> @sync begin
           Threads.@spawn println("Thread-id $(Threads.threadid()), task 1")
           Threads.@spawn println("Thread-id $(Threads.threadid()), task 2")
       end;
Thread-id 3, task 1
Thread-id 1, task 2
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/task.jl#L473-L493)
Special note for [`Threads.Condition`](#Base.Threads.Condition):
The caller must be holding the [`lock`](#Base.lock) that owns a `Threads.Condition` before calling this method. The calling task will be blocked until some other task wakes it, usually by calling [`notify`](#Base.notify) on the same `Threads.Condition` object. The lock will be atomically released when blocking (even if it was locked recursively), and will be reacquired before returning.


## [Synchronization](#lib-task-sync)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L381-L389)
```julia
wait(r::Future)
```
Wait for a value to become available for the specified [`Future`](../../stdlib/Future/#Future).
```julia
wait(r::RemoteChannel, args...)
```
Wait for a value to become available on the specified [`RemoteChannel`](../../stdlib/Distributed/#Distributed.RemoteChannel).
```julia
wait([x])
```
Block the current task until some event occurs, depending on the type of the argument:
-   [`Channel`](#Base.Channel): Wait for a value to be appended to the channel.
-   [`Condition`](#Base.Condition): Wait for [`notify`](#Base.notify) on a condition and return the `val` parameter passed to `notify`. Waiting on a condition additionally allows passing `first=true` which results in the waiter being put *first* in line to wake up on `notify` instead of the usual first-in-first-out behavior.
-   `Process`: Wait for a process or process chain to exit. The `exitcode` field of a process can be used to determine success or failure.
-   [`Task`](#Core.Task): Wait for a `Task` to finish. If the task fails with an exception, a `TaskFailedException` (which wraps the failed task) is thrown.
-   [`RawFD`](../file/#Base.Libc.RawFD): Wait for changes on a file descriptor (see the `FileWatching` package).
If no argument is passed, the task blocks for an undefined period. A task can only be restarted by an explicit call to [`schedule`](#Base.schedule) or [`yieldto`](#Base.yieldto).


## [Synchronization](#lib-task-sync)
Often `wait` is called within a `while` loop to ensure a waited-for condition is met before proceeding.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/condition.jl#L103-L124)
```julia
wait(c::Channel)
```
Blocks until the `Channel` [`isready`](#Base.isready-Tuple%7BChannel%7D).
```julia-repl
julia> c = Channel(1);

julia> isready(c)
false

julia> task = Task(() -> wait(c));

julia> schedule(task);

julia> istaskdone(task)  # task is blocked because channel is not ready
false

julia> put!(c, 1);

julia> istaskdone(task)  # task is now unblocked
true
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L567-L590)
```julia
fetch(t::Task)
```
Wait for a [`Task`](#Core.Task) to finish, then return its result value. If the task fails with an exception, a [`TaskFailedException`](../base/#Base.TaskFailedException) (which wraps the failed task) is thrown.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/task.jl#L382-L388)
```julia
fetch(x::Any)
```
Return `x`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/task.jl#L375-L379)
```julia
timedwait(testcb, timeout::Real; pollint::Real=0.1)
```
Wait until `testcb()` returns `true` or `timeout` seconds have passed, whichever is earlier. The test function is polled every `pollint` seconds. The minimum value for `pollint` is 0.001 seconds, that is, 1 millisecond.
Return `:ok` or `:timed_out`.
**Examples**


## [Synchronization](#lib-task-sync)
```julia-repl
julia> cb() = (sleep(5); return);

julia> t = @async cb();

julia> timedwait(()->istaskdone(t), 1)
:timed_out

julia> timedwait(()->istaskdone(t), 6.5)
:ok
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/asyncevent.jl#L334-L355)
```julia
Condition()
```
Create an edge-triggered event source that tasks can wait for. Tasks that call [`wait`](#Base.wait) on a `Condition` are suspended and queued. Tasks are woken up when [`notify`](#Base.notify) is later called on the `Condition`. Waiting on a condition can return a value or raise an error if the optional arguments of [`notify`](#Base.notify) are used. Edge triggering means that only tasks waiting at the time [`notify`](#Base.notify) is called can be woken up. For level-triggered notifications, you must keep extra state to keep track of whether a notification has happened. The [`Channel`](#Base.Channel) and [`Threads.Event`](#Base.Event) types do this, and can be used for level-triggered events.
This object is NOT thread-safe. See [`Threads.Condition`](#Base.Threads.Condition) for a thread-safe version.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/condition.jl#L173-L185)
```julia
Threads.Condition([lock])
```
A thread-safe version of [`Base.Condition`](#Base.Condition).


## [Synchronization](#lib-task-sync)
To call [`wait`](#Base.wait) or [`notify`](#Base.notify) on a `Threads.Condition`, you must first call [`lock`](#Base.lock) on it. When `wait` is called, the lock is atomically released during blocking, and will be reacquired before `wait` returns. Therefore idiomatic use of a `Threads.Condition` `c` looks like the following:
```julia
lock(c)
try
    while !thing_we_are_waiting_for
        wait(c)
    end
finally
    unlock(c)
end
```
This functionality requires at least Julia 1.2.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L355-L378)
```julia
Event([autoreset=false])
```
Create a level-triggered event source. Tasks that call [`wait`](#Base.wait) on an `Event` are suspended and queued until [`notify`](#Base.notify) is called on the `Event`. After `notify` is called, the `Event` remains in a signaled state and tasks will no longer block when waiting for it, until `reset` is called.
If `autoreset` is true, at most one task will be released from `wait` for each call to `notify`.
This provides an acquire & release memory ordering on notify/wait.
This functionality requires at least Julia 1.1.
The `autoreset` functionality and memory ordering guarantee requires at least Julia 1.8.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L481-L499)
```julia
notify(condition, val=nothing; all=true, error=false)
```


## [Synchronization](#lib-task-sync)
Wake up tasks waiting for a condition, passing them `val`. If `all` is `true` (the default), all waiting tasks are woken, otherwise only one is. If `error` is `true`, the passed value is raised as an exception in the woken tasks.
Return the count of tasks woken up. Return 0 if no tasks are waiting on `condition`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/condition.jl#L139-L147)
```julia
reset(::Event)
```
Reset an [`Event`](#Base.Event) back into an un-set state. Then any future calls to `wait` will block until [`notify`](#Base.notify) is called again.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L544-L549)
```julia
Semaphore(sem_size)
```
Create a counting semaphore that allows at most `sem_size` acquires to be in use at any time. Each acquire must be matched with a release.
This provides a acquire & release memory ordering on acquire/release calls.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L393-L401)
```julia
acquire(s::Semaphore)
```
Wait for one of the `sem_size` permits to be available, blocking until one can be acquired.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L409-L414)
```julia
acquire(f, s::Semaphore)
```
Execute `f` after acquiring from Semaphore `s`, and `release` on completion or error.
For example, a do-block form that ensures only 2 calls of `foo` will be active at the same time:


## [Synchronization](#lib-task-sync)
```julia
s = Base.Semaphore(2)
@sync for _ in 1:100
    Threads.@spawn begin
        Base.acquire(s) do
            foo()
        end
    end
end
```
This method requires at least Julia 1.8.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L428-L451)
```julia
release(s::Semaphore)
```
Return one permit to the pool, possibly allowing another task to acquire it and resume execution.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L461-L467)
```julia
AbstractLock
```
Abstract supertype describing types that implement the synchronization primitives: [`lock`](#Base.lock), [`trylock`](#Base.trylock), [`unlock`](#Base.unlock), and [`islocked`](#Base.islocked).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/condition.jl#L11-L17)
```julia
lock(lock)
```
Acquire the `lock` when it becomes available. If the lock is already locked by a different task/thread, wait for it to become available.
Each `lock` must be matched by an [`unlock`](#Base.unlock).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L137-L145)
```julia
lock(f::Function, lock)
```
Acquire the `lock`, execute `f` with the `lock` held, and release the `lock` when `f` returns. If the lock is already locked by a different task/thread, wait for it to become available.
When this function returns, the `lock` has been released, so the caller should not attempt to `unlock` it.


## [Synchronization](#lib-task-sync)
See also: [`@lock`](#Base.@lock).
Using a [`Channel`](#Base.Channel) as the second argument requires Julia 1.7 or later.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L214-L228)
```julia
lock(f::Function, l::Lockable)
```
Acquire the lock associated with `l`, execute `f` with the lock held, and release the lock when `f` returns. `f` will receive one positional argument: the value wrapped by `l`. If the lock is already locked by a different task/thread, wait for it to become available. When this function returns, the `lock` has been released, so the caller should not attempt to `unlock` it.
Requires at least Julia 1.11.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L330-L342)
```julia
unlock(lock)
```
Releases ownership of the `lock`.
If this is a recursive lock which has been acquired before, decrement an internal counter and return immediately.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L167-L174)
```julia
trylock(lock) -> Success (Boolean)
```
Acquire the lock if it is available, and return `true` if successful. If the lock is already locked by a different task/thread, return `false`.
Each successful `trylock` must be matched by an [`unlock`](#Base.unlock).


## [Synchronization](#lib-task-sync)
Function `trylock` combined with [`islocked`](#Base.islocked) can be used for writing the test-and-test-and-set or exponential backoff algorithms *if it is supported by the `typeof(lock)`* (read its documentation).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L97-L110)
```julia
islocked(lock) -> Status (Boolean)
```
Check whether the `lock` is held by any task/thread. This function alone should not be used for synchronization. However, `islocked` combined with [`trylock`](#Base.trylock) can be used for writing the test-and-test-and-set or exponential backoff algorithms *if it is supported by the `typeof(lock)`* (read its documentation).
**Extended help**
For example, an exponential backoff can be implemented as follows if the `lock` implementation satisfied the properties documented below.
```julia
nspins = 0
while true
    while islocked(lock)
        GC.safepoint()
        nspins += 1
        nspins > LIMIT && error("timeout")
    end
    trylock(lock) && break
    backoff()
end
```
**Implementation**
A lock implementation is advised to define `islocked` with the following properties and note it in its docstring.
-   `islocked(lock)` is data-race-free.
-   If `islocked(lock)` returns `false`, an immediate invocation of `trylock(lock)` must succeed (returns `true`) if there is no interference from other tasks.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L54-L88)
```julia
ReentrantLock()
```


## [Synchronization](#lib-task-sync)
Creates a re-entrant lock for synchronizing [`Task`](#Core.Task)s. The same task can acquire the lock as many times as required (this is what the "Reentrant" part of the name means). Each [`lock`](#Base.lock) must be matched with an [`unlock`](#Base.unlock).
Calling `lock` will also inhibit running of finalizers on that thread until the corresponding `unlock`. Use of the standard lock pattern illustrated below should naturally be supported, but beware of inverting the try/lock order or missing the try block entirely (e.g. attempting to return with the lock still held):
This provides a acquire/release memory ordering on lock/unlock calls.
```julia
lock(l)
try
    <atomic work>
finally
    unlock(l)
end
```
If [`!islocked(lck::ReentrantLock)`](#Base.islocked) holds, [`trylock(lck)`](#Base.trylock) succeeds unless there are other tasks attempting to hold the lock "at the same time."
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L6-L32)
```julia
@lock l expr
```
Macro version of `lock(f, l::AbstractLock)` but with `expr` instead of `f` function. Expands to:
```julia
lock(l)
try
    expr
finally
    unlock(l)
end
```
This is similar to using [`lock`](#Base.lock) with a `do` block, but avoids creating a closure and thus can improve the performance.
`@lock` was added in Julia 1.3, and exported in Julia 1.10.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L249-L267)
```julia
Lockable(value, lock = ReentrantLock())
```


## [Synchronization](#lib-task-sync)
Creates a `Lockable` object that wraps `value` and associates it with the provided `lock`. This object supports [`@lock`](#Base.@lock), [`lock`](#Base.lock), [`trylock`](#Base.trylock), [`unlock`](#Base.unlock). To access the value, index the lockable object while holding the lock.
Requires at least Julia 1.11.
**Example**
```julia-repl
julia> locked_list = Base.Lockable(Int[]);

julia> @lock(locked_list, push!(locked_list[], 1)) # must hold the lock to access the value
1-element Vector{Int64}:
 1

julia> lock(summary, locked_list)
"1-element Vector{Int64}"
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/lock.jl#L297-L321)


## [Channels](#Channels)
```julia
AbstractChannel{T}
```
Representation of a channel passing objects of type `T`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L3-L7)
```julia
Channel{T=Any}(size::Int=0)
```
Constructs a `Channel` with an internal buffer that can hold a maximum of `size` objects of type `T`. [`put!`](#Base.put!-Tuple%7BChannel,%20Any%7D) calls on a full channel block until an object is removed with [`take!`](../io-network/#Base.take!-Tuple%7BBase.GenericIOBuffer%7D).
`Channel(0)` constructs an unbuffered channel. `put!` blocks until a matching `take!` is called. And vice-versa.
Other constructors:
-   `Channel()`: default constructor, equivalent to `Channel{Any}(0)`
-   `Channel(Inf)`: equivalent to `Channel{Any}(typemax(Int))`
-   `Channel(sz)`: equivalent to `Channel{Any}(sz)`
The default constructor `Channel()` and default `size=0` were added in Julia 1.3.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L13-L31)
```julia
Channel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false, threadpool=nothing)
```
Create a new task from `func`, [`bind`](../../stdlib/Sockets/#Base.bind) it to a new channel of type `T` and size `size`, and schedule the task, all in a single call. The channel is automatically closed when the task terminates.
`func` must accept the bound channel as its only argument.
If you need a reference to the created task, pass a `Ref{Task}` object via the keyword argument `taskref`.


## [Channels](#Channels)
If `spawn=true`, the `Task` created for `func` may be scheduled on another thread in parallel, equivalent to creating a task via [`Threads.@spawn`](../multi-threading/#Base.Threads.@spawn).
If `spawn=true` and the `threadpool` argument is not set, it defaults to `:default`.
If the `threadpool` argument is set (to `:default` or `:interactive`), this implies that `spawn=true` and the new Task is spawned to the specified threadpool.
Return a `Channel`.
**Examples**
```julia-repl
julia> chnl = Channel() do ch
           foreach(i -> put!(ch, i), 1:4)
       end;

julia> typeof(chnl)
Channel{Any}

julia> for i in chnl
           @show i
       end;
i = 1
i = 2
i = 3
i = 4
```
Referencing the created task:
```julia-repl
julia> taskref = Ref{Task}();

julia> chnl = Channel(taskref=taskref) do ch
           println(take!(ch))
       end;

julia> istaskdone(taskref[])
false

julia> put!(chnl, "Hello");
Hello

julia> istaskdone(taskref[])
true
```
The `spawn=` parameter was added in Julia 1.3. This constructor was added in Julia 1.3. In earlier versions of Julia, Channel used keyword arguments to set `size` and `T`, but those constructors are deprecated.
The `threadpool=` argument was added in Julia 1.9.
```julia-repl
julia> chnl = Channel{Char}(1, spawn=true) do ch
           for c in "hello world"
               put!(ch, c)
           end
       end
Channel{Char}(1) (2 items available)

julia> String(collect(chnl))
"hello world"
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L61-L139)


## [Channels](#Channels)
```julia
put!(c::Channel, v)
```
Append an item `v` to the channel `c`. Blocks if the channel is full.
For unbuffered channels, blocks until a [`take!`](../io-network/#Base.take!-Tuple%7BBase.GenericIOBuffer%7D) is performed by a different task.
`v` now gets converted to the channel's type with [`convert`](../base/#Base.convert) as `put!` is called.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L344-L354)
```julia
take!(c::Channel)
```
Removes and returns a value from a [`Channel`](#Base.Channel) in order. Blocks until data is available. For unbuffered channels, blocks until a [`put!`](#Base.put!-Tuple%7BChannel,%20Any%7D) is performed by a different task.
**Examples**
Buffered channel:
```julia-repl
julia> c = Channel(1);

julia> put!(c, 1);

julia> take!(c)
1
```
Unbuffered channel:
```julia-repl
julia> c = Channel(0);

julia> task = Task(() -> put!(c, 1));

julia> schedule(task);

julia> take!(c)
1
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L457-L486)
```julia
isready(c::Channel)
```
Determines whether a [`Channel`](#Base.Channel) has a value stored in it. Returns immediately, does not block.
For unbuffered channels returns `true` if there are tasks waiting on a [`put!`](#Base.put!-Tuple%7BChannel,%20Any%7D).
**Examples**
Buffered channel:
```julia-repl
julia> c = Channel(1);

julia> isready(c)
false

julia> put!(c, 1);

julia> isready(c)
true
```
Unbuffered channel:


## [Channels](#Channels)
```julia-repl
julia> c = Channel();

julia> isready(c)  # no tasks waiting to put!
false

julia> task = Task(() -> put!(c, 1));

julia> schedule(task);  # schedule a put! task

julia> isready(c)
true
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L516-L554)
```julia
fetch(c::Channel)
```
Waits for and returns (without removing) the first available item from the `Channel`. Note: `fetch` is unsupported on an unbuffered (0-size) `Channel`.
**Examples**
Buffered channel:
```julia-repl
julia> c = Channel(3) do ch
           foreach(i -> put!(ch, i), 1:3)
       end;

julia> fetch(c)
1

julia> collect(c)  # item is not removed
3-element Vector{Any}:
 1
 2
 3
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L417-L440)
```julia
close(c::Channel[, excp::Exception])
```
Close a channel. An exception (optionally given by `excp`), is thrown by:
-   [`put!`](#Base.put!-Tuple%7BChannel,%20Any%7D) on a closed channel.
-   [`take!`](../io-network/#Base.take!-Tuple%7BBase.GenericIOBuffer%7D) and [`fetch`](#Base.fetch-Tuple%7BTask%7D) on an empty, closed channel.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L192-L199)
```julia
bind(chnl::Channel, task::Task)
```
Associate the lifetime of `chnl` with a task. `Channel` `chnl` is automatically closed when the task terminates. Any uncaught exception in the task is propagated to all waiters on `chnl`.


## [Channels](#Channels)
The `chnl` object can be explicitly closed independent of task termination. Terminating tasks have no effect on already closed `Channel` objects.
When a channel is bound to multiple tasks, the first task to terminate will close the channel. When multiple channels are bound to the same task, termination of the task will close all of the bound channels.
**Examples**
```julia-repl
julia> c = Channel(0);

julia> task = @async foreach(i->put!(c, i), 1:4);

julia> bind(c,task);

julia> for i in c
           @show i
       end;
i = 1
i = 2
i = 3
i = 4

julia> isopen(c)
false
```
```julia-repl
julia> c = Channel(0);

julia> task = @async (put!(c, 1); error("foo"));

julia> bind(c, task);

julia> take!(c)
1

julia> put!(c, 1);
ERROR: TaskFailedException
Stacktrace:
[...]
    nested task error: foo
[...]
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/channels.jl#L237-L288)


## [Low-level synchronization using schedule and wait](#low-level-schedule-wait)
The easiest correct use of [`schedule`](#Base.schedule) is on a `Task` that is not started (scheduled) yet. However, it is possible to use [`schedule`](#Base.schedule) and [`wait`](#Base.wait) as a very low-level building block for constructing synchronization interfaces. A crucial pre-condition of calling `schedule(task)` is that the caller must "own" the `task`; i.e., it must know that the call to `wait` in the given `task` is happening at the locations known to the code calling `schedule(task)`. One strategy for ensuring such pre-condition is to use atomics, as demonstrated in the following example:


## [Low-level synchronization using schedule and wait](#low-level-schedule-wait)
```julia
@enum OWEState begin
    OWE_EMPTY
    OWE_WAITING
    OWE_NOTIFYING
end

mutable struct OneWayEvent
    @atomic state::OWEState
    task::Task
    OneWayEvent() = new(OWE_EMPTY)
end

function Base.notify(ev::OneWayEvent)
    state = @atomic ev.state
    while state !== OWE_NOTIFYING
        # Spin until we successfully update the state to OWE_NOTIFYING:
        state, ok = @atomicreplace(ev.state, state => OWE_NOTIFYING)
        if ok
            if state == OWE_WAITING
                # OWE_WAITING -> OWE_NOTIFYING transition means that the waiter task is
                # already waiting or about to call `wait`. The notifier task must wake up
                # the waiter task.
                schedule(ev.task)
            else
                @assert state == OWE_EMPTY
                # Since we are assuming that there is only one notifier task (for
                # simplicity), we know that the other possible case here is OWE_EMPTY.
                # We do not need to do anything because we know that the waiter task has
                # not called `wait(ev::OneWayEvent)` yet.
            end
            break
        end
    end
    return
end

function Base.wait(ev::OneWayEvent)
    ev.task = current_task()
    state, ok = @atomicreplace(ev.state, OWE_EMPTY => OWE_WAITING)
    if ok
        # OWE_EMPTY -> OWE_WAITING transition means that the notifier task is guaranteed to
        # invoke OWE_WAITING -> OWE_NOTIFYING transition.  The waiter task must call
        # `wait()` immediately.  In particular, it MUST NOT invoke any function that may
        # yield to the scheduler at this point in code.
        wait()
    else
        @assert state == OWE_NOTIFYING
        # Otherwise, the `state` must have already been moved to OWE_NOTIFYING by the
        # notifier task.
    end
    return
end

ev = OneWayEvent()
@sync begin
    @async begin
        wait(ev)
        println("done")
    end
    println("notifying...")
    notify(ev)
end

# output
notifying...
done
```


## [Low-level synchronization using schedule and wait](#low-level-schedule-wait)
`OneWayEvent` lets one task to `wait` for another task's `notify`. It is a limited communication interface since `wait` can only be used once from a single task (note the non-atomic assignment of `ev.task`)
In this example, `notify(ev::OneWayEvent)` is allowed to call `schedule(ev.task)` if and only if *it* modifies the state from `OWE_WAITING` to `OWE_NOTIFYING`. This lets us know that the task executing `wait(ev::OneWayEvent)` is now in the `ok` branch and that there cannot be other tasks that tries to `schedule(ev.task)` since their `@atomicreplace(ev.state, state => OWE_NOTIFYING)` will fail.
------------------------------------------------------------------------


# Multi-Threading · The Julia Language
Source: https://docs.julialang.org/en/v1/base/multi-threading/


# [Multi-Threading](#lib-multithreading)
```julia
Threads.@threads [schedule] for ... end
```
A macro to execute a `for` loop in parallel. The iteration space is distributed to coarse-grained tasks. This policy can be specified by the `schedule` argument. The execution of the loop waits for the evaluation of all iterations.
See also: [`@spawn`](#Base.Threads.@spawn) and `pmap` in [`Distributed`](../../stdlib/Distributed/#man-distributed).
**Extended help**
**Semantics**
Unless stronger guarantees are specified by the scheduling option, the loop executed by `@threads` macro have the following semantics.
The `@threads` macro executes the loop body in an unspecified order and potentially concurrently. It does not specify the exact assignments of the tasks and the worker threads. The assignments can be different for each execution. The loop body code (including any code transitively called from it) must not make any assumptions about the distribution of iterations to tasks or the worker thread in which they are executed. The loop body for each iteration must be able to make forward progress independent of other iterations and be free from data races. As such, invalid synchronizations across iterations may deadlock while unsynchronized memory accesses may result in undefined behavior.
For example, the above conditions imply that:
-   A lock taken in an iteration *must* be released within the same iteration.
-   Communicating between iterations using blocking primitives like `Channel`s is incorrect.


# [Multi-Threading](#lib-multithreading)
-   Write only to locations not shared across iterations (unless a lock or atomic operation is used).
-   Unless the `:static` schedule is used, the value of [`threadid()`](#Base.Threads.threadid) may change even within a single iteration. See [`Task Migration`](../../manual/multi-threading/#man-task-migration).
**Schedulers**
Without the scheduler argument, the exact scheduling is unspecified and varies across Julia releases. Currently, `:dynamic` is used when the scheduler is not specified.
The `schedule` argument is available as of Julia 1.5.
**`:dynamic` (default)**
`:dynamic` scheduler executes iterations dynamically to available worker threads. Current implementation assumes that the workload for each iteration is uniform. However, this assumption may be removed in the future.
This scheduling option is merely a hint to the underlying execution mechanism. However, a few properties can be expected. The number of `Task`s used by `:dynamic` scheduler is bounded by a small constant multiple of the number of available worker threads ([`Threads.threadpoolsize()`](#Base.Threads.threadpoolsize)). Each task processes contiguous regions of the iteration space. Thus, `@threads :dynamic for x in xs; f(x); end` is typically more efficient than `@sync for x in xs; @spawn f(x); end` if `length(xs)` is significantly larger than the number of the worker threads and the run-time of `f(x)` is relatively smaller than the cost of spawning and synchronizing a task (typically less than 10 microseconds).


# [Multi-Threading](#lib-multithreading)
The `:dynamic` option for the `schedule` argument is available and the default as of Julia 1.8.
**`:greedy`**
`:greedy` scheduler spawns up to [`Threads.threadpoolsize()`](#Base.Threads.threadpoolsize) tasks, each greedily working on the given iterated values as they are produced. As soon as one task finishes its work, it takes the next value from the iterator. Work done by any individual task is not necessarily on contiguous values from the iterator. The given iterator may produce values forever, only the iterator interface is required (no indexing).
This scheduling option is generally a good choice if the workload of individual iterations is not uniform/has a large spread.
The `:greedy` option for the `schedule` argument is available as of Julia 1.11.
**`:static`**
`:static` scheduler creates one task per thread and divides the iterations equally among them, assigning each task specifically to each thread. In particular, the value of [`threadid()`](#Base.Threads.threadid) is guaranteed to be constant within one iteration. Specifying `:static` is an error if used from inside another `@threads` loop or from a thread other than 1.
`:static` scheduling exists for supporting transition of code written before Julia 1.3. In newly written library functions, `:static` scheduling is discouraged because the functions using this option cannot be called from arbitrary worker threads.
**Examples**


# [Multi-Threading](#lib-multithreading)
To illustrate of the different scheduling strategies, consider the following function `busywait` containing a non-yielding timed loop that runs for a given number of seconds.
```julia-repl
julia> function busywait(seconds)
            tstart = time_ns()
            while (time_ns() - tstart) / 1e9 < seconds
            end
        end

julia> @time begin
            Threads.@spawn busywait(5)
            Threads.@threads :static for i in 1:Threads.threadpoolsize()
                busywait(1)
            end
        end
6.003001 seconds (16.33 k allocations: 899.255 KiB, 0.25% compilation time)

julia> @time begin
            Threads.@spawn busywait(5)
            Threads.@threads :dynamic for i in 1:Threads.threadpoolsize()
                busywait(1)
            end
        end
2.012056 seconds (16.05 k allocations: 883.919 KiB, 0.66% compilation time)
```
The `:dynamic` example takes 2 seconds since one of the non-occupied threads is able to run two of the 1-second iterations to complete the for loop.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L260-L380)
```julia
Threads.foreach(f, channel::Channel;
                schedule::Threads.AbstractSchedule=Threads.FairSchedule(),
                ntasks=Threads.threadpoolsize())
```
Similar to `foreach(f, channel)`, but iteration over `channel` and calls to `f` are split across `ntasks` tasks spawned by `Threads.@spawn`. This function will wait for all internally spawned tasks to complete before returning.


# [Multi-Threading](#lib-multithreading)
If `schedule isa FairSchedule`, `Threads.foreach` will attempt to spawn tasks in a manner that enables Julia's scheduler to more freely load-balance work items across threads. This approach generally has higher per-item overhead, but may perform better than `StaticSchedule` in concurrence with other multithreaded workloads.
If `schedule isa StaticSchedule`, `Threads.foreach` will spawn tasks in a manner that incurs lower per-item overhead than `FairSchedule`, but is less amenable to load-balancing. This approach thus may be more suitable for fine-grained, uniform workloads, but may perform worse than `FairSchedule` in concurrence with other multithreaded workloads.
**Examples**
```julia-repl
julia> n = 20

julia> c = Channel{Int}(ch -> foreach(i -> put!(ch, i), 1:n), 1)

julia> d = Channel{Int}(n) do ch
           f = i -> put!(ch, i^2)
           Threads.foreach(f, c)
       end

julia> collect(d)
collect(d) = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400]
```
This function requires Julia 1.6 or later.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threads_overloads.jl#L3-L40)
```julia
Threads.@spawn [:default|:interactive] expr
```


# [Multi-Threading](#lib-multithreading)
Create a [`Task`](../parallel/#Core.Task) and [`schedule`](../parallel/#Base.schedule) it to run on any available thread in the specified threadpool (`:default` if unspecified). The task is allocated to a thread once one becomes available. To wait for the task to finish, call [`wait`](../parallel/#Base.wait) on the result of this macro, or call [`fetch`](../parallel/#Base.fetch-Tuple%7BTask%7D) to wait and then obtain its return value.
Values can be interpolated into `@spawn` via `$`, which copies the value directly into the constructed underlying closure. This allows you to insert the *value* of a variable, isolating the asynchronous code from changes to the variable's value in the current task.
The thread that the task runs on may change if the task yields, therefore `threadid()` should not be treated as constant for a task. See [`Task Migration`](../../manual/multi-threading/#man-task-migration), and the broader [multi-threading](../../manual/multi-threading/#man-multithreading) manual for further important caveats. See also the chapter on [threadpools](../../manual/multi-threading/#man-threadpools).
This macro is available as of Julia 1.3.
Interpolating values via `$` is available as of Julia 1.4.
A threadpool may be specified as of Julia 1.9.
**Examples**
```julia-repl
julia> t() = println("Hello from ", Threads.threadid());

julia> tasks = fetch.([Threads.@spawn t() for i in 1:4]);
Hello from 1
Hello from 1
Hello from 3
Hello from 4
```


# [Multi-Threading](#lib-multithreading)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L419-L458)
```julia
Threads.threadid() -> Int
```
Get the ID number of the current thread of execution. The master thread has ID `1`.
**Examples**
```julia-repl
julia> Threads.threadid()
1

julia> Threads.@threads for i in 1:4
          println(Threads.threadid())
       end
4
2
5
4
```
The thread that a task runs on may change if the task yields, which is known as [`Task Migration`](../../manual/multi-threading/#man-task-migration). For this reason in most cases it is not safe to use `threadid()` to index into, say, a vector of buffer or stateful objects.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L6-L30)
```julia
Threads.maxthreadid() -> Int
```
Get a lower bound on the number of threads (across all thread pools) available to the Julia process, with atomic-acquire semantics. The result will always be greater than or equal to [`threadid()`](#Base.Threads.threadid) as well as `threadid(task)` for any task you were able to observe before calling `maxthreadid`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L34-L41)
```julia
Threads.nthreads(:default | :interactive) -> Int
```


# [Multi-Threading](#lib-multithreading)
Get the current number of threads within the specified thread pool. The threads in `:interactive` have id numbers `1:nthreads(:interactive)`, and the threads in `:default` have id numbers in `nthreads(:interactive) .+ (1:nthreads(:default))`.
See also `BLAS.get_num_threads` and `BLAS.set_num_threads` in the [`LinearAlgebra`](../../stdlib/LinearAlgebra/#man-linalg) standard library, and `nprocs()` in the [`Distributed`](../../stdlib/Distributed/#man-distributed) standard library and [`Threads.maxthreadid()`](#Base.Threads.maxthreadid).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L44-L54)
```julia
Threads.threadpool(tid = threadid()) -> Symbol
```
Returns the specified thread's threadpool; either `:default`, `:interactive`, or `:foreign`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L86-L90)
```julia
Threads.nthreadpools() -> Int
```
Returns the number of threadpools currently configured.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L96-L100)
```julia
Threads.threadpoolsize(pool::Symbol = :default) -> Int
```
Get the number of threads available to the default thread pool (or to the specified thread pool).


# [Multi-Threading](#lib-multithreading)
See also: `BLAS.get_num_threads` and `BLAS.set_num_threads` in the [`LinearAlgebra`](../../stdlib/LinearAlgebra/#man-linalg) standard library, and `nprocs()` in the [`Distributed`](../../stdlib/Distributed/#man-distributed) standard library.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L103-L112)
```julia
Threads.ngcthreads() -> Int
```
Returns the number of GC threads currently configured. This includes both mark threads and concurrent sweep threads.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadingconstructs.jl#L140-L145)
See also [Multi-Threading](../../manual/multi-threading/#man-multithreading).


## [Atomic operations](#Atomic-operations)
Unsafe pointer operations are compatible with loading and storing pointers declared with `_Atomic` and `std::atomic` type in C11 and C++23 respectively. An error may be thrown if there is not support for atomically loading the Julia type `T`.
See also: [`unsafe_load`](../c/#Base.unsafe_load), [`unsafe_modify!`](../c/#Base.unsafe_modify!), [`unsafe_replace!`](../c/#Base.unsafe_replace!), [`unsafe_store!`](../c/#Base.unsafe_store!), [`unsafe_swap!`](../c/#Base.unsafe_swap!)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/docs/basedocs.jl#L3617-L3623)
```julia
@atomic var
@atomic order ex
```
Mark `var` or `ex` as being performed atomically, if `ex` is a supported expression. If no `order` is specified it defaults to :sequentially_consistent.
```julia
@atomic a.b.x = new
@atomic a.b.x += addend
@atomic :release a.b.x = new
@atomic :acquire_release a.b.x += addend
```
Perform the store operation expressed on the right atomically and return the new value.
With `=`, this operation translates to a `setproperty!(a.b, :x, new)` call. With any operator also, this operation translates to a `modifyproperty!(a.b, :x, +, addend)[2]` call.
```julia
@atomic a.b.x max arg2
@atomic a.b.x + arg2
@atomic max(a.b.x, arg2)
@atomic :acquire_release max(a.b.x, arg2)
@atomic :acquire_release a.b.x + arg2
@atomic :acquire_release a.b.x max arg2
```
Perform the binary operation expressed on the right atomically. Store the result into the field in the first argument and return the values `(old, new)`.


## [Atomic operations](#Atomic-operations)
This operation translates to a `modifyproperty!(a.b, :x, func, arg2)` call.
See [Per-field atomics](../../manual/multi-threading/#man-atomics) section in the manual for more details.
**Examples**
```julia-repl
julia> mutable struct Atomic{T}; @atomic x::T; end

julia> a = Atomic(1)
Atomic{Int64}(1)

julia> @atomic a.x # fetch field x of a, with sequential consistency
1

julia> @atomic :sequentially_consistent a.x = 2 # set field x of a, with sequential consistency
2

julia> @atomic a.x += 1 # increment field x of a, with sequential consistency
3

julia> @atomic a.x + 1 # increment field x of a, with sequential consistency
3 => 4

julia> @atomic a.x # fetch field x of a, with sequential consistency
4

julia> @atomic max(a.x, 10) # change field x of a to the max value, with sequential consistency
4 => 10

julia> @atomic a.x max 5 # again change field x of a to the max value, with sequential consistency
10 => 10
```
This functionality requires at least Julia 1.7.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/expr.jl#L1123-L1188)
```julia
@atomicswap a.b.x = new
@atomicswap :sequentially_consistent a.b.x = new
```
Stores `new` into `a.b.x` and returns the old value of `a.b.x`.
This operation translates to a `swapproperty!(a.b, :x, new)` call.
See [Per-field atomics](../../manual/multi-threading/#man-atomics) section in the manual for more details.
**Examples**


## [Atomic operations](#Atomic-operations)
```julia-repl
julia> mutable struct Atomic{T}; @atomic x::T; end

julia> a = Atomic(1)
Atomic{Int64}(1)

julia> @atomicswap a.x = 2+2 # replace field x of a with 4, with sequential consistency
1

julia> @atomic a.x # fetch field x of a, with sequential consistency
4
```
This functionality requires at least Julia 1.7.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/expr.jl#L1247-L1273)
```julia
@atomicreplace a.b.x expected => desired
@atomicreplace :sequentially_consistent a.b.x expected => desired
@atomicreplace :sequentially_consistent :monotonic a.b.x expected => desired
```
Perform the conditional replacement expressed by the pair atomically, returning the values `(old, success::Bool)`. Where `success` indicates whether the replacement was completed.
This operation translates to a `replaceproperty!(a.b, :x, expected, desired)` call.
See [Per-field atomics](../../manual/multi-threading/#man-atomics) section in the manual for more details.
**Examples**


## [Atomic operations](#Atomic-operations)
```julia-repl
julia> mutable struct Atomic{T}; @atomic x::T; end

julia> a = Atomic(1)
Atomic{Int64}(1)

julia> @atomicreplace a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency
(old = 1, success = true)

julia> @atomic a.x # fetch field x of a, with sequential consistency
2

julia> @atomicreplace a.x 1 => 2 # replace field x of a with 2 if it was 1, with sequential consistency
(old = 2, success = false)

julia> xchg = 2 => 0; # replace field x of a with 0 if it was 2, with sequential consistency

julia> @atomicreplace a.x xchg
(old = 2, success = true)

julia> @atomic a.x # fetch field x of a, with sequential consistency
0
```
This functionality requires at least Julia 1.7.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/expr.jl#L1291-L1331)
```julia
@atomiconce a.b.x = value
@atomiconce :sequentially_consistent a.b.x = value
@atomiconce :sequentially_consistent :monotonic a.b.x = value
```
Perform the conditional assignment of value atomically if it was previously unset, returning the value `success::Bool`. Where `success` indicates whether the assignment was completed.
This operation translates to a `setpropertyonce!(a.b, :x, value)` call.
See [Per-field atomics](../../manual/multi-threading/#man-atomics) section in the manual for more details.
**Examples**


## [Atomic operations](#Atomic-operations)
```julia-repl
julia> mutable struct AtomicOnce
           @atomic x
           AtomicOnce() = new()
       end

julia> a = AtomicOnce()
AtomicOnce(#undef)

julia> @atomiconce a.x = 1 # set field x of a to 1, if unset, with sequential consistency
true

julia> @atomic a.x # fetch field x of a, with sequential consistency
1

julia> @atomiconce a.x = 1 # set field x of a to 1, if unset, with sequential consistency
false
```
This functionality requires at least Julia 1.11.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/expr.jl#L1357-L1392)
```julia
AtomicMemory{T} == GenericMemory{:atomic, T, Core.CPU}
```
Fixed-size [`DenseVector{T}`](../arrays/#Base.DenseVector). Access to its any of its elements is performed atomically (with `:monotonic` ordering). Setting any of the elements must be accomplished using the `@atomic` macro and explicitly specifying ordering.
Each element is independently atomic when accessed, and cannot be set non-atomically. Currently the `@atomic` macro and higher level interface have not been completed, but the building blocks for a future implementation are the internal intrinsics `Core.memoryrefget`, `Core.memoryrefset!`, `Core.memoryref_isassigned`, `Core.memoryrefswap!`, `Core.memoryrefmodify!`, and `Core.memoryrefreplace!`.
For details, see [Atomic Operations](../../manual/multi-threading/#man-atomic-operations)
This type requires Julia 1.11 or later.


## [Atomic operations](#Atomic-operations)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/genericmemory.jl#L37-L55)
There are also optional memory ordering parameters for the `unsafe` set of functions, that select the C/C++-compatible versions of these atomic operations, if that parameter is specified to [`unsafe_load`](../c/#Base.unsafe_load), [`unsafe_store!`](../c/#Base.unsafe_store!), [`unsafe_swap!`](../c/#Base.unsafe_swap!), [`unsafe_replace!`](../c/#Base.unsafe_replace!), and [`unsafe_modify!`](../c/#Base.unsafe_modify!).
The following APIs are deprecated, though support for them is likely to remain for several releases.
```julia
Threads.Atomic{T}
```
Holds a reference to an object of type `T`, ensuring that it is only accessed atomically, i.e. in a thread-safe manner.
Only certain "simple" types can be used atomically, namely the primitive boolean, integer, and float-point types. These are `Bool`, `Int8`...`Int128`, `UInt8`...`UInt128`, and `Float16`...`Float64`.
New atomic objects can be created from a non-atomic values; if none is specified, the atomic object is initialized with zero.
Atomic objects can be accessed using the `[]` notation:
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)

julia> x[] = 1
1

julia> x[]
1
```
Atomic operations use an `atomic_` prefix, such as [`atomic_add!`](#Base.Threads.atomic_add!), [`atomic_xchg!`](#Base.Threads.atomic_xchg!), etc.


## [Atomic operations](#Atomic-operations)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L45-L74)
```julia
Threads.atomic_cas!(x::Atomic{T}, cmp::T, newval::T) where T
```
Atomically compare-and-set `x`
Atomically compares the value in `x` with `cmp`. If equal, write `newval` to `x`. Otherwise, leaves `x` unmodified. Returns the old value in `x`. By comparing the returned value to `cmp` (via `===`) one knows whether `x` was modified and now holds the new value `newval`.
For further details, see LLVM's `cmpxchg` instruction.
This function can be used to implement transactional semantics. Before the transaction, one records the value in `x`. After the transaction, the new value is stored only if `x` has not been modified in the mean time.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)

julia> Threads.atomic_cas!(x, 4, 2);

julia> x
Base.Threads.Atomic{Int64}(3)

julia> Threads.atomic_cas!(x, 3, 2);

julia> x
Base.Threads.Atomic{Int64}(2)
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L90-L122)
```julia
Threads.atomic_xchg!(x::Atomic{T}, newval::T) where T
```
Atomically exchange the value in `x`
Atomically exchanges the value in `x` with `newval`. Returns the **old** value.
For further details, see LLVM's `atomicrmw xchg` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)

julia> Threads.atomic_xchg!(x, 2)
3

julia> x[]
2
```


## [Atomic operations](#Atomic-operations)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L125-L146)
```julia
Threads.atomic_add!(x::Atomic{T}, val::T) where T <: ArithmeticTypes
```
Atomically add `val` to `x`
Performs `x[] += val` atomically. Returns the **old** value. Not defined for `Atomic{Bool}`.
For further details, see LLVM's `atomicrmw add` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)

julia> Threads.atomic_add!(x, 2)
3

julia> x[]
5
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L149-L170)
```julia
Threads.atomic_sub!(x::Atomic{T}, val::T) where T <: ArithmeticTypes
```
Atomically subtract `val` from `x`
Performs `x[] -= val` atomically. Returns the **old** value. Not defined for `Atomic{Bool}`.
For further details, see LLVM's `atomicrmw sub` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)

julia> Threads.atomic_sub!(x, 2)
3

julia> x[]
1
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L173-L194)
```julia
Threads.atomic_and!(x::Atomic{T}, val::T) where T
```
Atomically bitwise-and `x` with `val`
Performs `x[] &= val` atomically. Returns the **old** value.
For further details, see LLVM's `atomicrmw and` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)

julia> Threads.atomic_and!(x, 2)
3

julia> x[]
2
```


## [Atomic operations](#Atomic-operations)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L197-L217)
```julia
Threads.atomic_nand!(x::Atomic{T}, val::T) where T
```
Atomically bitwise-nand (not-and) `x` with `val`
Performs `x[] = ~(x[] & val)` atomically. Returns the **old** value.
For further details, see LLVM's `atomicrmw nand` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)

julia> Threads.atomic_nand!(x, 2)
3

julia> x[]
-3
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L220-L240)
```julia
Threads.atomic_or!(x::Atomic{T}, val::T) where T
```
Atomically bitwise-or `x` with `val`
Performs `x[] |= val` atomically. Returns the **old** value.
For further details, see LLVM's `atomicrmw or` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(5)
Base.Threads.Atomic{Int64}(5)

julia> Threads.atomic_or!(x, 7)
5

julia> x[]
7
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L243-L263)
```julia
Threads.atomic_xor!(x::Atomic{T}, val::T) where T
```
Atomically bitwise-xor (exclusive-or) `x` with `val`
Performs `x[] $= val` atomically. Returns the **old** value.
For further details, see LLVM's `atomicrmw xor` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(5)
Base.Threads.Atomic{Int64}(5)

julia> Threads.atomic_xor!(x, 7)
5

julia> x[]
2
```


## [Atomic operations](#Atomic-operations)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L266-L286)
```julia
Threads.atomic_max!(x::Atomic{T}, val::T) where T
```
Atomically store the maximum of `x` and `val` in `x`
Performs `x[] = max(x[], val)` atomically. Returns the **old** value.
For further details, see LLVM's `atomicrmw max` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(5)
Base.Threads.Atomic{Int64}(5)

julia> Threads.atomic_max!(x, 7)
5

julia> x[]
7
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L289-L309)
```julia
Threads.atomic_min!(x::Atomic{T}, val::T) where T
```
Atomically store the minimum of `x` and `val` in `x`
Performs `x[] = min(x[], val)` atomically. Returns the **old** value.
For further details, see LLVM's `atomicrmw min` instruction.
**Examples**
```julia-repl
julia> x = Threads.Atomic{Int}(7)
Base.Threads.Atomic{Int64}(7)

julia> Threads.atomic_min!(x, 5)
7

julia> x[]
5
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L312-L332)
```julia
Threads.atomic_fence()
```
Insert a sequential-consistency memory fence
Inserts a memory fence with sequentially-consistent ordering semantics. There are algorithms where this is needed, i.e. where an acquire/release ordering is insufficient.


## [Atomic operations](#Atomic-operations)
This is likely a very expensive operation. Given that all other atomic operations in Julia already have acquire/release semantics, explicit fences should not be necessary in most cases.
For further details, see LLVM's `fence` instruction.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/atomics.jl#L450-L464)


## [ccall using a libuv threadpool (Experimental)](#ccall-using-a-libuv-threadpool-(Experimental))
```julia
@threadcall((cfunc, clib), rettype, (argtypes...), argvals...)
```
The `@threadcall` macro is called in the same way as [`ccall`](../c/#ccall) but does the work in a different thread. This is useful when you want to call a blocking C function without causing the current `julia` thread to become blocked. Concurrency is limited by size of the libuv thread pool, which defaults to 4 threads but can be increased by setting the `UV_THREADPOOL_SIZE` environment variable and restarting the `julia` process.
Note that the called function should never call back into Julia.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/threadcall.jl#L8-L19)


## [Low-level synchronization primitives](#Low-level-synchronization-primitives)
These building blocks are used to create the regular synchronization objects.
```julia
SpinLock()
```
Create a non-reentrant, test-and-test-and-set spin lock. Recursive use will result in a deadlock. This kind of lock should only be used around code that takes little time to execute and does not block (e.g. perform I/O). In general, [`ReentrantLock`](../parallel/#Base.ReentrantLock) should be used instead.
Each [`lock`](../parallel/#Base.lock) must be matched with an [`unlock`](../parallel/#Base.unlock). If [`!islocked(lck::SpinLock)`](../parallel/#Base.islocked) holds, [`trylock(lck)`](../parallel/#Base.trylock) succeeds unless there are other tasks attempting to hold the lock "at the same time."
Test-and-test-and-set spin locks are quickest up to about 30ish contending threads. If you have more contention than that, different synchronization approaches should be considered.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/locks-mt.jl#L14-L30)
------------------------------------------------------------------------


# Scoped Values · The Julia Language
Source: https://docs.julialang.org/en/v1/base/scopedvalues/


# [Scoped Values](#scoped-values)
Scoped values provide an implementation of dynamic scoping in Julia.
[Lexical scoping](../../manual/variables-and-scoping/#scope-of-variables) is the default behavior in Julia. Under lexical scoping the scope of a variable is determined by the lexical (textual) structure of a program. Under dynamic scoping a variable is bound to the most recent assigned value during the program's execution.
The state of a scoped value is dependent on the execution path of the program. This means that for a scoped value you may observe multiple different values concurrently.
Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible implementation is available from the package ScopedValues.jl.
In its simplest form you can create a [`ScopedValue`](#Base.ScopedValues.ScopedValue) with a default value and then use [`with`](#Base.ScopedValues.with) or [`@with`](#Base.ScopedValues.@with) to enter a new dynamic scope. The new scope will inherit all values from the parent scope (and recursively from all outer scopes) with the provided scoped value taking priority over previous definitions.
Let's first look at an example of **lexical** scope. A `let` statement begins a new lexical scope within which the outer definition of `x` is shadowed by it's inner definition.
```julia
x = 1
let x = 5
    @show x # 5
end
@show x # 1
```
In the following example, since Julia uses lexical scope, the variable `x` in the body of `f` refers to the `x` defined in the global scope, and entering a `let` scope does not change the value `f` observes.


# [Scoped Values](#scoped-values)
```julia
x = 1
f() = @show x
let x = 5
    f() # 1
end
f() # 1
```
Now using a `ScopedValue` we can use **dynamic** scoping.
```julia
using Base.ScopedValues

x = ScopedValue(1)
f() = @show x[]
with(x=>5) do
    f() # 5
end
f() # 1
```
Note that the observed value of the `ScopedValue` is dependent on the execution path of the program.
It often makes sense to use a `const` variable to point to a scoped value, and you can set the value of multiple `ScopedValue`s with one call to `with`.
```julia
using Base.ScopedValues

f() = @show a[]
g() = @show b[]

const a = ScopedValue(1)
const b = ScopedValue(2)

f() # a[] = 1
g() # b[] = 2

# Enter a new dynamic scope and set value.
with(a => 3) do
    f() # a[] = 3
    g() # b[] = 2
    with(a => 4, b => 5) do
        f() # a[] = 4
        g() # b[] = 5
    end
    f() # a[] = 3
    g() # b[] = 2
end

f() # a[] = 1
g() # b[] = 2
```
`ScopedValues` provides a macro version of `with`. The expression `@with var=>val expr` evaluates `expr` in a new dynamic scope with `var` set to `val`. `@with var=>val expr` is equivalent to `with(var=>val) do expr end`. However, `with` requires a zero-argument closure or function, which results in an extra call-frame. As an example, consider the following function `f`:
```julia
using Base.ScopedValues
const a = ScopedValue(1)
f(x) = a[] + x
```
If you wish to run `f` in a dynamic scope with `a` set to `2`, then you can use `with`:
```julia
with(() -> f(10), a=>2)
```


# [Scoped Values](#scoped-values)
However, this requires wrapping `f` in a zero-argument function. If you wish to avoid the extra call-frame, then you can use the `@with` macro:
```julia
@with a=>2 f(10)
```
Dynamic scopes are inherited by [`Task`](../parallel/#Core.Task)s, at the moment of task creation. Dynamic scopes are **not** propagated through `Distributed.jl` operations.
In the example below we open a new dynamic scope before launching a task. The parent task and the two child tasks observe independent values of the same scoped value at the same time.
```julia
using Base.ScopedValues
import Base.Threads: @spawn

const scoped_val = ScopedValue(1)
@sync begin
    with(scoped_val => 2)
        @spawn @show scoped_val[] # 2
    end
    with(scoped_val => 3)
        @spawn @show scoped_val[] # 3
    end
    @show scoped_val[] # 1
end
```
Scoped values are constant throughout a scope, but you can store mutable state in a scoped value. Just keep in mind that the usual caveats for global variables apply in the context of concurrent programming.
Care is also required when storing references to mutable state in scoped values. You might want to explicitly [unshare mutable state](#unshare_mutable_state) when entering a new dynamic scope.


# [Scoped Values](#scoped-values)
```julia
using Base.ScopedValues
import Base.Threads: @spawn

const sval_dict = ScopedValue(Dict())

# Example of using a mutable value wrongly
@sync begin
    # `Dict` is not thread-safe the usage below is invalid
    @spawn (sval_dict[][:a] = 3)
    @spawn (sval_dict[][:b] = 3)
end

@sync begin
    # If we instead pass a unique dictionary to each
    # task we can access the dictionaries race free.
    with(sval_dict => Dict()) do
        @spawn (sval_dict[][:a] = 3)
    end
    with(sval_dict => Dict()) do
        @spawn (sval_dict[][:b] = 3)
    end
end
```


## [Example](#Example)
In the example below we use a scoped value to implement a permission check in a web-application. After determining the permissions of the request, a new dynamic scope is entered and the scoped value `LEVEL` is set. Other parts of the application can query the scoped value and will receive the appropriate value. Other alternatives like task-local storage and global variables are not well suited for this kind of propagation; our only alternative would have been to thread a value through the entire call-chain.
```julia
using Base.ScopedValues

const LEVEL = ScopedValue(:GUEST)

function serve(request, response)
    level = isAdmin(request) ? :ADMIN : :GUEST
    with(LEVEL => level) do
        Threads.@spawn handle(request, response)
    end
end

function open(connection::Database)
    level = LEVEL[]
    if level !== :ADMIN
        error("Access disallowed")
    end
    # ... open connection
end

function handle(request, response)
    # ...
    open(Database(#=...=#))
    # ...
end
```


## [Idioms](#Idioms)


### [Unshare mutable state](#unshare_mutable_state)
```julia
using Base.ScopedValues
import Base.Threads: @spawn

const sval_dict = ScopedValue(Dict())

# If you want to add new values to the dict, instead of replacing
# it, unshare the values explicitly. In this example we use `merge`
# to unshare the state of the dictionary in parent scope.
@sync begin
    with(sval_dict => merge(sval_dict[], Dict(:a => 10))) do
        @spawn @show sval_dict[][:a]
    end
    @spawn sval_dict[][:a] = 3 # Not a race since they are unshared.
end
```


### [Scoped values as globals](#Scoped-values-as-globals)
In order to access the value of a scoped value, the scoped value itself has to be in (lexical) scope. This means most often you likely want to use scoped values as constant globals.
```julia
using Base.ScopedValues
const sval = ScopedValue(1)
```
Indeed one can think of scoped values as hidden function arguments.
This does not preclude their use as non-globals.
```julia
using Base.ScopedValues
import Base.Threads: @spawn

function main()
    role = ScopedValue(:client)

    function launch()
        #...
        role[]
    end

    @with role => :server @spawn launch()
    launch()
end
```
But it might have been simpler to just directly pass the function argument in these cases.


### [Very many ScopedValues](#Very-many-ScopedValues)
If you find yourself creating many `ScopedValue`'s for one given module, it may be better to use a dedicated struct to hold them.
```julia
using Base.ScopedValues

Base.@kwdef struct Configuration
    color::Bool = false
    verbose::Bool = false
end

const CONFIG = ScopedValue(Configuration(color=true))

@with CONFIG => Configuration(color=CONFIG[].color, verbose=true) begin
    @show CONFIG[].color # true
    @show CONFIG[].verbose # true
end
```


## [API docs](#API-docs)
```julia
ScopedValue(x)
```
Create a container that propagates values across dynamic scopes. Use [`with`](#Base.ScopedValues.with) to create and enter a new dynamic scope.
Values can only be set when entering a new dynamic scope, and the value referred to will be constant during the execution of a dynamic scope.
Dynamic scopes are propagated across tasks.
**Examples**
```julia-repl
julia> using Base.ScopedValues;

julia> const sval = ScopedValue(1);

julia> sval[]
1

julia> with(sval => 2) do
           sval[]
       end
2

julia> sval[]
1
```
Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible implementation is available from the package ScopedValues.jl.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/scopedvalues.jl#L8-L42)
```julia
with(f, (var::ScopedValue{T} => val)...)
```
Execute `f` in a new dynamic scope with `var` set to `val`. `val` will be converted to type `T`.
See also: [`ScopedValues.@with`](#Base.ScopedValues.@with), [`ScopedValues.ScopedValue`](#Base.ScopedValues.ScopedValue), [`ScopedValues.get`](#Base.ScopedValues.get).
**Examples**
```julia-repl
julia> using Base.ScopedValues

julia> a = ScopedValue(1);

julia> f(x) = a[] + x;

julia> f(10)
11

julia> with(a=>2) do
           f(10)
       end
12

julia> f(10)
11

julia> b = ScopedValue(2);

julia> g(x) = a[] + b[] + x;

julia> with(a=>10, b=>20) do
           g(30)
       end
60

julia> with(() -> a[] * b[], a=>3, b=>4)
12
```


## [API docs](#API-docs)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/scopedvalues.jl#L228-L267)
```julia
@with (var::ScopedValue{T} => val)... expr
```
Macro version of `with`. The expression `@with var=>val expr` evaluates `expr` in a new dynamic scope with `var` set to `val`. `val` will be converted to type `T`. `@with var=>val expr` is equivalent to `with(var=>val) do expr end`, but `@with` avoids creating a closure.
See also: [`ScopedValues.with`](#Base.ScopedValues.with), [`ScopedValues.ScopedValue`](#Base.ScopedValues.ScopedValue), [`ScopedValues.get`](#Base.ScopedValues.get).
**Examples**
```julia-repl
julia> using Base.ScopedValues

julia> const a = ScopedValue(1);

julia> f(x) = a[] + x;

julia> @with a=>2 f(10)
12

julia> @with a=>3 begin
           x = 100
           f(x)
       end
103
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/scopedvalues.jl#L186-L213)
```julia
isassigned(val::ScopedValue)
```
Test whether a `ScopedValue` has an assigned value.
See also: [`ScopedValues.with`](#Base.ScopedValues.with), [`ScopedValues.@with`](#Base.ScopedValues.@with), [`ScopedValues.get`](#Base.ScopedValues.get).
**Examples**
```julia-repl
julia> using Base.ScopedValues

julia> a = ScopedValue(1); b = ScopedValue{Int}();

julia> isassigned(a)
true

julia> isassigned(b)
false
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/scopedvalues.jl#L55-L74)
```julia
get(val::ScopedValue{T})::Union{Nothing, Some{T}}
```


## [API docs](#API-docs)
If the scoped value isn't set and doesn't have a default value, return `nothing`. Otherwise returns `Some{T}` with the current value.
See also: [`ScopedValues.with`](#Base.ScopedValues.with), [`ScopedValues.@with`](#Base.ScopedValues.@with), [`ScopedValues.ScopedValue`](#Base.ScopedValues.ScopedValue).
**Examples**
```julia-repl
julia> using Base.ScopedValues

julia> a = ScopedValue(42); b = ScopedValue{Int}();

julia> ScopedValues.get(a)
Some(42)

julia> isnothing(ScopedValues.get(b))
true
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/scopedvalues.jl#L129-L150)


## [Implementation notes and performance](#Implementation-notes-and-performance)
`Scope`s use a persistent dictionary. Lookup and insertion is `O(log(32, n))`, upon dynamic scope entry a small amount of data is copied and the unchanged data is shared among other scopes.
The `Scope` object itself is not user-facing and may be changed in a future version of Julia.


## [Design inspiration](#Design-inspiration)
This design was heavily inspired by [JEPS-429](https://openjdk.org/jeps/429), which in turn was inspired by dynamically scoped free variables in many Lisp dialects. In particular Interlisp-D and its deep binding strategy.
A prior design discussed was context variables ala [PEPS-567](https://peps.python.org/pep-0567/) and implemented in Julia as [ContextVariablesX.jl](https://github.com/tkf/ContextVariablesX.jl).
------------------------------------------------------------------------


# Constants · The Julia Language
Source: https://docs.julialang.org/en/v1/base/constants/


# [Constants](#lib-constants)
```julia
nothing
```
The singleton instance of type [`Nothing`](../base/#Core.Nothing), used by convention when there is no value to return (as in a C `void` function) or when a variable or field holds no value.
See also: [`isnothing`](../base/#Base.isnothing), [`something`](../base/#Base.something), [`missing`](../../manual/missing/#missing).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/docs/basedocs.jl#L1542-L1549)
```julia
PROGRAM_FILE
```
A string containing the script name passed to Julia from the command line. Note that the script name remains unchanged from within included files. Alternatively see [`@__FILE__`](../base/#Base.@__FILE__).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/initdefs.jl#L5-L11)
```julia
ARGS
```
An array of the command line arguments passed to Julia, as strings.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/initdefs.jl#L14-L18)
```julia
C_NULL
```
The C null pointer constant, sometimes used when calling external code.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/pointer.jl#L13-L17)
```julia
VERSION
```
A [`VersionNumber`](../base/#Base.VersionNumber) object describing which version of Julia is in use. See also [Version Number Literals](../../manual/strings/#man-version-number-literals).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/version.jl#L243-L248)


# [Constants](#lib-constants)
```julia
DEPOT_PATH
```
A stack of "depot" locations where the package manager, as well as Julia's code loading mechanisms, look for package registries, installed packages, named environments, repo clones, cached compiled package images, and configuration files. By default it includes:
1.  `~/.julia` where `~` is the user home as appropriate on the system;
2.  an architecture-specific shared system directory, e.g. `/usr/local/share/julia`;
3.  an architecture-independent shared system directory, e.g. `/usr/share/julia`.
So `DEPOT_PATH` might be:
```julia
[joinpath(homedir(), ".julia"), "/usr/local/share/julia", "/usr/share/julia"]
```
The first entry is the "user depot" and should be writable by and owned by the current user. The user depot is where: registries are cloned, new package versions are installed, named environments are created and updated, package repos are cloned, newly compiled package image files are saved, log files are written, development packages are checked out by default, and global configuration data is saved. Later entries in the depot path are treated as read-only and are appropriate for registries, packages, etc. installed and managed by system administrators.
`DEPOT_PATH` is populated based on the [`JULIA_DEPOT_PATH`](../../manual/environment-variables/#JULIA_DEPOT_PATH) environment variable if set.
**DEPOT_PATH contents**
Each entry in `DEPOT_PATH` is a path to a directory which contains subdirectories used by Julia for various purposes. Here is an overview of some of the subdirectories that may exist in a depot:


# [Constants](#lib-constants)
-   `artifacts`: Contains content that packages use for which Pkg manages the installation of.
-   `clones`: Contains full clones of package repos. Maintained by `Pkg.jl` and used as a cache.
-   `config`: Contains julia-level configuration such as a `startup.jl`
-   `compiled`: Contains precompiled `*.ji` files for packages. Maintained by Julia.
-   `dev`: Default directory for `Pkg.develop`. Maintained by `Pkg.jl` and the user.
-   `environments`: Default package environments. For instance the global environment for a specific julia version. Maintained by `Pkg.jl`.
-   `logs`: Contains logs of `Pkg` and `REPL` operations. Maintained by `Pkg.jl` and `Julia`.
-   `packages`: Contains packages, some of which were explicitly installed and some which are implicit dependencies. Maintained by `Pkg.jl`.
-   `registries`: Contains package registries. By default only `General`. Maintained by `Pkg.jl`.
-   `scratchspaces`: Contains content that a package itself installs via the [`Scratch.jl`](https://github.com/JuliaPackaging/Scratch.jl) package. `Pkg.gc()` will delete content that is known to be unused.
Packages that want to store content should use the `scratchspaces` subdirectory via [`Scratch.jl`](https://github.com/JuliaPackaging/Scratch.jl) instead of creating new subdirectories in the depot root.
See also [`JULIA_DEPOT_PATH`](../../manual/environment-variables/#JULIA_DEPOT_PATH), and [Code Loading](../../manual/code-loading/#code-loading).


# [Constants](#lib-constants)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/initdefs.jl#L44-L94)
```julia
LOAD_PATH
```
An array of paths for `using` and `import` statements to consider as project environments or package directories when loading code. It is populated based on the [`JULIA_LOAD_PATH`](../../manual/environment-variables/#JULIA_LOAD_PATH) environment variable if set; otherwise it defaults to `["@", "@v#.#", "@stdlib"]`. Entries starting with `@` have special meanings:
-   `@` refers to the "current active environment", the initial value of which is initially determined by the [`JULIA_PROJECT`](../../manual/environment-variables/#JULIA_PROJECT) environment variable or the `--project` command-line option.
-   `@stdlib` expands to the absolute path of the current Julia installation's standard library directory.
-   `@name` refers to a named environment, which are stored in depots (see [`JULIA_DEPOT_PATH`](../../manual/environment-variables/#JULIA_DEPOT_PATH)) under the `environments` subdirectory. The user's named environments are stored in `~/.julia/environments` so `@name` would refer to the environment in `~/.julia/environments/name` if it exists and contains a `Project.toml` file. If `name` contains `#` characters, then they are replaced with the major, minor and patch components of the Julia version number. For example, if you are running Julia 1.2 then `@v#.#` expands to `@v1.2` and will look for an environment by that name, typically at `~/.julia/environments/v1.2`.


# [Constants](#lib-constants)
The fully expanded value of `LOAD_PATH` that is searched for projects and packages can be seen by calling the `Base.load_path()` function.
See also [`JULIA_LOAD_PATH`](../../manual/environment-variables/#JULIA_LOAD_PATH), [`JULIA_PROJECT`](../../manual/environment-variables/#JULIA_PROJECT), [`JULIA_DEPOT_PATH`](../../manual/environment-variables/#JULIA_DEPOT_PATH), and [Code Loading](../../manual/code-loading/#code-loading).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/initdefs.jl#L159-L193)
```julia
Sys.BINDIR::String
```
A string containing the full path to the directory containing the `julia` executable.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/sysinfo.jl#L43-L47)
```julia
Sys.CPU_THREADS::Int
```
The number of logical CPU cores available in the system, i.e. the number of threads that the CPU can run concurrently. Note that this is not necessarily the number of CPU cores, for example, in the presence of [hyper-threading](https://en.wikipedia.org/wiki/Hyper-threading).
See Hwloc.jl or CpuId.jl for extended information, including number of physical cores.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/sysinfo.jl#L62-L71)
```julia
Sys.WORD_SIZE::Int
```
Standard word size on the current machine, in bits.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/sysinfo.jl#L96-L100)
```julia
Sys.KERNEL::Symbol
```


# [Constants](#lib-constants)
A symbol representing the name of the operating system, as returned by `uname` of the build configuration.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/sysinfo.jl#L82-L86)
```julia
Sys.ARCH::Symbol
```
A symbol representing the architecture of the build configuration.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/sysinfo.jl#L74-L78)
```julia
Sys.MACHINE::String
```
A string containing the build triple.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/sysinfo.jl#L89-L93)
See also:
-   [`stdin`](../io-network/#Base.stdin)
-   [`stdout`](../io-network/#Base.stdout)
-   [`stderr`](../io-network/#Base.stderr)
-   [`ENV`](../base/#Base.ENV)
-   [`ENDIAN_BOM`](../io-network/#Base.ENDIAN_BOM)
------------------------------------------------------------------------


# Filesystem · The Julia Language
Source: https://docs.julialang.org/en/v1/base/file/


# [Filesystem](#Filesystem)
```julia
read(filename::AbstractString)
```
Read the entire contents of a file as a `Vector{UInt8}`.
```julia
read(filename::AbstractString, String)
```
Read the entire contents of a file as a string.
```julia
read(filename::AbstractString, args...)
```
Open a file and read its contents. `args` is passed to `read`: this is equivalent to `open(io->read(io, args...), filename)`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/io.jl#L491-L504)
```julia
write(filename::AbstractString, content)
```
Write the canonical binary representation of `content` to a file, which will be created if it does not exist yet or overwritten if it does exist.
Return the number of bytes written into the file.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/io.jl#L482-L488)
```julia
pwd() -> String
```
Get the current working directory.
See also: [`cd`](#Base.Filesystem.cd-Tuple%7BAbstractString%7D), [`tempdir`](#Base.Filesystem.tempdir).
**Examples**
```julia-repl
julia> pwd()
"/home/JuliaUser"

julia> cd("/home/JuliaUser/Projects/julia")

julia> pwd()
"/home/JuliaUser/Projects/julia"
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L34-L51)
```julia
cd(dir::AbstractString=homedir())
```
Set the current working directory.
See also: [`pwd`](#Base.Filesystem.pwd), [`mkdir`](#Base.Filesystem.mkdir), [`mkpath`](#Base.Filesystem.mkpath), [`mktempdir`](#Base.Filesystem.mktempdir-Tuple%7BAbstractString%7D).
**Examples**


# [Filesystem](#Filesystem)
```julia-repl
julia> cd("/home/JuliaUser/Projects/julia")

julia> pwd()
"/home/JuliaUser/Projects/julia"

julia> cd()

julia> pwd()
"/home/JuliaUser"
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L69-L88)
```julia
cd(f::Function, dir::AbstractString=homedir())
```
Temporarily change the current working directory to `dir`, apply function `f` and finally return to the original directory.
**Examples**
```julia-repl
julia> pwd()
"/home/JuliaUser"

julia> cd(readdir, "/home/JuliaUser/Projects/julia")
34-element Array{String,1}:
 ".circleci"
 ".freebsdci.sh"
 ".git"
 ".gitattributes"
 ".github"
 ⋮
 "test"
 "ui"
 "usr"
 "usr-staging"

julia> pwd()
"/home/JuliaUser"
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L119-L146)
```julia
readdir(dir::AbstractString=pwd();
    join::Bool = false,
    sort::Bool = true,
) -> Vector{String}
```
Return the names in the directory `dir` or the current working directory if not given. When `join` is false, `readdir` returns just the names in the directory as is; when `join` is true, it returns `joinpath(dir, name)` for each `name` so that the returned strings are full paths. If you want to get absolute paths back, call `readdir` with an absolute directory path and `join` set to true.
By default, `readdir` sorts the list of names it returns. If you want to skip sorting the names and get them in the order that the file system lists them, you can use `readdir(dir, sort=false)` to opt out of sorting.


# [Filesystem](#Filesystem)
See also: [`walkdir`](#Base.Filesystem.walkdir).
The `join` and `sort` keyword arguments require at least Julia 1.4.
**Examples**
```julia-repl
julia> cd("/home/JuliaUser/dev/julia")

julia> readdir()
30-element Array{String,1}:
 ".appveyor.yml"
 ".git"
 ".gitattributes"
 ⋮
 "ui"
 "usr"
 "usr-staging"

julia> readdir(join=true)
30-element Array{String,1}:
 "/home/JuliaUser/dev/julia/.appveyor.yml"
 "/home/JuliaUser/dev/julia/.git"
 "/home/JuliaUser/dev/julia/.gitattributes"
 ⋮
 "/home/JuliaUser/dev/julia/ui"
 "/home/JuliaUser/dev/julia/usr"
 "/home/JuliaUser/dev/julia/usr-staging"

julia> readdir("base")
145-element Array{String,1}:
 ".gitignore"
 "Base.jl"
 "Enums.jl"
 ⋮
 "version_git.sh"
 "views.jl"
 "weakkeydict.jl"

julia> readdir("base", join=true)
145-element Array{String,1}:
 "base/.gitignore"
 "base/Base.jl"
 "base/Enums.jl"
 ⋮
 "base/version_git.sh"
 "base/views.jl"
 "base/weakkeydict.jl"

julia> readdir(abspath("base"), join=true)
145-element Array{String,1}:
 "/home/JuliaUser/dev/julia/base/.gitignore"
 "/home/JuliaUser/dev/julia/base/Base.jl"
 "/home/JuliaUser/dev/julia/base/Enums.jl"
 ⋮
 "/home/JuliaUser/dev/julia/base/version_git.sh"
 "/home/JuliaUser/dev/julia/base/views.jl"
 "/home/JuliaUser/dev/julia/base/weakkeydict.jl"
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L840-L915)
```julia
walkdir(dir; topdown=true, follow_symlinks=false, onerror=throw)
```


# [Filesystem](#Filesystem)
Return an iterator that walks the directory tree of a directory. The iterator returns a tuple containing `(rootpath, dirs, files)`. The directory tree can be traversed top-down or bottom-up. If `walkdir` or `stat` encounters a `IOError` it will rethrow the error by default. A custom error handling function can be provided through `onerror` keyword argument. `onerror` is called with a `IOError` as argument.
See also: [`readdir`](#Base.Filesystem.readdir).
**Examples**
```julia
for (root, dirs, files) in walkdir(".")
    println("Directories in $root")
    for dir in dirs
        println(joinpath(root, dir)) # path to directories
    end
    println("Files in $root")
    for file in files
        println(joinpath(root, file)) # path to files
    end
end
```
```julia-repl
julia> mkpath("my/test/dir");

julia> itr = walkdir("my");

julia> (root, dirs, files) = first(itr)
("my", ["test"], String[])

julia> (root, dirs, files) = first(itr)
("my/test", ["dir"], String[])

julia> (root, dirs, files) = first(itr)
("my/test/dir", String[], String[])
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L1022-L1062)
```julia
mkdir(path::AbstractString; mode::Unsigned = 0o777)
```


# [Filesystem](#Filesystem)
Make a new directory with name `path` and permissions `mode`. `mode` defaults to `0o777`, modified by the current file creation mask. This function never creates more than one directory. If the directory already exists, or some intermediate directories do not exist, this function throws an error. See [`mkpath`](#Base.Filesystem.mkpath) for a function which creates all required intermediate directories. Return `path`.
**Examples**
```julia-repl
julia> mkdir("testingdir")
"testingdir"

julia> cd("testingdir")

julia> pwd()
"/home/JuliaUser/testingdir"
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L156-L176)
```julia
mkpath(path::AbstractString; mode::Unsigned = 0o777)
```
Create all intermediate directories in the `path` as required. Directories are created with the permissions `mode` which defaults to `0o777` and is modified by the current file creation mask. Unlike [`mkdir`](#Base.Filesystem.mkdir), `mkpath` does not error if `path` (or parts of it) already exists. However, an error will be thrown if `path` (or parts of it) points to an existing file. Return `path`.
If `path` includes a filename you will probably want to use `mkpath(dirname(path))` to avoid creating a directory using the filename.
**Examples**


# [Filesystem](#Filesystem)
```julia-repl
julia> cd(mktempdir())

julia> mkpath("my/test/dir") # creates three directories
"my/test/dir"

julia> readdir()
1-element Array{String,1}:
 "my"

julia> cd("my")

julia> readdir()
1-element Array{String,1}:
 "test"

julia> readdir("test")
1-element Array{String,1}:
 "dir"

julia> mkpath("intermediate_dir/actually_a_directory.txt") # creates two directories
"intermediate_dir/actually_a_directory.txt"

julia> isdir("intermediate_dir/actually_a_directory.txt")
true
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L194-L234)
```julia
hardlink(src::AbstractString, dst::AbstractString)
```
Creates a hard link to an existing source file `src` with the name `dst`. The destination, `dst`, must not exist.
See also: [`symlink`](#Base.Filesystem.symlink).
This method was added in Julia 1.8.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L1148-L1158)
```julia
symlink(target::AbstractString, link::AbstractString; dir_target = false)
```
Creates a symbolic link to `target` with the name `link`.


# [Filesystem](#Filesystem)
On Windows, symlinks must be explicitly declared as referring to a directory or not. If `target` already exists, by default the type of `link` will be auto- detected, however if `target` does not exist, this function defaults to creating a file symlink unless `dir_target` is set to `true`. Note that if the user sets `dir_target` but `target` exists and is a file, a directory symlink will still be created, but dereferencing the symlink will fail, just as if the user creates a file symlink (by calling `symlink()` with `dir_target` set to `false` before the directory is created) and tries to dereference it to a directory.
Additionally, there are two methods of making a link on Windows; symbolic links and junction points. Junction points are slightly more efficient, but do not support relative paths, so if a relative directory symlink is requested (as denoted by `isabspath(target)` returning `false`) a symlink will be used, else a junction point will be used. Best practice for creating symlinks on Windows is to create them only after the files/directories they reference are already created.
See also: [`hardlink`](#Base.Filesystem.hardlink).
This function raises an error under operating systems that do not support soft symbolic links, such as Windows XP.
The `dir_target` keyword argument was added in Julia 1.6. Prior to this, symlinks to nonexistent paths on windows would always be file symlinks, and relative symlinks to directories were not supported.


# [Filesystem](#Filesystem)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L1168-L1200)
```julia
readlink(path::AbstractString) -> String
```
Return the target location a symbolic link `path` points to.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L1244-L1248)
```julia
chmod(path::AbstractString, mode::Integer; recursive::Bool=false)
```
Change the permissions mode of `path` to `mode`. Only integer `mode`s (e.g. `0o777`) are currently supported. If `recursive=true` and the path is a directory all permissions in that directory will be recursively changed. Return `path`.
Prior to Julia 1.6, this did not correctly manipulate filesystem ACLs on Windows, therefore it would only set read-only bits on files. It now is able to manipulate ACLs.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L1268-L1280)
```julia
chown(path::AbstractString, owner::Integer, group::Integer=-1)
```
Change the owner and/or group of `path` to `owner` and/or `group`. If the value entered for `owner` or `group` is `-1` the corresponding ID will not change. Only integer `owner`s and `group`s are currently supported. Return `path`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L1294-L1300)
```julia
RawFD
```


# [Filesystem](#Filesystem)
Primitive type which wraps the native OS file descriptor. `RawFD`s can be passed to methods like [`stat`](#Base.stat) to discover information about the underlying file, and can also be used to open streams, with the `RawFD` describing the OS file backing the stream.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/libc.jl#L25-L33)
```julia
stat(file)
```
Return a structure whose fields contain information about the file. The fields of the structure are:
| Name    | Type                            | Description                                                        |
|:--------|:--------------------------------|:-------------------------------------------------------------------|
| desc    | `Union{String, Base.OS_HANDLE}` | The path or OS file descriptor                                     |
| size    | `Int64`                         | The size (in bytes) of the file                                    |
| device  | `UInt`                          | ID of the device that contains the file                            |
| inode   | `UInt`                          | The inode number of the file                                       |
| mode    | `UInt`                          | The protection mode of the file                                    |
| nlink   | `Int`                           | The number of hard links to the file                               |
| uid     | `UInt`                          | The user id of the owner of the file                               |
| gid     | `UInt`                          | The group id of the file owner                                     |
| rdev    | `UInt`                          | If this file refers to a device, the ID of the device it refers to |
| blksize | `Int64`                         | The file-system preferred block size for the file                  |
| blocks  | `Int64`                         | The number of 512-byte blocks allocated                            |
| mtime   | `Float64`                       | Unix timestamp of when the file was last modified                  |
| ctime   | `Float64`                       | Unix timestamp of when the file's metadata was changed             |


# [Filesystem](#Filesystem)
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L194-L215)
```julia
diskstat(path=pwd())
```
Returns statistics in bytes about the disk that contains the file or directory pointed at by `path`. If no argument is passed, statistics about the disk that contains the current working directory are returned.
This method was added in Julia 1.8.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L1341-L1350)
```julia
lstat(file)
```
Like [`stat`](#Base.stat), but for symbolic links gets the info for the link itself rather than the file it refers to. This function must be called on a file path rather than a file object or a file descriptor.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L218-L225)
```julia
ctime(file)
```
Equivalent to `stat(file).ctime`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L312-L316)
```julia
mtime(file)
```
Equivalent to `stat(file).mtime`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L305-L309)
```julia
filemode(file)
```
Equivalent to `stat(file).mode`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L275-L279)
```julia
filesize(path...)
```
Equivalent to `stat(file).size`.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L298-L302)


# [Filesystem](#Filesystem)
```julia
uperm(file)
```
Get the permissions of the owner of the file as a bitfield of
| Value | Description        |
|:------|:-------------------|
| 01    | Execute Permission |
| 02    | Write Permission   |
| 04    | Read Permission    |
For allowed arguments, see [`stat`](#Base.stat).
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L443-L455)
```julia
gperm(file)
```
Like [`uperm`](#Base.Filesystem.uperm) but gets the permissions of the group owning the file.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L458-L462)
```julia
operm(file)
```
Like [`uperm`](#Base.Filesystem.uperm) but gets the permissions for people who neither own the file nor are a member of the group owning the file
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/stat.jl#L465-L470)
```julia
cp(src::AbstractString, dst::AbstractString; force::Bool=false, follow_symlinks::Bool=false)
```
Copy the file, link, or directory from `src` to `dst`. `force=true` will first remove an existing `dst`.
If `follow_symlinks=false`, and `src` is a symbolic link, `dst` will be created as a symbolic link. If `follow_symlinks=true` and `src` is a symbolic link, `dst` will be a copy of the file or directory `src` refers to. Return `dst`.


# [Filesystem](#Filesystem)
The `cp` function is different from the `cp` command. The `cp` function always operates on the assumption that `dst` is a file, while the command does different things depending on whether `dst` is a directory or a file. Using `force=true` when `dst` is a directory will result in loss of all the contents present in the `dst` directory, and `dst` will become a file that has the contents of `src` instead.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L360-L377)
```julia
download(url::AbstractString, [path::AbstractString = tempname()]) -> path
```
Download a file from the given url, saving it to the location `path`, or if not specified, a temporary path. Returns the path of the downloaded file.
Since Julia 1.6, this function is deprecated and is just a thin wrapper around `Downloads.download`. In new code, you should use that function directly instead of calling this.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/download.jl#L8-L18)
```julia
mv(src::AbstractString, dst::AbstractString; force::Bool=false)
```
Move the file, link, or directory from `src` to `dst`. `force=true` will first remove an existing `dst`. Return `dst`.
**Examples**


# [Filesystem](#Filesystem)
```julia-repl
julia> write("hello.txt", "world");

julia> mv("hello.txt", "goodbye.txt")
"goodbye.txt"

julia> "hello.txt" in readdir()
false

julia> readline("goodbye.txt")
"world"

julia> write("hello.txt", "world2");

julia> mv("hello.txt", "goodbye.txt")
ERROR: ArgumentError: 'goodbye.txt' exists. `force=true` is required to remove 'goodbye.txt' before moving.
Stacktrace:
 [1] #checkfor_mv_cp_cptree#10(::Bool, ::Function, ::String, ::String, ::String) at ./file.jl:293
[...]

julia> mv("hello.txt", "goodbye.txt", force=true)
"goodbye.txt"

julia> rm("goodbye.txt");
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L391-L425)
```julia
rm(path::AbstractString; force::Bool=false, recursive::Bool=false)
```
Delete the file, link, or empty directory at the given path. If `force=true` is passed, a non-existing path is not treated as error. If `recursive=true` is passed and the path is a directory, then all contents are removed recursively.
**Examples**
```julia-repl
julia> mkpath("my/test/dir");

julia> rm("my", recursive=true)

julia> rm("this_file_does_not_exist", force=true)

julia> rm("this_file_does_not_exist")
ERROR: IOError: unlink("this_file_does_not_exist"): no such file or directory (ENOENT)
Stacktrace:
[...]
```
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/file.jl#L252-L272)
```julia
Base.touch(::Pidfile.LockMonitor)
```
Update the `mtime` on the lock, to indicate it is still fresh.