(file) Return to Thread.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 karl  1.89 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.71 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.56 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.71 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.75 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.89 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15 chip  1.11 // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20 karl  1.89 // 
 21 chip  1.11 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 mike  1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24 chip  1.11 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27 mike  1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31            //
 32            //%/////////////////////////////////////////////////////////////////////////////
 33            
 34            #include "Thread.h"
 35 mike  1.96 #include <errno.h>
 36 kumpf 1.68 #include <exception>
 37 kumpf 1.14 #include <Pegasus/Common/Tracer.h>
 38 mike  1.91 #include "Time.h"
 39 mike  1.2  
 40 mike  1.91 PEGASUS_USING_STD;
 41 mike  1.2  
 42            PEGASUS_NAMESPACE_BEGIN
 43            
 44 mike  1.91 //==============================================================================
 45            //
 46            // POSIX Threads Implementation:
 47            //
 48            //==============================================================================
 49 mday  1.42 
 50 mike  1.91 #if defined(PEGASUS_HAVE_PTHREADS)
 51            
 52            struct StartWrapperArg
 53 chip  1.11 {
 54 mike  1.91     void *(PEGASUS_THREAD_CDECL * start) (void *);
 55                void *arg;
 56            };
 57 mike  1.2  
 58 mike  1.91 extern "C" void *_start_wrapper(void *arg_)
 59 chuck 1.43 {
 60 mike  1.100.2.1     // Clean up dynamic memory now to prevent a leak if the thread is canceled.
 61                     StartWrapperArg arg;
 62                     arg.start = ((StartWrapperArg *) arg_)->start;
 63                     arg.arg = ((StartWrapperArg *) arg_)->arg;
 64                     delete (StartWrapperArg *) arg_;
 65 chuck 1.43      
 66 mike  1.100.2.1     // establish cancelability of the thread
 67                     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 68                     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
 69                 
 70                     void *return_value = (*arg.start) (arg.arg);
 71 chuck 1.37      
 72 mike  1.91          return return_value;
 73                 }
 74 mike  1.2       
 75 mike  1.91      void Thread::cancel()
 76 mike  1.2       {
 77 mike  1.91          _cancelled = true;
 78 mike  1.94          pthread_cancel(_handle.thid.thread);
 79 mike  1.2       }
 80 kumpf 1.81      
 81 mike  1.91      void Thread::test_cancel()
 82 mike  1.2       {
 83 mike  1.91      #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
 84                     pthread_testintr();
 85                 #else
 86                     pthread_testcancel();
 87                 #endif
 88 mike  1.2       }
 89 kumpf 1.81      
 90 kumpf 1.98      Boolean Thread::is_cancelled()
 91 chip  1.11      {
 92 mike  1.91          return _cancelled;
 93 mike  1.2       }
 94                 
 95 mike  1.91      void Thread::thread_switch()
 96                 {
 97                 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
 98                     pthread_yield(NULL);
 99                 #else
100                     sched_yield();
101 mike  1.2       #endif
102 mike  1.91      }
103 mike  1.2       
104 mike  1.91      /*
105                 ATTN: why are these missing on other platforms?
106                 */
107                 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
108                 void Thread::suspend()
109 chuck 1.39      {
110 mike  1.94          pthread_kill(_handle.thid.thread, SIGSTOP);
111 chuck 1.39      }
112                 
113 mike  1.91      void Thread::resume()
114 chuck 1.37      {
115 mike  1.94          pthread_kill(_handle.thid.thread, SIGCONT);
116 chuck 1.39      }
117 mike  1.91      #endif
118 chuck 1.39      
119 mike  1.91      void Thread::sleep(Uint32 msec)
120 chuck 1.39      {
121 mike  1.91          Threads::sleep(msec);
122 chuck 1.37      }
123                 
124 kumpf 1.98      void Thread::join()
125 chuck 1.37      {
126 mike  1.94          if (!_is_detached && !Threads::null(_handle.thid))
127                         pthread_join(_handle.thid.thread, &_exit_code);
128 kumpf 1.81      
129 mike  1.91          Threads::clear(_handle.thid);
130 chuck 1.37      }
131                 
132 kumpf 1.98      void Thread::thread_init()
133 chuck 1.37      {
134 mike  1.91      #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
135                     pthread_setintr(PTHREAD_INTR_ENABLE);
136                     pthread_setintrtype(PTHREAD_INTR_ASYNCHRONOUS);
137                 #else
138                     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
139                     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
140                 #endif
141                     _cancel_enabled = true;
142 chuck 1.37      }
143                 
144 kumpf 1.98      void Thread::detach()
145 chuck 1.37      {
146 mike  1.91          _is_detached = true;
147                 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
148 mike  1.94          pthread_t  thread_id=_handle.thid.thread;
149 mike  1.91          pthread_detach(&thread_id);
150                 #else
151 mike  1.94          pthread_detach(_handle.thid.thread);
152 mike  1.91      #endif
153 chuck 1.37      }
154                 
155 mike  1.91      ThreadStatus Thread::run()
156                 {
157                     StartWrapperArg *arg = new StartWrapperArg;
158                     arg->start = _start;
159                     arg->arg = this;
160 mday  1.52      
161 mike  1.100.2.2     Threads::Type type = 
162                         _is_detached ? Threads::THREADS_DETACHED : Threads::THREADS_JOINABLE;
163 mike  1.91          int rc = Threads::create(_handle.thid, type, _start_wrapper, arg);
164 kumpf 1.81      
165 kumpf 1.98          // On Linux distributions released prior 2005, the implementation of
166 mike  1.91          // Native POSIX Thread Library returns ENOMEM instead of EAGAIN when
167 kumpf 1.98          // there
168 mike  1.91          // are no insufficient memory.  Hence we are checking for both.  See bug
169                     // 386.
170 mday  1.58      
171 marek 1.93          if (rc == -1)
172                         rc = errno;
173 mike  1.91          if ((rc == EAGAIN) || (rc == ENOMEM))
174 kumpf 1.81          {
175 mike  1.91              Threads::clear(_handle.thid);
176                         delete arg;
177                         return PEGASUS_THREAD_INSUFFICIENT_RESOURCES;
178 kumpf 1.81          }
179 mike  1.91          else if (rc != 0)
180 kumpf 1.81          {
181 mike  1.91              Threads::clear(_handle.thid);
182                         delete arg;
183                         return PEGASUS_THREAD_SETUP_FAILURE;
184 kumpf 1.81          }
185 mike  1.91          return PEGASUS_THREAD_OK;
186                 }
187 mday  1.58      
188 mike  1.91      static sigset_t *block_signal_mask(sigset_t * sig)
189                 {
190                     sigemptyset(sig);
191                     // should not be used for main()
192                     sigaddset(sig, SIGHUP);
193                     sigaddset(sig, SIGINT);
194                     // maybe useless, since KILL can't be blocked according to POSIX
195                     sigaddset(sig, SIGKILL);
196                 
197                     sigaddset(sig, SIGABRT);
198                     sigaddset(sig, SIGALRM);
199                     sigaddset(sig, SIGPIPE);
200                 
201                 
202                 // Note: older versions of the linux pthreads library use SIGUSR1 and SIGUSR2
203                 // internally to stop and start threads that are blocking, the newer ones
204                 // implement this through the kernel's real time signals
205                 // since SIGSTOP/CONT can handle suspend()/resume() on Linux
206                 // block them
207                 // #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU)
208                 //     sigaddset(sig, SIGUSR1);
209 mike  1.91      //     sigaddset(sig, SIGUSR2);
210                 // #endif
211 carson.hovey 1.92      #if defined (PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined (PEGASUS_OS_VMS)
212                            sigprocmask(SIG_BLOCK, sig, NULL);
213                        #else
214 mike         1.91          pthread_sigmask(SIG_BLOCK, sig, NULL);
215                        #endif
216                            return sig;
217                        }
218 mday         1.52      
219 mike         1.100.2.3 /*
220                        ATTN: remove this!
221                        */
222                        static Uint32 _num_threads = 0;
223                        static Mutex _num_threads_mutex;
224                        
225 kumpf        1.98      Thread::Thread(
226                            ThreadReturnType(PEGASUS_THREAD_CDECL* start) (void*),
227                            void* parameter,
228                            Boolean detached)
229                            : _is_detached(detached),
230                              _cancel_enabled(true),
231                              _cancelled(false),
232                              _start(start),
233                              _cleanup(),
234                              _tsd(),
235                              _thread_parm(parameter),
236                              _exit_code(0)
237 mike         1.91      {
238 mike         1.100.2.3 /*
239                        ATTN: remove this!
240                        */
241                            Uint32 num_threads;
242                            _num_threads_mutex.lock();
243                            _num_threads++;
244                            num_threads = _num_threads;
245                            _num_threads_mutex.unlock();
246                            printf("Thread::Thread(): num_threads=%u\n", num_threads);
247                        
248 mike         1.91          Threads::clear(_handle.thid);
249 kumpf        1.81      }
250 mday         1.20      
251 mike         1.91      Thread::~Thread()
252 mday         1.20      {
253 mike         1.100.2.3 /*
254                        ATTN: remove this!
255                        */
256                            Uint32 num_threads;
257                            _num_threads_mutex.lock();
258                            _num_threads--;
259                            num_threads = _num_threads;
260                            _num_threads_mutex.unlock();
261                            printf("Thread::~Thread(): num_threads=%u\n", num_threads);
262                        
263 kumpf        1.81          try
264                            {
265 mike         1.91              join();
266                                empty_tsd();
267 kumpf        1.81          }
268 kumpf        1.98          catch (...)
269 kumpf        1.81          {
270 mike         1.91              // Do not allow the destructor to throw an exception
271 kumpf        1.81          }
272 mday         1.20      }
273                        
274 mike         1.91      #endif /* PEGASUS_HAVE_PTHREADS */
275                        
276                        //==============================================================================
277                        //
278                        // Windows Threads Implementation:
279                        //
280                        //==============================================================================
281 kumpf        1.81      
282 mike         1.91      #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
283 kumpf        1.81      
284 kumpf        1.98      ThreadStatus Thread::run()
285 mike         1.91      {
286                            // Note: A Win32 thread ID is not the same thing as a pthread ID.
287                            // Win32 threads have both a thread ID and a handle.  The handle
288                            // is used in the wait functions, etc.
289                            // So _handle.thid is actually the thread handle.
290 kumpf        1.81      
291 mike         1.91          unsigned threadid = 0;
292 mike         1.2       
293 mike         1.91          ThreadType tt;
294                            tt.handle = (HANDLE) _beginthreadex(NULL, 0, _start, this, 0, &threadid);
295                            _handle.thid = tt;
296 chuck        1.39      
297 mike         1.95          if (Threads::null(_handle.thid))
298 mike         1.91          {
299                                if (errno == EAGAIN)
300 kumpf        1.81              {
301 mike         1.91                  return PEGASUS_THREAD_INSUFFICIENT_RESOURCES;
302 kumpf        1.81              }
303 mike         1.91              else
304 kumpf        1.81              {
305 mike         1.91                  return PEGASUS_THREAD_SETUP_FAILURE;
306 kumpf        1.81              }
307 mike         1.91          }
308                            return PEGASUS_THREAD_OK;
309                        }
310 mday         1.52      
311 kumpf        1.98      void Thread::cancel()
312 mike         1.91      {
313                            _cancelled = true;
314                        }
315 kumpf        1.82      
316 kumpf        1.98      void Thread::test_cancel()
317 mike         1.91      {
318                            if (_cancel_enabled && _cancelled)
319                            {
320                                exit_self(0);
321                            }
322                        }
323 kumpf        1.82      
324 kumpf        1.98      Boolean Thread::is_cancelled()
325 mike         1.91      {
326                            return _cancelled;
327                        }
328 kumpf        1.82      
329 kumpf        1.98      void Thread::thread_switch()
330 mike         1.91      {
331                            Sleep(0);
332                        }
333 kumpf        1.82      
334 mike         1.91      void Thread::sleep(Uint32 milliseconds)
335                        {
336                            Sleep(milliseconds);
337                        }
338 mike         1.2       
339 kumpf        1.98      void Thread::join()
340 mike         1.91      {
341 mike         1.95          if (!Threads::null(_handle.thid))
342 mike         1.91          {
343                                if (!_is_detached)
344                                {
345                                    if (!_cancelled)
346 kumpf        1.82                  {
347 mike         1.91                      // Emulate the unix join api. Caller sleeps until thread is
348                                        // done.
349                                        WaitForSingleObject(_handle.thid.handle, INFINITE);
350 kumpf        1.82                  }
351 mike         1.91                  else
352 kumpf        1.82                  {
353 mike         1.91                      // Currently this is the only way to ensure this code does
354 kumpf        1.98                      // not
355 mike         1.91                      // hang forever.
356                                        if (WaitForSingleObject(_handle.thid.handle, 10000) ==
357                                            WAIT_TIMEOUT)
358 kumpf        1.82                      {
359 mike         1.91                          TerminateThread(_handle.thid.handle, 0);
360 kumpf        1.82                      }
361 mike         1.91                  }
362 s.hills      1.49      
363 mike         1.91                  DWORD exit_code = 0;
364                                    GetExitCodeThread(_handle.thid.handle, &exit_code);
365                                    _exit_code = (ThreadReturnType) exit_code;
366 kumpf        1.81              }
367 mike         1.91      
368                                CloseHandle(_handle.thid.handle);
369                                Threads::clear(_handle.thid);
370 kumpf        1.82          }
371 mike         1.91      }
372 kumpf        1.14      
373 kumpf        1.98      void Thread::thread_init()
374 mike         1.91      {
375                            _cancel_enabled = true;
376 mike         1.2       }
377                        
378 kumpf        1.98      void Thread::detach()
379 mike         1.2       {
380 mike         1.91          _is_detached = true;
381                        }
382 kumpf        1.81      
383 mike         1.91      Thread::Thread(ThreadReturnType(PEGASUS_THREAD_CDECL * start) (void *),
384                                       void *parameter,
385                                       Boolean detached):_is_detached(detached),
386                        _cancel_enabled(true),
387                        _cancelled(false),
388                        _start(start), _cleanup(), _tsd(), _thread_parm(parameter), _exit_code(0)
389                        {
390                            Threads::clear(_handle.thid);
391                        }
392 kumpf        1.81      
393 mike         1.91      Thread::~Thread()
394                        {
395 kumpf        1.81          try
396                            {
397 mike         1.91              join();
398                                empty_tsd();
399                            }
400 kumpf        1.98          catch (...)
401 mike         1.91          {
402                            }
403                        }
404 kumpf        1.81      
405 mike         1.91      #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
406 kumpf        1.57      
407 mike         1.91      //==============================================================================
408                        //
409                        // Common implementation:
410                        //
411                        //==============================================================================
412 kumpf        1.81      
413 mike         1.91      void thread_data::default_delete(void *data)
414                        {
415                            if (data != NULL)
416                                ::operator  delete(data);
417                        }
418 mike         1.2       
419 mike         1.91      void language_delete(void *data)
420                        {
421                            if (data != NULL)
422                            {
423                                AutoPtr < AcceptLanguageList > al(static_cast <
424                                                                  AcceptLanguageList * >(data));
425 kumpf        1.57          }
426 mike         1.2       }
427                        
428 mike         1.91      Boolean Thread::_signals_blocked = false;
429                        #ifndef PEGASUS_OS_ZOS
430                        TSDKeyType Thread::_platform_thread_key = TSDKeyType(-1);
431                        #else
432                        TSDKeyType Thread::_platform_thread_key;
433                        #endif
434                        Boolean Thread::_key_initialized = false;
435                        Boolean Thread::_key_error = false;
436 mday         1.12      
437 mike         1.91      void Thread::cleanup_push(void (*routine) (void *), void *parm)
438 mike         1.2       {
439 mike         1.91          AutoPtr < cleanup_handler > cu(new cleanup_handler(routine, parm));
440                            _cleanup.insert_front(cu.get());
441                            cu.release();
442                            return;
443                        }
444 kumpf        1.81      
445 mike         1.91      void Thread::cleanup_pop(Boolean execute)
446                        {
447                            AutoPtr < cleanup_handler > cu;
448                            try
449                            {
450                                cu.reset(_cleanup.remove_front());
451                            }
452 kumpf        1.98          catch (IPCException &)
453 mike         1.91          {
454                                PEGASUS_ASSERT(0);
455                            }
456                            if (execute == true)
457                                cu->execute();
458                        }
459 kumpf        1.81      
460                        
461 mike         1.91      void Thread::exit_self(ThreadReturnType exit_code)
462                        {
463 ouyang.jian  1.100     #if !defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) \
464                            && !defined(PEGASUS_PLATFORM_PASE_ISERIES_IBMCXX)
465 marek        1.97          Threads::exit(exit_code);
466 mike         1.91      #else
467                            // execute the cleanup stack and then return
468                            while (_cleanup.size())
469                            {
470 kumpf        1.81              try
471                                {
472 mike         1.91                  cleanup_pop(true);
473 kumpf        1.81              }
474 kumpf        1.98              catch (IPCException &)
475 kumpf        1.81              {
476 mike         1.91                  PEGASUS_ASSERT(0);
477 kumpf        1.81                  break;
478                                }
479 mike         1.91          }
480                            _exit_code = exit_code;
481                            Threads::exit(exit_code);
482                            Threads::clear(_handle.thid);
483                        #endif
484                        }
485 kumpf        1.81      
486 mike         1.91      Sint8 Thread::initializeKey()
487                        {
488                            PEG_METHOD_ENTER(TRC_THREAD, "Thread::initializeKey");
489                            if (!Thread::_key_initialized)
490                            {
491                                if (Thread::_key_error)
492                                {
493 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
494 mike         1.91                                "Thread: ERROR - thread key error");
495                                    return -1;
496                                }
497 kumpf        1.81      
498 mike         1.91              if (TSDKey::create(&Thread::_platform_thread_key) == 0)
499 kumpf        1.81              {
500 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
501 mike         1.91                                "Thread: able to create a thread key");
502                                    Thread::_key_initialized = true;
503 kumpf        1.81              }
504                                else
505                                {
506 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
507 mike         1.91                                "Thread: ERROR - unable to create a thread key");
508                                    Thread::_key_error = true;
509                                    return -1;
510 kumpf        1.81              }
511 konrad.r     1.67          }
512 kumpf        1.81      
513                            PEG_METHOD_EXIT();
514 mike         1.91          return 0;
515 konrad.r     1.67      }
516 mday         1.19      
517 mike         1.91      Thread *Thread::getCurrent()
518 mday         1.19      {
519 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::getCurrent");
520                            if (Thread::initializeKey() != 0)
521                            {
522                                return NULL;
523                            }
524 kumpf        1.81          PEG_METHOD_EXIT();
525 mike         1.91          return (Thread *) TSDKey::get_thread_specific(_platform_thread_key);
526 mday         1.19      }
527                        
528 mike         1.91      void Thread::setCurrent(Thread * thrd)
529 mday         1.19      {
530 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::setCurrent");
531                            if (Thread::initializeKey() == 0)
532 kumpf        1.81          {
533 mike         1.91              if (TSDKey::
534                                    set_thread_specific(Thread::_platform_thread_key,
535                                                        (void *) thrd) == 0)
536                                {
537 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
538 mike         1.91                      "Successful set Thread * into thread specific storage");
539                                }
540                                else
541                                {
542 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
543 mike         1.91                      "ERROR: error setting Thread * into thread specific storage");
544                                }
545 kumpf        1.81          }
546 mike         1.91          PEG_METHOD_EXIT();
547 mday         1.19      }
548                        
549 mike         1.91      AcceptLanguageList *Thread::getLanguages()
550 mday         1.19      {
551 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::getLanguages");
552                        
553                            Thread *curThrd = Thread::getCurrent();
554                            if (curThrd == NULL)
555                                return NULL;
556                            AcceptLanguageList *acceptLangs =
557                                (AcceptLanguageList *) curThrd->reference_tsd("acceptLanguages");
558                            curThrd->dereference_tsd();
559                            PEG_METHOD_EXIT();
560                            return acceptLangs;
561 mday         1.19      }
562                        
563 kumpf        1.98      void Thread::setLanguages(AcceptLanguageList * langs)
564 mday         1.19      {
565 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::setLanguages");
566 kumpf        1.81      
567 mike         1.91          Thread *currentThrd = Thread::getCurrent();
568                            if (currentThrd != NULL)
569 kumpf        1.81          {
570 mike         1.91              // deletes the old tsd and creates a new one
571                                currentThrd->put_tsd("acceptLanguages",
572                                                     language_delete,
573                                                     sizeof (AcceptLanguageList *), langs);
574 kumpf        1.81          }
575                        
576                            PEG_METHOD_EXIT();
577 mday         1.19      }
578 mike         1.2       
579 kumpf        1.98      void Thread::clearLanguages()
580 kumpf        1.81      {
581 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::clearLanguages");
582                        
583                            Thread *currentThrd = Thread::getCurrent();
584                            if (currentThrd != NULL)
585 kumpf        1.81          {
586 mike         1.91              // deletes the old tsd
587                                currentThrd->delete_tsd("acceptLanguages");
588 kumpf        1.81          }
589                        
590 mike         1.91          PEG_METHOD_EXIT();
591 kumpf        1.81      }
592 mike         1.2       
593 mike         1.91      // ATTN: not sure where to put this!
594                        #ifdef PEGASUS_ZOS_SECURITY
595                        bool isEnhancedSecurity = 99;
596                        #endif
597                        
598 mike         1.2       PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2