| | 138 | == Building Concurrency Primitives == |
| | 139 | |
| | 140 | Now that we have defined an abstract interface, lets look at how to construct concurrency primitives using the scheduler actions. The implementation of primitives `yield` and `forkIO` using the scheduler actions is shown below. |
| | 141 | |
| | 142 | {{{ |
| | 143 | yield :: IO () |
| | 144 | yield = atomically $ do |
| | 145 | s <- getCurrentSCont |
| | 146 | -- Append current SCont to scheduler |
| | 147 | ssa <- getScheduleSContAction s |
| | 148 | enque :: PTM () <- ssa a |
| | 149 | enque |
| | 150 | -- Switch to next SCont from scheduler |
| | 151 | switchToNext :: PTM () <- getYieldControlAction s |
| | 152 | switchToNext |
| | 153 | |
| | 154 | forkIO :: IO () -> IO SCont |
| | 155 | forkIO f = do |
| | 156 | ns <- newSCont f |
| | 157 | atomically $ do { |
| | 158 | s <- getCurrentSCont; |
| | 159 | -- Initialize scheduler actions |
| | 160 | ssa <- getScheduleSContAction s; |
| | 161 | setScheduleSContAction ns ssa; |
| | 162 | yca <- getYieldControlAction s; |
| | 163 | setYieldControlAction ns yca; |
| | 164 | -- Append the new SCont to current SCont's scheduler |
| | 165 | appendAct <- ssa ns; |
| | 166 | appendAct |
| | 167 | } |
| | 168 | return ns |
| | 169 | }}} |
| | 170 | |