Skip to content

Commit

Permalink
rework some docs
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy committed Aug 18, 2023
1 parent 47269ce commit 795d0de
Showing 1 changed file with 46 additions and 17 deletions.
63 changes: 46 additions & 17 deletions doc/src/base/scopedvalues.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,76 @@ In particular dynamical scopes are propagated through [Task](@ref)s.
In its simplest form you can create a [`ScopedValue`](@ref) with a
default value and then use [`scoped`](@ref) to enter a new dynamical
scope. The new scope will inherit all values from the parent scope
(and recursivly from all outer scopes) with the the provided scoped
(and recursivly from all outer scopes) with the provided scoped
value taking priority over previous definitions.

```julia
const scoped_val = ScopedValue(1)
const scoped_val2 = ScopedValue(2)
const scoped_val2 = ScopedValue(0)

# Enter a new dynamic scope and set value
@show scoped_val[] # 1
@show scoped_val2[] # 0
scoped(scoped_val => 2) do
@show scoped_val[] # 2
@show scoped_val2[] # 2
@show scoped_val2[] # 0
scoped(scoped_val => 3, scoped_val2 => 5) do
@show scoped_val[] # 3
@show scoped_val2[] # 5
end
@show scoped_val[] # 2
@show scoped_val2[] # 0
end
@show scoped_val[] # 1
@show scoped_val2[] # 0
```

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.

```julia
const scoped_dict = ScopedValue(Dict())
Care is also required when storing references to mutable state in scoped
values. You might want to explicitly unshare when entering a new dynamic scope.

# Important we are using `merge` to "unshare" the mutable values
# across the different views of the same scoped value.
scoped(svar_dict => merge(svar_dict, Dict(:a => 10))) do
@show svar_dict[][:a]
```julia
import 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
```

Care is also required when storing references to mutable state in scoped
values. You might want to explicitly unshare when entering a new dynamic scope.
@sync begin
# If we instead pass a unique dictionary to each
# task we can access the dictonaries race free.
scoped(sval_dict => Dict())
@spawn (sval_dict[][:a] = 3)
end
scoped(sval_dict => Dict())
@spawn (sval_dict[][:b] = 3)
end
end

# 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 dictonary in parent scope.
@sync begin
scoped(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
```

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 now 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 and our only alternative would have
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
Expand All @@ -73,6 +101,7 @@ function open(connection::Database)
end

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

0 comments on commit 795d0de

Please sign in to comment.