(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 mike         1.100.2.5 #if 1
223 mike         1.100.2.3 static Uint32 _num_threads = 0;
224                        static Mutex _num_threads_mutex;
225 mike         1.100.2.5 #endif
226 mike         1.100.2.3 
227 kumpf        1.98      Thread::Thread(
228                            ThreadReturnType(PEGASUS_THREAD_CDECL* start) (void*),
229                            void* parameter,
230                            Boolean detached)
231                            : _is_detached(detached),
232                              _cancel_enabled(true),
233                              _cancelled(false),
234                              _start(start),
235                              _cleanup(),
236                              _tsd(),
237                              _thread_parm(parameter),
238                              _exit_code(0)
239 mike         1.91      {
240 mike         1.100.2.3 /*
241                        ATTN: remove this!
242                        */
243 mike         1.100.2.5 #if 1
244 mike         1.100.2.3     Uint32 num_threads;
245                            _num_threads_mutex.lock();
246                            _num_threads++;
247                            num_threads = _num_threads;
248 mike         1.100.2.5     printf("Thread::Thread(): num_threads=%u\n", num_threads);
249 mike         1.100.2.3     _num_threads_mutex.unlock();
250 mike         1.100.2.5 #endif
251 mike         1.100.2.3 
252 mike         1.91          Threads::clear(_handle.thid);
253 kumpf        1.81      }
254 mday         1.20      
255 mike         1.91      Thread::~Thread()
256 mday         1.20      {
257 mike         1.100.2.3 /*
258                        ATTN: remove this!
259                        */
260 mike         1.100.2.5 #if 1
261 mike         1.100.2.3     Uint32 num_threads;
262                            _num_threads_mutex.lock();
263                            _num_threads--;
264                            num_threads = _num_threads;
265 mike         1.100.2.5     printf("Thread::~Thread(): num_threads=%u\n", num_threads);
266 mike         1.100.2.3     _num_threads_mutex.unlock();
267 mike         1.100.2.5 #endif
268 mike         1.100.2.3 
269 kumpf        1.81          try
270                            {
271 mike         1.91              join();
272                                empty_tsd();
273 kumpf        1.81          }
274 kumpf        1.98          catch (...)
275 kumpf        1.81          {
276 mike         1.91              // Do not allow the destructor to throw an exception
277 kumpf        1.81          }
278 mday         1.20      }
279                        
280 mike         1.91      #endif /* PEGASUS_HAVE_PTHREADS */
281                        
282                        //==============================================================================
283                        //
284                        // Windows Threads Implementation:
285                        //
286                        //==============================================================================
287 kumpf        1.81      
288 mike         1.91      #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
289 kumpf        1.81      
290 kumpf        1.98      ThreadStatus Thread::run()
291 mike         1.91      {
292                            // Note: A Win32 thread ID is not the same thing as a pthread ID.
293                            // Win32 threads have both a thread ID and a handle.  The handle
294                            // is used in the wait functions, etc.
295                            // So _handle.thid is actually the thread handle.
296 kumpf        1.81      
297 mike         1.91          unsigned threadid = 0;
298 mike         1.2       
299 mike         1.91          ThreadType tt;
300                            tt.handle = (HANDLE) _beginthreadex(NULL, 0, _start, this, 0, &threadid);
301                            _handle.thid = tt;
302 chuck        1.39      
303 mike         1.95          if (Threads::null(_handle.thid))
304 mike         1.91          {
305                                if (errno == EAGAIN)
306 kumpf        1.81              {
307 mike         1.91                  return PEGASUS_THREAD_INSUFFICIENT_RESOURCES;
308 kumpf        1.81              }
309 mike         1.91              else
310 kumpf        1.81              {
311 mike         1.91                  return PEGASUS_THREAD_SETUP_FAILURE;
312 kumpf        1.81              }
313 mike         1.91          }
314                            return PEGASUS_THREAD_OK;
315                        }
316 mday         1.52      
317 kumpf        1.98      void Thread::cancel()
318 mike         1.91      {
319                            _cancelled = true;
320                        }
321 kumpf        1.82      
322 kumpf        1.98      void Thread::test_cancel()
323 mike         1.91      {
324                            if (_cancel_enabled && _cancelled)
325                            {
326                                exit_self(0);
327                            }
328                        }
329 kumpf        1.82      
330 kumpf        1.98      Boolean Thread::is_cancelled()
331 mike         1.91      {
332                            return _cancelled;
333                        }
334 kumpf        1.82      
335 kumpf        1.98      void Thread::thread_switch()
336 mike         1.91      {
337                            Sleep(0);
338                        }
339 kumpf        1.82      
340 mike         1.91      void Thread::sleep(Uint32 milliseconds)
341                        {
342                            Sleep(milliseconds);
343                        }
344 mike         1.2       
345 kumpf        1.98      void Thread::join()
346 mike         1.91      {
347 mike         1.95          if (!Threads::null(_handle.thid))
348 mike         1.91          {
349                                if (!_is_detached)
350                                {
351                                    if (!_cancelled)
352 kumpf        1.82                  {
353 mike         1.91                      // Emulate the unix join api. Caller sleeps until thread is
354                                        // done.
355                                        WaitForSingleObject(_handle.thid.handle, INFINITE);
356 kumpf        1.82                  }
357 mike         1.91                  else
358 kumpf        1.82                  {
359 mike         1.91                      // Currently this is the only way to ensure this code does
360 kumpf        1.98                      // not
361 mike         1.91                      // hang forever.
362                                        if (WaitForSingleObject(_handle.thid.handle, 10000) ==
363                                            WAIT_TIMEOUT)
364 kumpf        1.82                      {
365 mike         1.91                          TerminateThread(_handle.thid.handle, 0);
366 kumpf        1.82                      }
367 mike         1.91                  }
368 s.hills      1.49      
369 mike         1.91                  DWORD exit_code = 0;
370                                    GetExitCodeThread(_handle.thid.handle, &exit_code);
371                                    _exit_code = (ThreadReturnType) exit_code;
372 kumpf        1.81              }
373 mike         1.91      
374                                CloseHandle(_handle.thid.handle);
375                                Threads::clear(_handle.thid);
376 kumpf        1.82          }
377 mike         1.91      }
378 kumpf        1.14      
379 kumpf        1.98      void Thread::thread_init()
380 mike         1.91      {
381                            _cancel_enabled = true;
382 mike         1.2       }
383                        
384 kumpf        1.98      void Thread::detach()
385 mike         1.2       {
386 mike         1.91          _is_detached = true;
387                        }
388 kumpf        1.81      
389 mike         1.91      Thread::Thread(ThreadReturnType(PEGASUS_THREAD_CDECL * start) (void *),
390                                       void *parameter,
391                                       Boolean detached):_is_detached(detached),
392                        _cancel_enabled(true),
393                        _cancelled(false),
394                        _start(start), _cleanup(), _tsd(), _thread_parm(parameter), _exit_code(0)
395                        {
396                            Threads::clear(_handle.thid);
397                        }
398 kumpf        1.81      
399 mike         1.91      Thread::~Thread()
400                        {
401 kumpf        1.81          try
402                            {
403 mike         1.91              join();
404                                empty_tsd();
405                            }
406 kumpf        1.98          catch (...)
407 mike         1.91          {
408                            }
409                        }
410 kumpf        1.81      
411 mike         1.91      #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
412 kumpf        1.57      
413 mike         1.91      //==============================================================================
414                        //
415                        // Common implementation:
416                        //
417                        //==============================================================================
418 kumpf        1.81      
419 mike         1.91      void thread_data::default_delete(void *data)
420                        {
421                            if (data != NULL)
422                                ::operator  delete(data);
423                        }
424 mike         1.2       
425 mike         1.91      void language_delete(void *data)
426                        {
427                            if (data != NULL)
428                            {
429                                AutoPtr < AcceptLanguageList > al(static_cast <
430                                                                  AcceptLanguageList * >(data));
431 kumpf        1.57          }
432 mike         1.2       }
433                        
434 mike         1.91      Boolean Thread::_signals_blocked = false;
435                        #ifndef PEGASUS_OS_ZOS
436                        TSDKeyType Thread::_platform_thread_key = TSDKeyType(-1);
437                        #else
438                        TSDKeyType Thread::_platform_thread_key;
439                        #endif
440                        Boolean Thread::_key_initialized = false;
441                        Boolean Thread::_key_error = false;
442 mday         1.12      
443 mike         1.91      void Thread::cleanup_push(void (*routine) (void *), void *parm)
444 mike         1.2       {
445 mike         1.91          AutoPtr < cleanup_handler > cu(new cleanup_handler(routine, parm));
446                            _cleanup.insert_front(cu.get());
447                            cu.release();
448                            return;
449                        }
450 kumpf        1.81      
451 mike         1.91      void Thread::cleanup_pop(Boolean execute)
452                        {
453                            AutoPtr < cleanup_handler > cu;
454                            try
455                            {
456                                cu.reset(_cleanup.remove_front());
457                            }
458 kumpf        1.98          catch (IPCException &)
459 mike         1.91          {
460                                PEGASUS_ASSERT(0);
461                            }
462                            if (execute == true)
463                                cu->execute();
464                        }
465 kumpf        1.81      
466                        
467 mike         1.91      void Thread::exit_self(ThreadReturnType exit_code)
468                        {
469 ouyang.jian  1.100     #if !defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) \
470                            && !defined(PEGASUS_PLATFORM_PASE_ISERIES_IBMCXX)
471 marek        1.97          Threads::exit(exit_code);
472 mike         1.91      #else
473                            // execute the cleanup stack and then return
474                            while (_cleanup.size())
475                            {
476 kumpf        1.81              try
477                                {
478 mike         1.91                  cleanup_pop(true);
479 kumpf        1.81              }
480 kumpf        1.98              catch (IPCException &)
481 kumpf        1.81              {
482 mike         1.91                  PEGASUS_ASSERT(0);
483 kumpf        1.81                  break;
484                                }
485 mike         1.91          }
486                            _exit_code = exit_code;
487                            Threads::exit(exit_code);
488                            Threads::clear(_handle.thid);
489                        #endif
490                        }
491 kumpf        1.81      
492 mike         1.91      Sint8 Thread::initializeKey()
493                        {
494                            PEG_METHOD_ENTER(TRC_THREAD, "Thread::initializeKey");
495                            if (!Thread::_key_initialized)
496                            {
497                                if (Thread::_key_error)
498                                {
499 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
500 mike         1.91                                "Thread: ERROR - thread key error");
501                                    return -1;
502                                }
503 kumpf        1.81      
504 mike         1.91              if (TSDKey::create(&Thread::_platform_thread_key) == 0)
505 kumpf        1.81              {
506 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
507 mike         1.91                                "Thread: able to create a thread key");
508                                    Thread::_key_initialized = true;
509 kumpf        1.81              }
510                                else
511                                {
512 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
513 mike         1.91                                "Thread: ERROR - unable to create a thread key");
514                                    Thread::_key_error = true;
515                                    return -1;
516 kumpf        1.81              }
517 konrad.r     1.67          }
518 kumpf        1.81      
519                            PEG_METHOD_EXIT();
520 mike         1.91          return 0;
521 konrad.r     1.67      }
522 mday         1.19      
523 mike         1.91      Thread *Thread::getCurrent()
524 mday         1.19      {
525 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::getCurrent");
526                            if (Thread::initializeKey() != 0)
527                            {
528                                return NULL;
529                            }
530 kumpf        1.81          PEG_METHOD_EXIT();
531 mike         1.91          return (Thread *) TSDKey::get_thread_specific(_platform_thread_key);
532 mday         1.19      }
533                        
534 mike         1.91      void Thread::setCurrent(Thread * thrd)
535 mday         1.19      {
536 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::setCurrent");
537                            if (Thread::initializeKey() == 0)
538 kumpf        1.81          {
539 mike         1.91              if (TSDKey::
540                                    set_thread_specific(Thread::_platform_thread_key,
541                                                        (void *) thrd) == 0)
542                                {
543 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
544 mike         1.91                      "Successful set Thread * into thread specific storage");
545                                }
546                                else
547                                {
548 marek        1.99                  PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
549 mike         1.91                      "ERROR: error setting Thread * into thread specific storage");
550                                }
551 kumpf        1.81          }
552 mike         1.91          PEG_METHOD_EXIT();
553 mday         1.19      }
554                        
555 mike         1.91      AcceptLanguageList *Thread::getLanguages()
556 mday         1.19      {
557 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::getLanguages");
558                        
559                            Thread *curThrd = Thread::getCurrent();
560                            if (curThrd == NULL)
561                                return NULL;
562                            AcceptLanguageList *acceptLangs =
563                                (AcceptLanguageList *) curThrd->reference_tsd("acceptLanguages");
564                            curThrd->dereference_tsd();
565                            PEG_METHOD_EXIT();
566                            return acceptLangs;
567 mday         1.19      }
568                        
569 kumpf        1.98      void Thread::setLanguages(AcceptLanguageList * langs)
570 mday         1.19      {
571 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::setLanguages");
572 kumpf        1.81      
573 mike         1.91          Thread *currentThrd = Thread::getCurrent();
574                            if (currentThrd != NULL)
575 kumpf        1.81          {
576 mike         1.91              // deletes the old tsd and creates a new one
577                                currentThrd->put_tsd("acceptLanguages",
578                                                     language_delete,
579                                                     sizeof (AcceptLanguageList *), langs);
580 kumpf        1.81          }
581                        
582                            PEG_METHOD_EXIT();
583 mday         1.19      }
584 mike         1.2       
585 kumpf        1.98      void Thread::clearLanguages()
586 kumpf        1.81      {
587 mike         1.91          PEG_METHOD_ENTER(TRC_THREAD, "Thread::clearLanguages");
588                        
589                            Thread *currentThrd = Thread::getCurrent();
590                            if (currentThrd != NULL)
591 kumpf        1.81          {
592 mike         1.91              // deletes the old tsd
593                                currentThrd->delete_tsd("acceptLanguages");
594 kumpf        1.81          }
595                        
596 mike         1.91          PEG_METHOD_EXIT();
597 kumpf        1.81      }
598 mike         1.2       
599 mike         1.91      // ATTN: not sure where to put this!
600                        #ifdef PEGASUS_ZOS_SECURITY
601                        bool isEnhancedSecurity = 99;
602                        #endif
603                        
604 mike         1.2       PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2