Параллельные действия Haskell с тайм-аутом

Pro
вы продолжаете работать со строго типизированными объектами, как вы хотели

Против
Некоторым людям действительно не нравится: расширяет


package foo;
import com.mongodb.BasicDBObject;

public class Employee extends BasicDBObject {

private static final long serialVersionUID = 2105061907470199595L;
//should be something shorter as "name" like "n" 
//here just use name to conform your  sample
public static final String NAME = "name";
public static final String NO = "no";
public static final String COLLECTION_NAME = "employee";

public Long getNo() {
    return getLong(NO);
}

public void setNo(long no) {
    put(NO, no);
}

public String getName() {
    return getString(NAME);
}

public void setName(String name) {
    put(NAME, name);
}

}


package foo;
import java.net.UnknownHostException;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

public class Test {

public static void main(String[] args) throws UnknownHostException,
        MongoException {

    Mongo mongo = new Mongo("localhost", 27017);
    DB db = mongo.getDB("yeahMongo");

    Employee employee = new Employee();
    employee.setNo(1L);
    employee.setName("yogesh");

    DBCollection employeeCollection = null ;
    employeeCollection = db.getCollection(Employee.COLLECTION_NAME);

    employeeCollection.save(employee);

    System.err.println(employeeCollection.findOne());

}

}

В дополнение к морфии вы должны взглянуть на jongo: http://jongo.org/ jongo использует тот же синтаксис формы, что и js mongo двигатель, и я нашел это отличное место для начинающего. Вам не нужно переключать свою ментальную карту между mongojs и java. Вы можете использовать образец js с небольшими изменениями.

6
задан Cetin Sert 30 May 2009 в 20:54
поделиться

2 ответа

Реализовать желаемый timed поверх System.Timeout.timeout очень просто:

import System.Timeout (timeout)

timed :: Int -> IO a -> b -> IO (Either b a)
timed us act def = liftM (maybe (Left def) Right) (timeout us act)

Между прочим, обычная реализация ] timeout ближе к следующему: ( $! = seq , чтобы попытаться принудительно выполнить оценку возвращаемого значения в потоке, а не только вернуть преобразователь):

import Control.Concurrent (forkIO, threadDelay, killThread)
import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)
import System.IO (hPrint, stderr)

timeout :: Int -> IO a -> IO (Maybe a)
timeout us act = do
    mvar <- newEmptyMVar
    tid1 <- forkIO $ (putMVar mvar . Just $!) =<< act
    tid2 <- forkIO $ threadDelay us >> putMVar mvar Nothing
    res <- takeMVar mvar
    killThread (maybe tid1 (const tid2) res) `catch` hPrint stderr
    return res

Реализация System.Timeout.timeout в библиотеках немного сложнее и обрабатывает больше исключительных случаев.

import Control.Concurrent  (forkIO, threadDelay, myThreadId, killThread)
import Control.Exception   (Exception, handleJust, throwTo, bracket)
import Data.Typeable
import Data.Unique         (Unique, newUnique)

data Timeout = Timeout Unique deriving Eq
timeoutTc :: TyCon
timeoutTc = mkTyCon "Timeout"
instance Typeable Timeout where { typeOf _ = mkTyConApp timeoutTc [] }
instance Show Timeout where
    show _ = "<<timeout>>"
instance Exception Timeout

timeout n f
    | n <  0    = fmap Just f
    | n == 0    = return Nothing
    | otherwise = do
        pid <- myThreadId
        ex  <- fmap Timeout newUnique
        handleJust (\e -> if e == ex then Just () else Nothing)
                   (\_ -> return Nothing)
                   (bracket (forkIO (threadDelay n >> throwTo pid ex))
                            (killThread)
                            (\_ -> fmap Just f))
9
ответ дан 10 December 2019 в 02:52
поделиться

Вот первый ответ, который я мог придумать. Мне это понадобилось для сканера портов. o_O Я забыл пароль администратора своего роутера и хотел проверить, какие порты я открыл на нашем домашнем сервере до этого, я мог теперь перепрофилировать и использовать повторно ^ _ ^ "... Эта реализация пока должна выполнять свою работу.

module Control.Concurrent.Timed (timed) where

import Prelude hiding (take)
import System.IO
import Control.Monad
import System.Process
import System.Timeout
import Control.Concurrent
import System.Environment

timed :: Int → IO a → b → IO (Either b a)
timed max act def = do

  w ← new
  r ← new

  t ← forkIO $ do
    a ← act
    r ≔ Right a
    e ← em w
    case e of
      False → kill =<< take w
      True  → return ()

  s ← forkIO $ do
    (w ≔) =<< mine
    wait max
    e ← em r
    case e of
      True  → do
        kill t
        r ≔ Left def
      False → return ()

  take r

timed_ :: Int → IO a → a → IO a
timed_ max act def = do
  r ← timed max act def
  return $ case r of
    Right a → a
    Left  a → a

(≔) = putMVar
new = newEmptyMVar
wait = threadDelay
em = isEmptyMVar
kill = killThread
mine = myThreadId
take = takeMVar

или просто используйте System.Timeout.timeout -__- "

0
ответ дан 10 December 2019 в 02:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: