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
|