2012-03-31 3 views
1

Моя программа считывает строку из сетевого сокета и записывает его на диск. Поскольку строки могут быть очень длинными, а строки имеют ужасную производительность, я начал использовать ленивые строки байтов. Теперь, похоже, что Haskell будет пройти hClose на диск дескрипторе файла фактически не топить все байты строку на диск, таким образом:Принудительная оценка lazy IO

  • открыть файл для записи
  • записи байт строки в файл с hPut
  • закрыть файл
  • открыть файл для чтения

обычно приводит к openFile: resource busy (file is locked).

Возможно ли выполнить проверку и дождаться записи всей строки байта перед закрытием файла, поэтому я могу быть уверен, что файл фактически закрыт после этой операции?

+0

Вы смотрели на [ 'hFlush'] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.html#v:hFlush)? – huon

+0

Промывка не помогает, так как с помощью 'hClose' GHC проходит через нее, не дожидаясь. –

ответ

0

Поскольку единственный ответ на вопрос «использовать что-то еще», я отправляю свое собственное решение. С помощью этой функции после hClose будет висеть нить до тех пор, пока не будет выполнена ленивая запись.

waitForLazyIO location = do 
    t <- liftIO $ try $ openFile location AppendMode 
    handle t 
    where 
     handle (Right v) = hClose v 
     handle (Left e) 
      -- Add some sleep if you expect the write operation to be slow. 
      | isAlreadyInUseError e = waitForLazyIO location 
      | otherwise = throwError $ show e 
+0

Это может сработать, но, откровенно говоря, это взломать, не совсем обычные стандарты для программного обеспечения haskell. Лётный путь ввода-вывода полон ловушек, потому что концепция сломана тихо. В настоящий момент единственным жизнеспособным вариантом для операций ввода-вывода с постоянной памятью является семейство счетчиков с левым краем, из которых [канал] (http://hackage.haskell.org/package/conduit) является одним из популярных членов. –

0

Попробуйте использовать строгие i/o со строчными байтовыми строками вместо ленивых i/o и ленивых строк байтов.

Если это окажется слишком неэффективным, попробуйте использовать conduit или аналогичный пакет.

Смежные вопросы