Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Q
quasar
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jens Nolte
quasar
Commits
66503392
Commit
66503392
authored
4 years ago
by
Jens Nolte
Browse files
Options
Downloads
Patches
Plain Diff
Implement DeltaObservable instance for ObservableHashMap
parent
8e93ca86
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/lib/Qd/Observable/ObservableHashMap.hs
+118
-41
118 additions, 41 deletions
src/lib/Qd/Observable/ObservableHashMap.hs
with
118 additions
and
41 deletions
src/lib/Qd/Observable/ObservableHashMap.hs
+
118
−
41
View file @
66503392
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
module
Qd.Observable.ObservableHashMap
(
module
Qd.Observable.ObservableHashMap
(
ObservableHashMap
,
ObservableHashMap
,
create
,
new
,
observeKey
,
observeKey
,
insert
,
insert
,
delete
,
delete
,
...
@@ -10,78 +10,155 @@ module Qd.Observable.ObservableHashMap (
...
@@ -10,78 +10,155 @@ module Qd.Observable.ObservableHashMap (
)
where
)
where
import
Qd.Observable
import
Qd.Observable
import
Qd.Observable.Delta
import
Qd.Prelude
hiding
(
lookup
,
lookupDelete
)
import
Qd.Prelude
hiding
(
lookup
,
lookupDelete
)
import
Qd.Utils.GetT
import
Qd.Utils.GetT
import
Control.Concurrent.MVar
import
Control.Concurrent.MVar
import
qualified
Data.HashMap.Strict
as
HM
import
qualified
Data.HashMap.Strict
as
HM
import
Data.Maybe
(
isJust
)
import
Data.Unique
import
Data.Unique
import
Language.Haskell.TH.Syntax
(
mkName
,
nameBase
)
import
Lens.Micro.Platform
newtype
ObservableHashMap
k
v
=
ObservableHashMap
(
MVar
(
HM
.
HashMap
k
(
ObservableValue
v
)))
data
ObservableValue
v
=
ObservableValue
{
newtype
ObservableHashMap
k
v
=
ObservableHashMap
(
MVar
(
Handle
k
v
))
data
Handle
k
v
=
Handle
{
keyHandles
::
HM
.
HashMap
k
(
KeyHandle
v
),
subscribers
::
HM
.
HashMap
Unique
(
ObservableMessage
(
HM
.
HashMap
k
v
)
->
IO
()
),
deltaSubscribers
::
HM
.
HashMap
Unique
(
Delta
k
v
->
IO
()
)
}
data
KeyHandle
v
=
KeyHandle
{
value
::
Maybe
v
,
value
::
Maybe
v
,
s
ubscribers
::
(
HM
.
HashMap
Unique
(
ObservableMessage
(
Maybe
v
)
->
IO
()
))
keyS
ubscribers
::
(
HM
.
HashMap
Unique
(
ObservableMessage
(
Maybe
v
)
->
IO
()
))
}
}
modifyValue
::
forall
k
v
a
.
(
Eq
k
,
Hashable
k
)
=>
(
ObservableValue
v
->
IO
(
ObservableValue
v
,
a
))
->
k
->
ObservableHashMap
k
v
->
IO
a
makeLensesWith
(
lensField
.~
(
\
_
_
->
pure
.
TopName
.
mkName
.
(
"_"
<>
)
.
nameBase
)
$
lensRules
)
''Handle
modifyValue
f
k
(
ObservableHashMap
mvar
)
=
modifyMVar
mvar
$
\
hashmap
->
runGetT
(
HM
.
alterF
update
k
hashmap
)
makeLensesWith
(
lensField
.~
(
\
_
_
->
pure
.
TopName
.
mkName
.
(
"_"
<>
)
.
nameBase
)
$
lensRules
)
''KeyHandle
instance
Gettable
(
HM
.
HashMap
k
v
)
(
ObservableHashMap
k
v
)
where
getValue
(
ObservableHashMap
mvar
)
=
HM
.
mapMaybe
value
.
keyHandles
<$>
readMVar
mvar
instance
Observable
(
HM
.
HashMap
k
v
)
(
ObservableHashMap
k
v
)
where
subscribe
ohm
callback
=
modifyHandle
update
ohm
where
update
::
Handle
k
v
->
IO
(
Handle
k
v
,
SubscriptionHandle
)
update
handle
=
do
callback
(
Current
,
toHashMap
handle
)
unique
<-
newUnique
let
handle'
=
handle
&
set
(
_subscribers
.
at
unique
)
(
Just
callback
)
return
(
handle'
,
SubscriptionHandle
$
unsubscribe
unique
)
unsubscribe
::
Unique
->
IO
()
unsubscribe
unique
=
modifyHandle_
(
return
.
set
(
_subscribers
.
at
unique
)
Nothing
)
ohm
instance
DeltaObservable
k
v
(
ObservableHashMap
k
v
)
where
subscribeDelta
ohm
callback
=
modifyHandle
update
ohm
where
update
::
Handle
k
v
->
IO
(
Handle
k
v
,
SubscriptionHandle
)
update
handle
=
do
callback
(
Reset
$
toHashMap
handle
)
unique
<-
newUnique
let
handle'
=
handle
&
set
(
_deltaSubscribers
.
at
unique
)
(
Just
callback
)
return
(
handle'
,
SubscriptionHandle
$
unsubscribe
unique
)
unsubscribe
::
Unique
->
IO
()
unsubscribe
unique
=
modifyHandle_
(
return
.
set
(
_deltaSubscribers
.
at
unique
)
Nothing
)
ohm
-- TODO
--subscribeAbstraction :: SomeIndexedLens -> (a -> v) -> (IO (a, r) -> IO r) -> (v -> IO ()) -> IO r
--subscribeAbstraction setter getCurrent modifyMVar callback = modify $ do
toHashMap
::
Handle
k
v
->
HM
.
HashMap
k
v
toHashMap
=
HM
.
mapMaybe
value
.
keyHandles
modifyHandle
::
(
Handle
k
v
->
IO
(
Handle
k
v
,
a
))
->
ObservableHashMap
k
v
->
IO
a
modifyHandle
f
(
ObservableHashMap
mvar
)
=
modifyMVar
mvar
f
modifyHandle_
::
(
Handle
k
v
->
IO
(
Handle
k
v
))
->
ObservableHashMap
k
v
->
IO
()
modifyHandle_
f
=
modifyHandle
(
fmap
(,
()
)
.
f
)
modifyKeyHandle
::
(
Eq
k
,
Hashable
k
)
=>
(
KeyHandle
v
->
IO
(
KeyHandle
v
,
a
))
->
k
->
ObservableHashMap
k
v
->
IO
a
modifyKeyHandle
f
k
=
modifyHandle
(
updateKeyHandle
f
k
)
modifyKeyHandle_
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
(
KeyHandle
v
->
IO
(
KeyHandle
v
))
->
k
->
ObservableHashMap
k
v
->
IO
()
modifyKeyHandle_
f
=
modifyKeyHandle
(
fmap
(,
()
)
.
f
)
updateKeyHandle
::
forall
k
v
a
.
(
Eq
k
,
Hashable
k
)
=>
(
KeyHandle
v
->
IO
(
KeyHandle
v
,
a
))
->
k
->
Handle
k
v
->
IO
(
Handle
k
v
,
a
)
updateKeyHandle
f
k
=
runGetT
.
(
_keyHandles
(
HM
.
alterF
updateMaybe
k
))
where
where
update
::
Maybe
(
ObservableValue
v
)
->
GetT
a
IO
(
Maybe
(
ObservableValue
v
))
updateMaybe
::
Maybe
(
KeyHandle
v
)
->
GetT
a
IO
(
Maybe
(
KeyHandle
v
))
update
=
fmap
toMaybe
.
(
GetT
.
f
)
.
fromMaybe
emptyObservableValue
updateMaybe
=
fmap
toMaybe
.
(
GetT
.
f
)
.
fromMaybe
emptyKeyHandle
emptyObservableValue
::
ObservableValue
v
emptyKeyHandle
::
KeyHandle
v
emptyObservableValue
=
ObservableValue
Nothing
HM
.
empty
emptyKeyHandle
=
KeyHandle
Nothing
HM
.
empty
toMaybe
::
ObservableValue
v
->
Maybe
(
ObservableValue
v
)
toMaybe
::
KeyHandle
v
->
Maybe
(
KeyHandle
v
)
toMaybe
(
ObservableValue
Nothing
(
HM
.
null
->
True
))
=
Nothing
toMaybe
(
KeyHandle
Nothing
(
HM
.
null
->
True
))
=
Nothing
toMaybe
ov
=
Just
ov
toMaybe
keyHandle
=
Just
keyHandle
modifyKeyHandleNotifying
::
(
Eq
k
,
Hashable
k
)
=>
(
KeyHandle
v
->
IO
(
KeyHandle
v
,
(
Maybe
(
Delta
k
v
),
a
)))
->
k
->
ObservableHashMap
k
v
->
IO
a
modifyKeyHandleNotifying
f
k
=
modifyHandle
$
\
handle
->
do
(
newHandle
,
(
delta
,
result
))
<-
updateKeyHandle
f
k
handle
notifySubscribers
newHandle
delta
return
(
newHandle
,
result
)
modifyKeyHandleNotifying_
::
(
Eq
k
,
Hashable
k
)
=>
(
KeyHandle
v
->
IO
(
KeyHandle
v
,
Maybe
(
Delta
k
v
)))
->
k
->
ObservableHashMap
k
v
->
IO
()
modifyKeyHandleNotifying_
f
k
=
modifyHandle_
$
\
handle
->
do
(
newHandle
,
delta
)
<-
updateKeyHandle
f
k
handle
notifySubscribers
newHandle
delta
return
newHandle
modifyValue_
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
(
ObservableValue
v
->
IO
(
ObservableValue
v
))
->
k
->
ObservableHashMap
k
v
->
IO
()
notifySubscribers
::
Handle
k
v
->
Maybe
(
Delta
k
v
)
->
IO
()
modifyValue_
f
=
modifyValue
(
fmap
(,
()
)
.
f
)
notifySubscribers
_
Nothing
=
return
()
notifySubscribers
handle
@
Handle
{
deltaSubscribers
,
subscribers
}
(
Just
delta
)
=
do
mapM_
(
$
delta
)
$
HM
.
elems
deltaSubscribers
mapM_
(
$
(
Update
,
toHashMap
handle
))
$
HM
.
elems
subscribers
modifySubscribers
::
(
HM
.
HashMap
Unique
(
ObservableMessage
(
Maybe
v
)
->
IO
()
)
->
HM
.
HashMap
Unique
(
ObservableMessage
(
Maybe
v
)
->
IO
()
))
->
ObservableValue
v
->
ObservableValu
e
v
modify
Key
Subscribers
::
(
HM
.
HashMap
Unique
(
ObservableMessage
(
Maybe
v
)
->
IO
()
)
->
HM
.
HashMap
Unique
(
ObservableMessage
(
Maybe
v
)
->
IO
()
))
->
KeyHandle
v
->
KeyHandl
e
v
modifySubscribers
f
ov
@
ObservableValue
{
subscribers
}
=
ov
{
subscribers
=
f
s
ubscribers
}
modify
Key
Subscribers
f
=
over
_keyS
ubscribers
f
create
::
IO
(
ObservableHashMap
k
v
)
new
::
IO
(
ObservableHashMap
k
v
)
create
=
ObservableHashMap
<$>
newMVar
H
M
.
empty
new
=
ObservableHashMap
<$>
newMVar
H
andle
{
keyHandles
=
HM
.
empty
,
subscribers
=
HM
.
empty
,
deltaSubscribers
=
HM
.
empty
}
observeKey
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
k
->
ObservableHashMap
k
v
->
SomeObservable
(
Maybe
v
)
observeKey
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
k
->
ObservableHashMap
k
v
->
SomeObservable
(
Maybe
v
)
observeKey
key
om
@
(
ObservableHashMap
mvar
)
=
SomeObservable
FnObservable
{
getValueFn
,
subscribeFn
}
observeKey
key
o
h
m
@
(
ObservableHashMap
mvar
)
=
SomeObservable
FnObservable
{
getValueFn
,
subscribeFn
}
where
where
getValueFn
::
IO
(
Maybe
v
)
getValueFn
::
IO
(
Maybe
v
)
getValueFn
=
(
value
<=<
HM
.
lookup
key
)
<$>
readMVar
mvar
getValueFn
=
join
.
preview
(
_keyHandles
.
at
key
.
_Just
.
_value
)
<$>
readMVar
mvar
subscribeFn
::
((
ObservableMessage
(
Maybe
v
)
->
IO
()
)
->
IO
SubscriptionHandle
)
subscribeFn
::
((
ObservableMessage
(
Maybe
v
)
->
IO
()
)
->
IO
SubscriptionHandle
)
subscribeFn
callback
=
do
subscribeFn
callback
=
do
subscriptionKey
<-
newUnique
subscriptionKey
<-
newUnique
modify
Valu
e_
(
subscribeFn'
subscriptionKey
)
key
om
modify
KeyHandl
e_
(
subscribeFn'
subscriptionKey
)
key
o
h
m
return
$
SubscriptionHandle
$
unsubscribe
subscriptionKey
return
$
SubscriptionHandle
$
unsubscribe
subscriptionKey
where
where
subscribeFn'
::
Unique
->
ObservableValue
v
->
IO
(
ObservableValu
e
v
)
subscribeFn'
::
Unique
->
KeyHandle
v
->
IO
(
KeyHandl
e
v
)
subscribeFn'
subKey
ov
@
ObservableValu
e
{
value
}
=
do
subscribeFn'
subKey
keyHandle
@
KeyHandl
e
{
value
}
=
do
callback
(
Current
,
value
)
callback
(
Current
,
value
)
return
$
modifySubscribers
(
HM
.
insert
subKey
callback
)
ov
return
$
modify
Key
Subscribers
(
HM
.
insert
subKey
callback
)
keyHandle
unsubscribe
::
Unique
->
IO
()
unsubscribe
::
Unique
->
IO
()
unsubscribe
subKey
=
modify
Valu
e_
(
return
.
modifySubscribers
(
HM
.
delete
subKey
))
key
om
unsubscribe
subKey
=
modify
KeyHandl
e_
(
return
.
modify
Key
Subscribers
(
HM
.
delete
subKey
))
key
o
h
m
insert
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
k
->
v
->
ObservableHashMap
k
v
->
IO
()
insert
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
k
->
v
->
ObservableHashMap
k
v
->
IO
()
insert
key
value
=
modify
Value
_
fn
key
insert
key
value
=
modify
KeyHandleNotifying
_
fn
key
where
where
fn
::
ObservableValue
v
->
IO
(
ObservableValue
v
)
fn
::
KeyHandle
v
->
IO
(
KeyHandle
v
,
Maybe
(
Delta
k
v
))
fn
ov
@
ObservableValue
{
subscribers
}
=
do
fn
keyHandle
@
KeyHandle
{
value
=
oldValue
,
keySubscribers
}
=
do
mapM_
(
$
(
Update
,
Just
value
))
$
HM
.
elems
subscribers
mapM_
(
$
(
Update
,
Just
value
))
$
HM
.
elems
keySubscribers
return
ov
{
value
=
Just
value
}
let
delta
=
if
isJust
oldValue
then
Change
key
value
else
Add
key
value
return
(
keyHandle
{
value
=
Just
value
},
Just
delta
)
delete
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
k
->
ObservableHashMap
k
v
->
IO
()
delete
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
k
->
ObservableHashMap
k
v
->
IO
()
delete
=
modify
Value_
fn
delete
key
=
modify
KeyHandleNotifying_
fn
key
where
where
fn
::
ObservableValue
v
->
IO
(
ObservableValue
v
)
fn
::
KeyHandle
v
->
IO
(
KeyHandle
v
,
Maybe
(
Delta
k
v
))
fn
ov
@
ObservableValue
{
subscribers
}
=
do
fn
keyHandle
@
KeyHandle
{
value
=
oldValue
,
keySubscribers
}
=
do
mapM_
(
$
(
Update
,
Nothing
))
$
HM
.
elems
subscribers
mapM_
(
$
(
Update
,
Nothing
))
$
HM
.
elems
keySubscribers
return
ov
{
value
=
Nothing
}
let
delta
=
if
isJust
oldValue
then
Just
(
Remove
key
)
else
Nothing
return
(
keyHandle
{
value
=
Nothing
},
delta
)
lookupDelete
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
k
->
ObservableHashMap
k
v
->
IO
(
Maybe
v
)
lookupDelete
::
forall
k
v
.
(
Eq
k
,
Hashable
k
)
=>
k
->
ObservableHashMap
k
v
->
IO
(
Maybe
v
)
lookupDelete
=
modify
Value
fn
lookupDelete
key
=
modify
KeyHandleNotifying
fn
key
where
where
fn
::
ObservableValue
v
->
IO
(
ObservableValue
v
,
Maybe
v
)
fn
::
KeyHandle
v
->
IO
(
KeyHandle
v
,
(
Maybe
(
Delta
k
v
),
Maybe
v
))
fn
ov
@
ObservableValue
{
value
=
oldValue
,
subscribers
}
=
do
fn
keyHandle
@
KeyHandle
{
value
=
oldValue
,
keySubscribers
}
=
do
mapM_
(
$
(
Update
,
Nothing
))
$
HM
.
elems
subscribers
mapM_
(
$
(
Update
,
Nothing
))
$
HM
.
elems
keySubscribers
return
(
ov
{
value
=
Nothing
},
oldValue
)
let
delta
=
if
isJust
oldValue
then
Just
(
Remove
key
)
else
Nothing
return
(
keyHandle
{
value
=
Nothing
},
(
delta
,
oldValue
))
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment