www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How do I exhaust a thread's message queue?

reply Andrej Mitrovic <none none.none> writes:
Note this is just pseudocode:

// worker thread
void doWork()
{
    // while there's still stuff in the message queue
    while (messagesInQueue)
    {
         result = receiveOnly!int(); 
         switch(result)
         {
             // main thread could be enabling or disabling features this way,
             // and sending some commands..
         }
    }

    // now that we have all of our commands, do some hard work..
}

// background Thread
void main()
{
    while (userHasMoreInputs())
    {
         // send switches to the worker thread, via e.g.:
         workerThread.send(userValue);
    }
}

So I'm really interested in how to implement that line:
while (messagesInQueue)

Perhaps I have to use receiveTimeout?
Apr 01 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I'm good at answering my own questions. :p

import std.stdio;
import std.concurrency;
import core.thread;

void main()
{
    auto workThread = spawn(&foo);
    int delay = 500;
    int command = 0;

    while(true)
    {
        Thread.sleep( dur!("msecs")( delay += 100 ) );
        workThread.send(++command);
    }
}


void handle(int x)
{
    writeln(x);
}

void foo()
{
    int result;

    bool gotMessage;
    do
    {
        gotMessage = receiveTimeout(1000,
                                    (int x) { result = x; }
                                    );
        switch (result)
        {
            case 1:
                writeln("one");
                break;
            case 2:
                writeln("two");
                break;
            default:
                writeln("something else");
                break;
        }

    } while (gotMessage);

    writeln("Done!");
}

I love how elegant D is.
Apr 01 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Btw disregard that "handle" function, I've used it first but then
decided to change `result` directly in the receiveTimeout function.
It's better that way.
Apr 01 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Actually I have a bug in `foo()`, the switch statement is executed
even if I didn't get a message back. Here's a fix:

void foo()
{
    int result;

    bool gotMessage;

    while (true)
    {
        gotMessage = receiveTimeout(1000,
                                    (int x) { result = x; }
                                    );

        if (!gotMessage)
            break;

        switch (result)
        {
            case 1:
                writeln("one");
                break;
            case 2:
                writeln("two");
                break;
            default:
                writeln("something else");
                break;
        }
    }

    writeln("Done!");
}
Apr 01 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
It turns out the receiveTimeout technique didn't work well for me. In
my case, there's a timer which spawns a high-priority thread calling
`foo` several hundred times per second. What I really needed is to
exhaust the message queue, and then do some other work after that. So
I've added a `shared int messagesInQueue`, which gets incremented in
the main thread, and decremented in the work thread when it reads off
those messages.

But isn't something like this already implemented somewhere in
core.thread or std.concurrency? All I want to do is check if there are
/any/ messages in queue for the current thread.
Apr 02 2011