searchengine/util/tsrc/cpixtoolsunittest/src/pooltests.cpp
changeset 0 671dee74050a
child 8 6547bf8ca13a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/searchengine/util/tsrc/cpixtoolsunittest/src/pooltests.cpp	Mon Apr 19 14:40:16 2010 +0300
@@ -0,0 +1,443 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+#include <wchar.h>
+
+#include <pthread.h>
+#include <unistd.h>
+
+#include <string>
+#include <iostream>
+
+#include "itk.h"
+
+#include "cpixsyncpool.h"
+
+
+namespace
+{
+
+
+    class TestPoolItemCounter
+    {
+    private:
+
+        static TestPoolItemCounter  * instance_;
+
+
+        size_t ctorInvocationCount_;
+        size_t dtorInvocationCount_;
+        size_t instanceCount_;
+
+    public:
+
+        static TestPoolItemCounter * instance()
+        {
+            if (instance_ == NULL)
+                {
+                    instance_ = new TestPoolItemCounter;
+                }
+
+            return instance_;
+        }
+
+
+        void ctor()
+        {
+            ++ctorInvocationCount_;
+            ++instanceCount_;
+        }
+
+        void dtor()
+        {
+            ++dtorInvocationCount_;
+            --instanceCount_;
+        }
+
+
+        void printStatus()
+        {
+            printf("TestPoolItem ctor %ld, dtor %ld, count %ld\n",
+                   ctorInvocationCount_,
+                   dtorInvocationCount_,
+                   instanceCount_);
+        }
+
+        
+        void reset()
+        {
+            ctorInvocationCount_ = 0;
+            dtorInvocationCount_ = 0;
+            instanceCount_ = 0;
+        }
+
+
+    private:
+        TestPoolItemCounter()
+            : ctorInvocationCount_(0),
+              dtorInvocationCount_(0),
+              instanceCount_(0)
+        {
+            ;
+        }
+    };
+
+
+
+    TestPoolItemCounter * TestPoolItemCounter::instance_ = NULL;
+
+
+    class TestPoolItem
+    {
+    public:
+        TestPoolItem()
+        {
+            TestPoolItemCounter::instance()->ctor();
+        }
+
+
+        ~TestPoolItem()
+        {
+            TestPoolItemCounter::instance()->dtor();
+        }
+    };
+
+
+    enum { ITEMCOUNT = 4 };
+
+
+    void PrintStatus(TestPoolItem   ** items,
+                     const char      * name = NULL)
+    {
+        TestPoolItemCounter::instance()->printStatus();
+
+        int
+            count = 0;
+
+        for (int i = 0; i < ITEMCOUNT; ++i)
+            {
+                if (*(items + i) != NULL)
+                    {
+                        ++count;
+                    }
+            }
+        
+
+        if (name == NULL)
+            {
+                printf("Items in use: %d\n",
+                       count);
+            }
+        else
+            {
+                printf("Thread %s: items in use: %d\n",
+                       name,
+                       count);
+            }
+    }
+
+
+    struct ThreadParam
+    {
+        const char                        * name_;
+        Itk::TestMgr                      * testMgr_;
+        Cpt::SyncPool<TestPoolItem>       * pool_;
+        TestPoolItem                     ** items_;
+    };
+
+
+
+    void ItemsArrayDeleter(void * p)
+    {
+        /*TestPoolItem
+            ** items = reinterpret_cast<TestPoolItem**>(p);
+          */
+        delete[] p;
+    }
+    
+
+    pthread_key_t     NameKey;
+    pthread_key_t     ItemsKey;
+
+
+    void PrintStatus()
+    {
+        void
+            * p = pthread_getspecific(ItemsKey);
+
+        if (p == NULL)
+            {
+                printf("Cannot get thread specific key: ItemsKey\n");
+                ITK_PANIC("ItemsKey");
+            }
+
+        TestPoolItem
+            ** items = reinterpret_cast<TestPoolItem **>(p);
+
+        p = pthread_getspecific(NameKey);
+
+        const char
+            * name = reinterpret_cast<const char*>(p);
+        
+        PrintStatus(items,
+                    name);
+
+        sleep(1);
+    }
+
+
+
+} // namespace
+
+
+
+
+
+void testSingleThreadedUse(Itk::TestMgr * )
+{
+    using namespace Cpt;
+
+    TestPoolItemCounter::instance()->reset();
+
+    static int 
+        minPoolItemCount = 2;
+
+    SyncPool<TestPoolItem>
+        pool(minPoolItemCount);
+
+    TestPoolItem
+        * items[ITEMCOUNT];
+    for (int i = 0; i < ITEMCOUNT; ++i)
+        {
+            items[i] = NULL;
+        }
+
+    items[0] = pool.acquire();
+    PrintStatus(items);
+
+    items[1] = pool.acquire();
+    PrintStatus(items);
+
+    pool.release(items[0]);
+    items[0] = NULL;
+    PrintStatus(items);
+
+    items[2] = pool.acquire();
+    PrintStatus(items);
+
+    items[3] = pool.acquire();
+    PrintStatus(items);
+    
+    items[0] = pool.acquire();
+    PrintStatus(items);
+
+    pool.release(items[1]);
+    items[1] = NULL;
+    PrintStatus(items);
+    
+    pool.release(items[0]);
+    items[0] = NULL;
+    PrintStatus(items);
+
+    pool.release(items[3]);
+    items[3] = NULL;
+    PrintStatus(items);
+
+    pool.release(items[2]);
+    items[2] = NULL;
+    PrintStatus(items);
+}
+
+
+
+void * ThreadFunc(void * param)
+{
+    ThreadParam
+        * p = reinterpret_cast<ThreadParam*>(param);
+
+    int
+        result = pthread_setspecific(NameKey,
+                                     p->name_);
+    if (result != 0)
+        {
+            printf("Could not set thread specific NameKey\n");
+            ITK_PANIC("NameKey setting");
+        }
+
+    result = pthread_setspecific(ItemsKey,
+                                 p->items_);
+
+    if (result != 0)
+        {
+            printf("Could not set thread specific ItemsKey\n");
+            ITK_PANIC("ItemsKey setting");
+        }
+
+    Cpt::SyncPool<TestPoolItem>
+        & pool = *p->pool_;;
+
+    TestPoolItem
+        ** items = p->items_;
+    for (int i = 0; i < ITEMCOUNT; ++i)
+        {
+            items[i] = NULL;
+        }
+
+    items[0] = pool.acquire();
+    PrintStatus();
+
+    items[1] = pool.acquire();
+    PrintStatus();
+
+    pool.release(items[0]);
+    items[0] = NULL;
+    PrintStatus();
+
+    items[2] = pool.acquire();
+    PrintStatus();
+
+    items[3] = pool.acquire();
+    PrintStatus();
+    
+    items[0] = pool.acquire();
+    PrintStatus();
+
+    pool.release(items[1]);
+    items[1] = NULL;
+    PrintStatus();
+    
+    pool.release(items[0]);
+    items[0] = NULL;
+    PrintStatus();
+
+    pool.release(items[3]);
+    items[3] = NULL;
+    PrintStatus();
+
+    pool.release(items[2]);
+    items[2] = NULL;
+    PrintStatus();
+
+    printf("Thread %s is DONE.\n",
+           p->name_);
+
+    return NULL;
+}
+
+
+
+
+void testMultiThreadedUse(Itk::TestMgr * testMgr)
+{
+    TestPoolItemCounter::instance()->reset();
+
+    int
+        result = pthread_key_create(&NameKey,
+                                    NULL);
+    ITK_ASSERT(testMgr,
+               result == 0,
+               "Could not create thread specific key: NameKey");
+
+    result = pthread_key_create(&ItemsKey,
+                                ItemsArrayDeleter);
+    ITK_ASSERT(testMgr,
+               result == 0,
+               "Could not create thread specific key: ItemsKey");
+    
+    static int 
+        minPoolItemCount = 2;
+
+    Cpt::SyncPool<TestPoolItem>
+        pool(minPoolItemCount);
+
+    TestPoolItem
+        ** tpi1 = new TestPoolItem*[ITEMCOUNT],
+        ** tpi2 = new TestPoolItem*[ITEMCOUNT];
+
+    ThreadParam threadParams[2] = {
+        {
+            "main",
+            testMgr,
+            &pool,
+            tpi1
+        },
+
+        {
+            "extra",
+            testMgr,
+            &pool,
+            tpi2
+        }
+    };
+
+    pthread_t
+        extra;
+
+    result = pthread_create(&extra,
+                            NULL,
+                            &ThreadFunc,
+                            threadParams + 1);
+
+    ITK_ASSERT(testMgr,
+               result == 0,
+               "Could not create extra thread");
+    
+    ThreadFunc(threadParams + 0);
+
+    void
+        * retVal = NULL;
+
+    printf("main: Joining extra\n");
+
+    result = pthread_join(extra,
+                          &retVal);
+
+    ITK_ASSERT(testMgr,
+               result == 0,
+               "Could not join extra thread");
+
+    printf("main: joined extra\n");
+}
+
+
+
+
+Itk::TesterBase * CreatePoolTests()
+{
+    using namespace Itk;
+
+    SuiteTester
+        * poolTests = new SuiteTester("pool");
+
+#define TEST "singleThreadedUse"
+    poolTests->add(TEST,
+                   testSingleThreadedUse,
+                   TEST);
+#undef TEST
+
+
+#define TEST "multiThreadedUse"
+    poolTests->add(TEST,
+                   testMultiThreadedUse,
+                   TEST);
+#undef TEST
+
+
+    // ... add more tests to suite
+    
+    return poolTests;
+}