Hi flux!

Thank you for your interest to this problem.

Well...

All you write is almost perfect, but in practice if we execute 10-20 threads 
then scheduler wakes up these T1, T2, ... T19 in cycle and even if we don't 
sleep or sleep 1ms it would work. You are right that when scheduler tries to 
execute Tx it can be blocked, but here is the mostly tricky moment: all threads 
are waiting for single resource and there will be a moment when lucky Tx does 
its work.

And of course the code is bad but it should be bad to check if each thread has 
a chance to be executed.

Despite I know that it should work I wrote same test in C++ (this code uses my 
thread pool written some time ago to simulate the logic like nim's spawn). It 
spawns **40 threads** and prints 80 characters in order (with and without 
sleep).

P.S. After comparing this C++ code to nim I started to love nim even more. :)

P.P.S. After all the testing I still suspect that something is wrong with nim's 
threading.
    
    
    size_t g_nLen;
    size_t g_nCallsTotal = 0;
    size_t g_nCallsCur = 0;
    size_t g_nRes = 0;
    std::mutex g_mutex;
    std::stringstream g_msg;
    
    void worker(char ch, size_t nValue) {
        while(true) {
            bool bWorkDone = true;
            {
                std::unique_lock<std::mutex> lck(g_mutex);
                if(g_nCallsCur == g_nCallsTotal)
                    return;
                if(g_nRes == nValue) {
                    g_nRes++;
                    g_nRes %= g_nLen;
                    g_nCallsCur++;
                    g_msg << ch;
                } else{
                    bWorkDone = false;
                }
            }
            if(!bWorkDone) {
                    std::chrono::milliseconds sleepDuration(1);
                    std::this_thread::sleep_for(sleepDuration);
            }
        }
    }
    
    int main(int argc, char* argv[]) {
            const std::string sText = 
"0123456789012345678901234567890123456789";
            g_nLen = sText.size();
            
            g_nCallsTotal = g_nLen * 2;
            
            CThreadPool *pPool = new CThreadPool(g_nLen);
            for(auto i = 0; i < g_nLen; i++)
                    pPool->executeInThread(&worker, sText[i], i);
            pPool->waitUntilFree();
            delete pPool;
            
            std::cout << g_msg.str() << std::endl << "Finished!!" << std::endl;
            return 0;
    }
    

Reply via email to