@@ -11,11 +11,9 @@ module Development.IDE.Core.ProgressReporting
11
11
where
12
12
13
13
import Control.Concurrent.Async
14
- import Control.Concurrent.STM
15
14
import Control.Concurrent.Strict
16
15
import Control.Monad.Extra
17
16
import Control.Monad.IO.Class
18
- import qualified Control.Monad.STM as STM
19
17
import Control.Monad.Trans.Class (lift )
20
18
import Data.Foldable (for_ )
21
19
import qualified Data.HashMap.Strict as HMap
@@ -60,96 +58,69 @@ delayedProgressReporting
60
58
-> IO ProgressReporting
61
59
delayedProgressReporting before after lspEnv optProgressStyle = do
62
60
inProgressVar <- newVar (HMap. empty @ NormalizedFilePath @ Int )
63
- mostRecentProgressEvent <- newTVarIO KickCompleted
64
- progressAsync <- async $
65
- progressThread optProgressStyle mostRecentProgressEvent inProgressVar
66
- let progressUpdate = atomically . writeTVar mostRecentProgressEvent
67
- progressStop = cancel progressAsync
61
+ progressThread <- newVar =<< async (pure () )
62
+ let progressUpdate KickStarted = writeVar progressThread =<< async (mRunLspT lspEnv $ lspShakeProgress inProgressVar)
63
+ progressUpdate KickCompleted = readVar progressThread >>= cancel
64
+ progressStop = progressUpdate KickCompleted
68
65
inProgress :: NormalizedFilePath -> Action a -> Action a
69
66
inProgress = withProgressVar inProgressVar
70
67
return ProgressReporting {.. }
71
68
where
72
- -- The progress thread is a state machine with two states:
73
- -- 1. Idle
74
- -- 2. Reporting a kick event
75
- -- And two transitions, modelled by 'ProgressEvent':
76
- -- 1. KickCompleted - transitions from Reporting into Idle
77
- -- 2. KickStarted - transitions from Idle into Reporting
78
- progressThread style mostRecentProgressEvent inProgress = progressLoopIdle
79
- where
80
- progressLoopIdle = do
81
- atomically $ do
82
- v <- readTVar mostRecentProgressEvent
83
- case v of
84
- KickCompleted -> STM. retry
85
- KickStarted -> return ()
86
- asyncReporter <- async $ mRunLspT lspEnv lspShakeProgress
87
- progressLoopReporting asyncReporter
88
- progressLoopReporting asyncReporter = do
89
- atomically $ do
90
- v <- readTVar mostRecentProgressEvent
91
- case v of
92
- KickStarted -> STM. retry
93
- KickCompleted -> return ()
94
- cancel asyncReporter
95
- progressLoopIdle
69
+ lspShakeProgress inProgress = do
70
+ -- first sleep a bit, so we only show progress messages if it's going to take
71
+ -- a "noticable amount of time" (we often expect a thread kill to arrive before the sleep finishes)
72
+ liftIO $ sleep before
73
+ u <- ProgressTextToken . T. pack . show . hashUnique <$> liftIO newUnique
96
74
97
- lspShakeProgress :: LSP. LspM config ()
98
- lspShakeProgress = do
99
- -- first sleep a bit, so we only show progress messages if it's going to take
100
- -- a "noticable amount of time" (we often expect a thread kill to arrive before the sleep finishes)
101
- liftIO $ sleep before
102
- u <- ProgressTextToken . T. pack . show . hashUnique <$> liftIO newUnique
75
+ b <- liftIO newBarrier
76
+ void $ LSP. sendRequest LSP. SWindowWorkDoneProgressCreate
77
+ LSP. WorkDoneProgressCreateParams { _token = u } $ liftIO . signalBarrier b
78
+ ready <- liftIO $ waitBarrier b
103
79
104
- b <- liftIO newBarrier
105
- void $ LSP. sendRequest LSP. SWindowWorkDoneProgressCreate
106
- LSP. WorkDoneProgressCreateParams { _token = u } $ liftIO . signalBarrier b
107
- ready <- liftIO $ waitBarrier b
108
-
109
- for_ ready $ const $ bracket_ (start u) (stop u) (loop u 0 )
110
- where
111
- start id = LSP. sendNotification LSP. SProgress $
112
- LSP. ProgressParams
113
- { _token = id
114
- , _value = LSP. Begin $ WorkDoneProgressBeginParams
115
- { _title = " Processing"
116
- , _cancellable = Nothing
117
- , _message = Nothing
118
- , _percentage = Nothing
119
- }
120
- }
121
- stop id = LSP. sendNotification LSP. SProgress
122
- LSP. ProgressParams
123
- { _token = id
124
- , _value = LSP. End WorkDoneProgressEndParams
125
- { _message = Nothing
80
+ for_ ready $ const $ bracket_ (start u) (stop u) (loop u 0 )
81
+ where
82
+ start id = LSP. sendNotification LSP. SProgress $
83
+ LSP. ProgressParams
84
+ { _token = id
85
+ , _value = LSP. Begin $ WorkDoneProgressBeginParams
86
+ { _title = " Processing"
87
+ , _cancellable = Nothing
88
+ , _message = Nothing
89
+ , _percentage = Nothing
90
+ }
91
+ }
92
+ stop id = LSP. sendNotification LSP. SProgress
93
+ LSP. ProgressParams
94
+ { _token = id
95
+ , _value = LSP. End WorkDoneProgressEndParams
96
+ { _message = Nothing
97
+ }
98
+ }
99
+ loop id prev = do
100
+ current <- liftIO $ readVar inProgress
101
+ let done = length $ filter (== 0 ) $ HMap. elems current
102
+ let todo = HMap. size current
103
+ if todo == 0 then loop id 0 else do
104
+ let next = 100 * fromIntegral done / fromIntegral todo
105
+ liftIO $ sleep after
106
+ when (optProgressStyle /= NoProgress && next /= prev) $
107
+ LSP. sendNotification LSP. SProgress $
108
+ LSP. ProgressParams
109
+ { _token = id
110
+ , _value = LSP. Report $ case optProgressStyle of
111
+ Explicit -> LSP. WorkDoneProgressReportParams
112
+ { _cancellable = Nothing
113
+ , _message = Just $ T. pack $ show done <> " /" <> show todo
114
+ , _percentage = Nothing
115
+ }
116
+ Percentage -> LSP. WorkDoneProgressReportParams
117
+ { _cancellable = Nothing
118
+ , _message = Nothing
119
+ , _percentage = Just next
120
+ }
121
+ NoProgress -> error " unreachable"
126
122
}
127
- }
128
- loop id prev = do
129
- current <- liftIO $ readVar inProgress
130
- let done = length $ filter (== 0 ) $ HMap. elems current
131
- let todo = HMap. size current
132
- if todo == 0 then loop id 0 else do
133
- let next = 100 * fromIntegral done / fromIntegral todo
134
- liftIO $ sleep after
135
- when (style /= NoProgress && next /= prev) $
136
- LSP. sendNotification LSP. SProgress $
137
- LSP. ProgressParams
138
- { _token = id
139
- , _value = LSP. Report $ case style of
140
- Explicit -> LSP. WorkDoneProgressReportParams
141
- { _cancellable = Nothing
142
- , _message = Just $ T. pack $ show done <> " /" <> show todo
143
- , _percentage = Nothing
144
- }
145
- Percentage -> LSP. WorkDoneProgressReportParams
146
- { _cancellable = Nothing
147
- , _message = Nothing
148
- , _percentage = Just next
149
- }
150
- NoProgress -> error " unreachable"
151
- }
152
- loop id next
123
+ loop id next
153
124
154
125
withProgressVar var file = actionBracket (f succ ) (const $ f pred ) . const
155
126
-- This functions are deliberately eta-expanded to avoid space leaks.
0 commit comments