single thread version