Changeset 26398 in vbox
- Timestamp:
- Feb 9, 2010 7:12:50 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/webservice/vboxweb.cpp
r26397 r26398 256 256 } 257 257 258 int fntSoapQueue(RTTHREAD pThread, void *pvThread); 258 /**************************************************************************** 259 * 260 * SoapQ, SoapThread (multithreading) 261 * 262 ****************************************************************************/ 259 263 260 264 class SoapQ; 261 265 262 struct SoapThread 263 { 264 size_t u; 265 SoapQ *pQ; 266 struct soap *soap; 267 RTTHREAD pThread; 266 class SoapThread 267 { 268 public: 269 /** 270 * Constructor. Creates the new thread and makes it call process() for processing the queue. 271 * @param u Thread number. (So we can count from 1 and be readable.) 272 * @param q SoapQ instance which has the queue to process. 273 * @param soap struct soap instance from main() which we copy here. 274 */ 275 SoapThread(size_t u, 276 SoapQ &q, 277 const struct soap *soap) 278 : m_u(u), 279 m_pQ(&q) 280 { 281 // make a copy of the soap struct for the new thread 282 m_soap = soap_copy(soap); 283 284 if (!RT_SUCCESS(RTThreadCreate(&m_pThread, 285 fntWrapper, 286 this, // pvUser 287 0, // cbStack, 288 RTTHREADTYPE_MAIN_HEAVY_WORKER, 289 0, 290 "SoapQWorker"))) 291 { 292 RTStrmPrintf(g_pStdErr, "[!] Cannot start worker thread %d\n", u); 293 exit(1); 294 } 295 } 296 297 void process(); 298 299 static int fntWrapper(RTTHREAD pThread, void *pvThread) 300 { 301 SoapThread *pst = (SoapThread*)pvThread; 302 pst->process(); // this never returns really 303 return 0; 304 } 305 306 private: 307 size_t m_u; // thread number 308 SoapQ *m_pQ; 309 struct soap *m_soap; 310 RTTHREAD m_pThread; 268 311 }; 269 312 313 /** 314 * SOAP queue encapsulation. add() adds an item to the queue, 315 * get() fetches one. 316 */ 270 317 class SoapQ 271 318 { … … 280 327 for (size_t u = 0; u < cThreads; ++u) 281 328 { 282 SoapThread *pst = new SoapThread(); 283 pst->u = u + 1; 284 pst->pQ = this; 285 pst->soap = soap_copy(pSoap); 286 if (!RT_SUCCESS(RTThreadCreate(&pst->pThread, 287 fntSoapQueue, 288 pst, // pvUser 289 0, // cbStack, 290 RTTHREADTYPE_MAIN_HEAVY_WORKER, 291 0, 292 "SoapQWorker"))) 293 { 294 RTStrmPrintf(g_pStdErr, "[!] Cannot start worker thread %d\n", pst->u); 295 exit(1); 296 } 297 329 SoapThread *pst = new SoapThread(u + 1, 330 *this, 331 pSoap); 298 332 m_llAllThreads.push_back(pst); 299 333 ++m_cIdleThreads; … … 308 342 /** 309 343 * Adds the given socket to the SOAP queue and posts the 310 * member event sem to wake up the workers. 344 * member event sem to wake up the workers. Called on the main thread 345 * whenever a socket has work to do. 311 346 * @param s Socket from soap_accept() which has work to do. 312 347 */ … … 331 366 * the SOAP socket which has work to do. This reduces m_cIdleThreads 332 367 * by one, and the caller MUST call done() when it's done processing. 368 * Called from the worker threads. 333 369 * @return 334 370 */ 335 int get( )371 int get(size_t &cIdleThreads) 336 372 { 337 373 while (1) … … 345 381 int socket = m_llSocketsQ.front(); 346 382 m_llSocketsQ.pop_front(); 347 --m_cIdleThreads;383 cIdleThreads = --m_cIdleThreads; 348 384 349 385 // reset the multi event only if the queue is now empty; otherwise … … 363 399 364 400 /** 365 * To be called by a thread after fetching an item from the401 * To be called by a worker thread after fetching an item from the 366 402 * queue via get() and having finished its lengthy processing. 367 403 */ … … 373 409 374 410 util::WriteLockHandle m_mutex; 375 RTSEMEVENTMULTI m_event; 376 377 std::list<SoapThread*> m_llAllThreads; 378 size_t m_cIdleThreads; 379 380 std::list<int> m_llSocketsQ; // this contains the actual jobs to do, 381 // represented by the socket from soap_accept() 411 RTSEMEVENTMULTI m_event; // posted by add(), blocked on by get() 412 413 std::list<SoapThread*> m_llAllThreads; // all the threads created by the constructor 414 size_t m_cIdleThreads; // threads which are currently idle (statistics) 415 416 // A std::list abused as a queue; this contains the actual jobs to do, 417 // each int being a socket from soap_accept() 418 std::list<int> m_llSocketsQ; 382 419 }; 383 420 … … 387 424 * up a socket from the queue therein, which has been put there by 388 425 * beginProcessing(). 389 * 390 * @param pThread 391 * @param pvThread 392 * @return 393 */ 394 int fntSoapQueue(RTTHREAD pThread, void *pvThread) 395 { 396 SoapThread *pst = (SoapThread*)pvThread; 397 398 WebLog("Started thread %d\n", pst->u); 426 */ 427 void SoapThread::process() 428 { 429 WebLog("Started thread %d\n", m_u); 399 430 400 431 while (1) 401 432 { 402 433 // wait for a socket to arrive on the queue 403 pst->soap->socket = pst->pQ->get(); 434 size_t cIdleThreads; 435 m_soap->socket = m_pQ->get(cIdleThreads); 404 436 405 437 WebLog("T%d handles connection from IP=%lu.%lu.%lu.%lu socket=%d (%d threads idle)\n", 406 pst->u,407 ( pst->soap->ip>>24)&0xFF,408 ( pst->soap->ip>>16)&0xFF,409 ( pst->soap->ip>>8)&0xFF,410 pst->soap->ip&0xFF,411 pst->soap->socket,412 pst->pQ->m_cIdleThreads);438 m_u, 439 (m_soap->ip>>24)&0xFF, 440 (m_soap->ip>>16)&0xFF, 441 (m_soap->ip>>8)&0xFF, 442 m_soap->ip&0xFF, 443 m_soap->socket, 444 cIdleThreads); 413 445 414 446 // process the request; this goes into the COM code in methodmaps.cpp 415 soap_serve( pst->soap);416 417 soap_destroy( pst->soap); // clean up class instances418 soap_end( pst->soap); // clean up everything and close socket447 soap_serve(m_soap); 448 449 soap_destroy(m_soap); // clean up class instances 450 soap_end(m_soap); // clean up everything and close socket 419 451 420 452 // tell the queue we're idle again 421 pst->pQ->done(); 422 } 423 424 return 0; 425 } 453 m_pQ->done(); 454 } 455 } 456 457 /**************************************************************************** 458 * 459 * Main 460 * 461 ****************************************************************************/ 426 462 427 463 /**
Note:
See TracChangeset
for help on using the changeset viewer.