single threaded version