Talk About Network

Google


Register and Login
Nick
Password
Register create new account Sign up is FREE and you can post replies, new topics, bookmark posts and more!
Recover lost password


Programming > Programming Threads > ****table event...
Latest [ Topics | Posts ] Archive Post A New Topic Post a Reply
<< Topic < Post Post 1 of 21 Topic 4029 of 4146
Post > Topic >>

****table eventcount (try 2)

by "Dmitriy V'jukov" <dvyukov@[EMAIL PROTECTED] > Sep 17, 2008 at 01:30 PM

I take into account feedback from Anthony Williams and Chris Thomasson
after my first try:
http://groups.google.com/group/comp.programming.threads/browse_frm/thread/9461b41709e4063a

Here is claimed properties:
1. No memory allocation/deallocation
2. No kernel object creation/destruction
3. Broadcasting with single syscall
4. No mutex acquisition after wait on semaphore
5. ****table because based on semaphore
6. No spurious wakeups by design
7. You can easily transform this algorithm into condition variable

Brief comments on algorithm:
1. Every thread has associated node which it uses in eventcount
operations
2. Threads exchange of their nodes
3. Mutex acquisition, which must be after wait on semaphore, executed
before next wait (it's just deferred).

Here is the code:

struct thread_node
{
    thread_node*            next;
    size_t                  count;
    size_t                  unconsumed;
    HANDLE                  sema;
    CRITICAL_SECTION        mtx;
};

__declspec(thread) thread_node* t_thread_node;

void on_thread_exit()
{
    thread_node* head = t_thread_node;
    thread_node* my = 0;
    if (head)
    {
        EnterCriticalSection(&head->mtx);
        if (head->next)
        {
            my = head->next;
            head->next = my->next;
        }
        else
        {
            my = head;
        }
        LeaveCriticalSection(&head->mtx);
        DeleteCriticalSection(&my->mtx);
        CloseHandle(my->sema);
        delete my;
    }
}

struct eventcount
{
    eventcount()
    {
        root = 0;
        InitializeCriticalSection(&mtx);
    }

    ~eventcount()
    {
        DeleteCriticalSection(&mtx);
    }

    void prepare_wait()
    {
        thread_node* my = 0;
        thread_node* head = t_thread_node;
        if (head)
        {
            EnterCriticalSection(&head->mtx);
            if (head->next)
            {
                my = head->next;
                head->next = my->next;
                my->next = 0;
            }
            else
            {
                my = head;
            }
            LeaveCriticalSection(&head->mtx);
        }
        else
        {
            my = new thread_node;
            my->next = 0;
            my->count = 0;
            my->unconsumed = 0;
            my->sema = CreateSemaphoreW(0, 0, LONG_MAX, 0);
            InitializeCriticalSection(&my->mtx);
        }

        while (my->unconsumed)
        {
            WaitForSingleObject(my->sema, 0);
            my->unconsumed -= 1;
        }

        EnterCriticalSection(&mtx);
        if (root)
        {
            my->next = root->next;
            root->next = my;
            my = root;
        }
        else
        {
            root = my;
        }
        root->count += 1;
        LeaveCriticalSection(&mtx);
        t_thread_node = my;
    }

    void wait()
    {
        thread_node* head = t_thread_node;
        if (head == root)
        {
            WaitForSingleObject(head->sema, INFINITE);
        }
        else
        {
            EnterCriticalSection(&head->mtx);
            head->unconsumed += 1;
            LeaveCriticalSection(&head->mtx);
        }
    }

    void retire_wait()
    {
        thread_node* head = t_thread_node;
        if (head == root)
        {
            EnterCriticalSection(&mtx);
            if (head == root)
            {
                thread_node* my = 0;
                head->count -= 1;
                if (head->next)
                {
                    my = head->next;
                    head->next = my->next;
                    my->next = 0;
                }
                else
                {
                    my = head;
                }
                LeaveCriticalSection(&mtx);
                t_thread_node = my;
                return;
            }
            LeaveCriticalSection(&mtx);
        }
        EnterCriticalSection(&head->mtx);
        head->unconsumed += 1;
        LeaveCriticalSection(&head->mtx);
    }

    void signal_all()
    {
        _mm_mfence();
        thread_node* head = root;
        if (0 == head)
            return;
        EnterCriticalSection(&mtx);
        if (head != root)
        {
            LeaveCriticalSection(&mtx);
            return;
        }
        root = 0;
        LeaveCriticalSection(&mtx);
        size_t count = head->count;
        head->count = 0;
        ReleaseSemaphore(head->sema, count, 0);
    }

    void signal_one()
    {
        _mm_mfence();
        thread_node* head = root;
        if (0 == head)
            return;
        EnterCriticalSection(&mtx);
        if (head != root)
        {
            LeaveCriticalSection(&mtx);
            return;
        }
        head->count -= 1;
        if (0 == head->count)
            root = 0;
        LeaveCriticalSection(&mtx);
        ReleaseSemaphore(head->sema, 1, 0);
    }

    thread_node* volatile   root;
    CRITICAL_SECTION        mtx;
};


Dmitriy V'jukov
--
Relacy Race Detector: Make your synchronization correct!
http://groups.google.ru/group/relacy/web
 




 21 Posts in Topic:
Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-17 13:30:03 
Re: Portable eventcount (try 2)
"Chris M. Thomasson&  2008-09-17 23:04:23 
Re: Portable eventcount (try 2)
"Chris M. Thomasson&  2008-09-18 00:46:10 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-18 00:51:36 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-18 01:21:06 
Re: Portable eventcount (try 2)
"Chris M. Thomasson&  2008-09-18 05:43:29 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-18 05:19:22 
Re: Portable eventcount (try 2)
"Chris M. Thomasson&  2008-09-18 06:50:02 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-18 06:19:28 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-18 06:53:58 
Re: Portable eventcount (try 2)
"Chris M. Thomasson&  2008-09-18 07:12:04 
Re: Portable eventcount (try 2)
"Chris M. Thomasson&  2008-09-18 07:19:36 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-18 07:31:39 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-19 12:27:59 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-21 14:08:03 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-09-23 04:40:07 
Re: Portable eventcount (try 2)
"Chris M. Thomasson&  2008-10-26 06:00:50 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-10-30 11:46:33 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-10-31 07:29:11 
Re: Portable eventcount (try 2)
"Chris M. Thomasson&  2008-10-31 12:43:21 
Re: Portable eventcount (try 2)
"Dmitriy V'jukov&quo  2008-10-31 14:31:18 

Post A Reply:
  Go here to Signup

AddThis Feed Button


About - Advertising - Contact - Frequently Asked Questions - Privacy Policy - Terms of Use - Signup

Contact
tan12V112 Sat Nov 22 7:46:00 CST 2008.