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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2