- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
{-# LANGUAGE ExistentialQuantification,
DeriveDataTypeable,
PatternSignatures #-}
import Data.Typeable
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Concurrent.Chan
-- Core data types
data Message = forall t . Typeable t => Message t | StopMessage
deriving Typeable
data Handler = forall t . Typeable t => Handler (t -> IO ())
-- Worker thread
data Worker = Worker (Chan Message) (MVar ())
workerThread :: [Handler] -> Chan Message -> MVar () -> IO ()
workerThread handlers chan finish = loop where
loop = do
message <- readChan chan
case message of
StopMessage -> putMVar finish ()
Message val -> do
foldr (tryHandler val) (putStrLn "Unhandled message") handlers
loop
tryHandler val (Handler h) rest = maybe rest h (cast val)
startWorker :: [Handler] -> IO Worker
startWorker handlers = do
chan <- newChan
finish <- newEmptyMVar
forkIO (workerThread handlers chan finish)
return $ Worker chan finish
send :: Typeable m => Worker -> m -> IO ()
send (Worker chan _) message = do
writeChan chan $ Message message
stopWorker :: Worker -> IO ()
stopWorker (Worker chan finish) = do
writeChan chan $ StopMessage
takeMVar finish
-- Some tests
data Test = Test Bool String deriving Typeable
intHandler :: Int -> IO ()
intHandler val = putStrLn $ "Int: " ++ show (val * 2)
strHandler :: String -> IO ()
strHandler val = putStrLn $ "String: " ++ reverse val
testHandler :: Test -> IO ()
testHandler (Test b s) = putStrLn $ "Test: " ++ show b ++ " " ++ show s
main = do
w <- startWorker [
Handler intHandler,
Handler (\(val::Char) -> putStrLn $ "Char: " ++ show val),
Handler strHandler,
Handler testHandler]
send w (5::Int)
send w False
send w 'a'
send w "foo"
send w (Test True "bar")
stopWorker w
putStrLn "Finished!"
Вот такая вот портянка была написана под влиянием дискуссии с HaskellGovno http://govnokod.ru/11968, и недавней его просьбой рассказать об общении потоков в хаскеле.
Код запускает тред, в который можно передавать различные сообщения (ограничение только одно - тип сообщения должен быть инстансом тайпкласса Typeable). В треде исполняются указанные хендлеры, каждый из которых ловит свой тип сообщений.
P.S. Для неимеющих хаскеля, но желающих посмотреть на работу кода: http://ideone.com/OMVamc.
HaskellGovno 22.10.2012 19:40 # 0
Очень красиво. :) Декларативно. А как этот паттерн называется? Планировщик на основе статически типизированных сообщений?
eth0 22.10.2012 19:51 # 0
HaskellGovno 22.10.2012 19:57 # 0
bormand 22.10.2012 20:21 # 0
3.14159265 22.10.2012 19:58 # +2
А хендлеры - это вновь изобретенный полиморфизм или же мультиметоды, если хотите.
>StopMessage -> putMVar finish ()
А без отравленных сообщений никак нельзя? Недолюбливаю я эти пилюли.
Ничего сверхгодного в вашем бомжественном хацкиле нету, я такую же хреновину в императивном стиле напишу за 15 минут с библиотечной очередью.
bormand 22.10.2012 20:15 # +1
Они самые. В том же лиспе это нативно работает.
> А без отравленных сообщений никак нельзя? Недолюбливаю я эти пилюли.
Поясните плиз, что не так со StopMessage?
> я такую же хреновину в императивном стиле напишу за 15 минут с библиотечной очередью
Да я не спорю ;). На питоне всяко и за 5 можно управиться.
3.14159265 22.10.2012 20:17 # +2
Да как-то некошерно в очереди с данными передавать управляющие конвеером сообщения.
bormand 22.10.2012 20:28 # 0
> volatile boolean terminated=false;
Так с этим булом потом начинаются проблемы - надо одновременно опрашивать и бул и очередь. Как это сделать в хаскеле - я х.з.
Имхо даже в императивном языке проще кинуть особое сообщение для остановки треда, чем городить этот огород с булом и его опросом.
3.14159265 22.10.2012 20:33 # +1
Отож. И я об этом.
>даже в императивном языке проще кинуть особое сообщение для остановки треда
Если потребителей много - не проще. Или надо делать одного потребителя и тредпул, которому он раздает задания.
Конечно если других средств коммуникации помимо канала нету - то символ "Конец передачи" неизбежен.
PS. Херня какая-то с говнокодом. Сессии на главной нету, а на остальных есть.
bormand 22.10.2012 20:38 # +2
Как вариант - если у нас N воркеров - вбросить N сообщений об остановке. Каждый получит ровно по одному. Минус способа - надо знать сколько именно запущено воркеров.
3.14159265 22.10.2012 20:43 # +1
Ну ведь потому и костыль. В данном случае оно вылазит наружу во всей красе.
Говно всплывает к верху, так сказать.
Переменная, а зачастую какой-то енум с состояниями INIT,RUN,STOP,FAIL гораздо лучше.
TarasB 22.10.2012 20:47 # 0
3.14159265 22.10.2012 20:53 # +3
- Баттхед, ты слышал, он сказал: "прибор!".
- А еще он сказал "канал"! Гы-гы-гы.
roskomgovno 25.05.2018 19:49 # −1
Doctor_Who 25.05.2018 20:13 # −1
3.14159265 22.10.2012 20:23 # 0
тогда непонятно в чем крутота хацкила, если всё то же, но только хуёвей.
Он по идее должен сам как-то всё асспараллелить и предоставить какую-то сверхудобную реализацию producer-consumer отношений.
HaskellGovno 22.10.2012 20:24 # −3
Я расскажу тебе свою историю.
Я учился в университете, по специальности программист. Да, я не был в группе самым одарённым, но я пытался что-то делать. Нам преподавали C++. Я не очень это всё понимал. Мои одногруппники были не очень хорошими людьми, и всегда не воспринимали меня и даже ущемляли. Преподы тоже не упускали своего и говорили, что только тупые не могут понять C++. Я не был тупой, я просто не понимал зачем всё это нужно?
Однажды я шёл по городу, ел шаурму, думая как бы им всем доказать, что я круче их.
И вдруг я услышал разговор двух молодых парней, которые выходили из новой машины, они говорили про программирование. Они были классно одеты. У них было много денег. Я хотел быть ими. Я подошёл к ним и спросил:
— Как мне стать таким как Вы?
Они улыбнулись и сказали: “Пошли с нами”.
HaskellGovno 22.10.2012 20:24 # −2
Когда я пришёл на защиту, то там собралась вся группа.
Они подходили к компьютерам и демонстрировали применение паттернов и шаблонов, наследование и прочее, всё что на самом деле не нужно.
Потом настала моя очередь. Я встал и медленно шёл. Они смеялись и кричали — что не написал видать?
Когда я показал этот код, который делал одной строчкой то, что у них было в 25 классах, они замолчали. Я встал и ушёл.
Говорят препод ушёл с работы из-за того, что свихнулся, он не мог поверить что его C++ не нужен.
Я теперь иногда телефоны своих одногруппников в газете объявлений, где они готовы работать за еду. Но мне пофиг, я знаю Haskell, что приносит мне тысячи долларов.
3.14159265 22.10.2012 20:27 # +5
2. Тухло, ведь я уже читал эту пасту.
3. Она неуместна - в примере 50 строк потрачено на конвейер.
bormand 22.10.2012 20:33 # +1
+
> 2. Тухло, ведь я уже читал эту пасту.
+
> 3. Она неуместна - в примере 50 строк потрачено на конвейер.
Ну не на сам конвейер, в качестве которого тут использовался готовый Chan, а на тред, который этот конвейер использует.
TarasB 22.10.2012 20:41 # +2
Lure Of Chaos 23.10.2012 10:29 # +4
я поступил в универ. там было все: и матан, и жаба, и паскакаль, и сци и сци-крест-крест, и васик, и алгоритмы и структуры данных, и опенжл, и даже философия, психология и физкультура.
и мне это все было интересно и сложно, но я не стал золотомедалистом по одной причине: еще на первом курсе нам преподавали самые основы поцкаля. на первую же лабу я постарался:
слабал на трубопоцкале игрулю тетрис, со всеми наворотами: и режим 320х200х256 и ассмовставки, и графоэффекты типа шторок и затемнения, и уровни, и спецфигуры - полный блекджек. и даже шлюхи были после каждого пройденного уровня. не было только музыки по причине отсутствия колонок.
я был глуп и наивен, с широко открытыми глазами, полными желания постигать и творить круть несусветную. но жизнь меня обломала, и я стал учиться из рук вон плохо, так и не окончив: препод покивал головой, позыркал на шлюх, и сказал:
- это все очень хорошо, но для нашей программы этого всего не нужно.
roskomgovno 29.07.2018 01:35 # 0
HaskellGovno 22.10.2012 20:10 # 0
roman-kashitsyn 22.10.2012 20:13 # +4
HaskellGovno 22.10.2012 20:19 # 0
Abbath 22.10.2012 20:28 # −1
HaskellGovno 22.10.2012 20:35 # 0
Abbath 22.10.2012 21:02 # −1
HaskellGovno 22.10.2012 22:19 # 0
Даже на нашем.
guest 23.10.2012 00:24 # +4
HaskellGovno 23.10.2012 00:28 # +3
HaskellGovno 23.10.2012 02:43 # 0
Спасибо. :)
guest8 28.07.2018 00:40 # −999
roman-kashitsyn 28.07.2018 00:55 # 0
guest8 28.07.2018 01:07 # −999
roman-kashitsyn 28.07.2018 01:14 # +1
vistefan 28.07.2018 01:44 # 0
666_N33D135 28.07.2018 06:11 # 0
666_N33D135 28.07.2018 06:42 # 0
666_N33D135 28.07.2018 10:37 # 0
roman-kashitsyn 29.07.2018 01:28 # 0
KOHTPArEHTTBOEuMAMKu 29.07.2018 01:29 # 0