VirtualBox

Changeset 26393 in vbox


Ignore:
Timestamp:
Feb 9, 2010 5:50:17 PM (15 years ago)
Author:
vboxsync
Message:

Web service: first attempt at multithreading.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/webservice/vboxweb.cpp

    r26375 r26393  
    4040#include <iprt/string.h>
    4141#include <iprt/ldr.h>
     42#include <iprt/semaphore.h>
    4243
    4344// workaround for compile problems on gcc 4.1
     
    5152// standard headers
    5253#include <map>
     54#include <list>
    5355
    5456#ifdef __GNUC__
     
    248250}
    249251
     252int fntSoapQueue(RTTHREAD pThread, void *pvThread);
     253
     254class SoapQ;
     255
     256struct SoapThread
     257{
     258    size_t      u;
     259    SoapQ       *pQ;
     260    struct soap *soap;
     261    RTTHREAD    pThread;
     262};
     263
     264class SoapQ
     265{
     266public:
     267    SoapQ(size_t cThreads, const struct soap *pSoap)
     268        : m_mutex(util::LOCKCLASS_OBJECTSTATE),
     269          m_cIdleThreads(0)
     270    {
     271        RTSemEventCreate(&m_event);
     272
     273        // create cThreads threads
     274        for (size_t u = 0; u < cThreads; ++u)
     275        {
     276            SoapThread *pst = new SoapThread();
     277            pst->u = u + 1;
     278            pst->pQ = this;
     279            pst->soap = soap_copy(pSoap);
     280            RTThreadCreate(&pst->pThread,
     281                           fntSoapQueue,
     282                           pst,             // pvUser
     283                           0,               // cbStack,
     284                           RTTHREADTYPE_MAIN_HEAVY_WORKER,
     285                           0,
     286                           "SoapQWorker");
     287            m_llAllThreads.push_back(pst);
     288            ++m_cIdleThreads;
     289        }
     290    }
     291
     292    ~SoapQ()
     293    {
     294        RTSemEventDestroy(m_event);
     295    }
     296
     297    util::WriteLockHandle   m_mutex;
     298    RTSEMEVENT              m_event;
     299
     300    std::list<SoapThread*>  m_llAllThreads;
     301    size_t                  m_cIdleThreads;
     302
     303    std::list<int>          m_llSocketsQ;       // this contains the actual jobs to do,
     304                                                // represented by the socket from soap_accept()
     305};
     306
     307int fntSoapQueue(RTTHREAD pThread, void *pvThread)
     308{
     309    SoapThread *pst = (SoapThread*)pvThread;
     310
     311    WebLog("Started thread %d\n", pst->u);
     312
     313    while (1)
     314    {
     315        // wait for something to happen
     316        RTSemEventWait(pst->pQ->m_event, RT_INDEFINITE_WAIT);
     317
     318        util::AutoWriteLock qlock(pst->pQ->m_mutex COMMA_LOCKVAL_SRC_POS);
     319        if (pst->pQ->m_llSocketsQ.size())
     320        {
     321            pst->soap->socket = pst->pQ->m_llSocketsQ.front();
     322            pst->pQ->m_llSocketsQ.pop_front();
     323            --pst->pQ->m_cIdleThreads;
     324            qlock.release();
     325
     326            WebLog("Thread %d is handling connection from IP=%lu.%lu.%lu.%lu socket=%d (%d threads idle)",
     327                   pst->u,
     328                   (pst->soap->ip>>24)&0xFF,
     329                   (pst->soap->ip>>16)&0xFF,
     330                   (pst->soap->ip>>8)&0xFF,
     331                   pst->soap->ip&0xFF,
     332                   pst->soap->socket,
     333                   pst->pQ->m_cIdleThreads);
     334
     335            // process the request; this goes into the COM code in methodmaps.cpp
     336            soap_serve(pst->soap);
     337
     338            soap_destroy(pst->soap); // clean up class instances
     339            soap_end(pst->soap); // clean up everything and close socket
     340
     341            qlock.acquire();
     342            ++pst->pQ->m_cIdleThreads;
     343        }
     344    }
     345
     346    return 0;
     347}
     348
    250349/**
    251350 * Called from main(). This implements the loop that takes SOAP calls
     
    276375               m);
    277376
     377        // initialize thread queue, mutex and eventsem, create 10 threads
     378        SoapQ soapq(10, &soap);
     379
    278380        for (uint64_t i = 1;
    279381             ;
     
    288390            }
    289391
    290             WebLog("%llu: accepted connection from IP=%lu.%lu.%lu.%lu socket=%d... ",
    291                    i,
    292                    (soap.ip>>24)&0xFF,
    293                    (soap.ip>>16)&0xFF,
    294                    (soap.ip>>8)&0xFF,
    295                    soap.ip&0xFF,
    296                    s);
    297 
    298             // now process the RPC request (this goes into the
    299             // generated code in methodmaps.cpp with all the COM calls)
    300             if (soap_serve(&soap) != SOAP_OK)
    301             {
    302                 WebLogSoapError(&soap);
    303             }
    304 
    305             WebLog("Request served\n");
    306 
    307             soap_destroy(&soap); // clean up class instances
    308             soap_end(&soap); // clean up everything and close socket
     392            // enqueue the socket of this connection and post eventsem so
     393            // that one of our threads can pick it up
     394            util::AutoWriteLock qlock(soapq.m_mutex COMMA_LOCKVAL_SRC_POS);
     395            soapq.m_llSocketsQ.push_back(s);
     396            WebLog("Request %llu on socket %d queued for processing\n", i, s);
     397            RTSemEventSignal(soapq.m_event);
     398            qlock.release();
    309399
    310400            // we have to process main event queue
     
    332422    RTR3Init();
    333423
    334     RTStrmPrintf(g_pStdErr, VBOX_PRODUCT " Webservice Version " VBOX_VERSION_STRING "\n"
     424    RTStrmPrintf(g_pStdErr, VBOX_PRODUCT " web service version " VBOX_VERSION_STRING "\n"
    335425                            "(C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
    336426                            "All rights reserved.\n");
     
    10451135 *  does perform that check.
    10461136 *
    1047  *  Preconditions: Caller must have locked g_mutexSessions.
     1137 * Preconditions: Caller must have locked g_pSessionsLockHandle in write mode.
    10481138 *
    10491139 * @param pObj
     
    10591149    _ulp = (uintptr_t)(IUnknown*)pcUnknown;
    10601150
     1151    Assert(g_pSessionsLockHandle->isWriteLockOnCurrentThread());
    10611152    _id = ++g_iMaxManagedObjectID;
    10621153    // and count globally
     
    10791170 * managed objects.
    10801171 *
    1081  * Preconditions: Caller must have locked g_mutexSessions.
     1172 * Preconditions: Caller must have locked g_pSessionsLockHandle in write mode.
    10821173 */
    10831174ManagedObjectRef::~ManagedObjectRef()
    10841175{
     1176    Assert(g_pSessionsLockHandle->isWriteLockOnCurrentThread());
    10851177    ULONG64 cTotal = --g_cManagedObjects;
    10861178
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette