Reputation: 28490
The following code keeps waiting for user input, and echoes it back to screen when it gets it. Then it goes back in waiting-for-input mode. When it's in this state, it keeps writing a constant message on screen.
import Control.Concurrent
import Data.Maybe
import System.IO
main = do
hSetBuffering stdin NoBuffering
future_input <- newEmptyMVar
forkIO $ (>>) <$> putMVar future_input
<*> (putStrLn . ("pressed key: " ++) . return)
=<< getChar
wait future_input
where wait future_input = do
input <- tryTakeMVar future_input
if isJust input
then main
else putStrLn "keep waiting" >> threadDelay 1000000 >> wait future_input
What I would like to obtain, is that the message keep waiting
be accompained by the lates available user input.
The only idea I had so far, is that I should
MVar
, latest_input
together with future_input
future_input
else
of if isJust input
, I should tryTakeMVar
from latest_input
and, if there is something in it (which is, by virtue of point 2, always the case except the first time), I could use it in the output.However, in this smokey idea of mine, I think I should also have wait
take both MVar
s, because I don't have to lose track of any of them when waiting. Similarly, even in the then
branch of if isJust input
, I should probably pass latest_input
, which means I have to use a function other than main
, which would be called by main
.
For now, I've got here:
import Control.Concurrent
import Data.Maybe
import System.IO
main = do
hSetBuffering stdin NoBuffering
future_input <- newEmptyMVar
latest_input <- newEmptyMVar
forkIO $ ((>>) .) . (>>)
<$> putMVar future_input
<*> putMVar latest_input
<*> (putStrLn . ("pressed key: " ++) . return)
=<< getChar
wait future_input
where wait future_input = do
input <- tryTakeMVar future_input
if isJust input
then main
else putStrLn "keep moving" >> threadDelay 1000000 >> wait future_input
Upvotes: 0
Views: 90
Reputation: 28490
Uh, I think I got it :D (and I've put it in Code Review).
import Control.Concurrent
import Data.Maybe
import System.IO
main = do
hSetBuffering stdin NoBuffering
future_input <- newEmptyMVar
latest_input <- newEmptyMVar
putMVar latest_input 'A' -- assuming a previous input the first time
work future_input latest_input
work :: MVar Char -> MVar Char -> IO ()
work future_input latest_input = do
forkIO $ ((>>) .) . (>>)
<$> putMVar future_input
<*> tryPutMVar latest_input
<*> (putStrLn . ("pressed key: " ++) . return)
=<< getChar
wait future_input latest_input
where wait future_input latest_input = do
input <- tryTakeMVar future_input
old_input <- takeMVar latest_input
if isJust input
then do
putMVar latest_input (fromJust input)
work future_input latest_input
else do
putMVar latest_input old_input
putStrLn ("latest input was " ++ (return old_input))
>> threadDelay 1000000
>> wait future_input latest_input
Upvotes: 0