1 /* -*- mode: c++; c-basic-offset: 4; -*-
3 * MICO --- an Open Source CORBA implementation
4 * Copyright (c) 1997-2001 by The Mico Team
7 * Copyright (C) 1999 Andreas Schultz
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * For more information, visit the MICO Home Page at
24 * http://www.mico.org/
28 #ifndef __OS_THREAD_H__
29 #define __OS_THREAD_H__
31 #if defined(_WIN32) && !defined(__MINGW32__)
32 #include <mico/config-win32.h>
34 #include <mico/config.h>
39 * \defgroup micomt Threading Support
41 * Definitions in this group provide thread support
49 * The MICOMT namespace contains classes and types that provide
50 * a complete multithreaded development environment for the MICO
51 * ORB and applications.
55 // Define HAVE_THREADS if any type of thread implementations are defined.
56 // supported "implementations" are:
58 // HAVE_PTHREADS - POSIX Draft 10 PThreads [Single UNIX Spec V.2 & X/Open Interfaces]
59 // (i.e. HP/UX 11, Linux PThreads (Xavier LeRoy@inria.fr))
60 // HAVE_DCE_THREADS - POSIX Draft 4 (DCE) Threads (i.e. HP/UX 10)
61 // HAVE_WIN_THREADS - M$ Windows threads or whatever M$ calls them...
62 // HAVE_SOLARIS_THREADS - SUN Solaris Threads.
63 // HAVE_OSPACE_THREADS - Object Space(r) Thread<ToolKit>(tm) via D10/D4/Linux
66 #if defined (HAVE_PTHREADS) || defined (HAVE_DCE_THREADS) || \
67 defined (HAVE_SOLARIS_THREADS) || defined (HAVE_PTH_THREADS) || \
68 defined (HAVE_WIN_THREADS)
71 #define HAVE_THREADS // def'd as a convenience
72 #endif // HAVE_THREADS
74 #endif // HAVE_THREADS
76 #include <mico/mtdebug.h>
81 // OS dependant includes
83 #if defined(HAVE_PTH_THREADS) && defined(HAVE_PTH_H)
86 #if defined(HAVE_PTHREADS) || defined(HAVE_DCETHREADS)
87 # ifdef HAVE_PTHREAD_H
90 # ifdef HAVE_SEMAPHORE_H
91 # include <semaphore.h>
97 #if defined(HAVE_SOLARIS_THREADS)
104 # ifdef HAVE_SEMAPHORE_H
105 # include <semaphore.h>
109 // thread startup mode
110 #define _THR_CREATE_AND_BLOCK
111 //#define _THR_DEFERED_CREATE
116 #include <mico/os-thread/pthreads.h>
117 #endif // HAVE_PTHREADS
119 #ifdef HAVE_DCE_THREADS
120 #include <mico/os-thread/dcethreads.h>
121 #endif // HAVE_DCE_THREADS
123 #ifdef HAVE_PTH_THREADS
124 #include <mico/os-thread/pththreads.h>
125 #endif // HAVE_PTH_THREADS
127 #ifdef HAVE_WIN_THREADS
129 #endif // HAVE_WIN_THREADS
131 #ifdef HAVE_SOLARIS_THREADS
132 #include <mico/os-thread/solaris-threads.h>
133 #endif // HAVE_SOLARIS_THREADS
141 * The AutoLock class is better way to work with Mutex class, so
153 * AutoLock l(my_mutex);
157 * The main advantage here is that it'll automatically unlock
158 * mutex even in case of throwing exception
164 //! \name Constructor/Destructor
167 * \param m The mutex to lock
168 * The constructor will lock the supplied mutex.
177 * The destructor unlocks the mutex.
189 * The AutoRDLock is usefull for reader-writer locks in the same
190 * way as AutoLock class is for mutexes, but this class will obtain
198 * \name Constructor/Destructor
202 * \param l The lock to use
203 * The constructor will obtain reader lock
205 AutoRDLock(RWLock& l)
212 * The destructor frees obtained read lock
224 * The AutoWRLock is usefull for reader-writer locks in the same
225 * way as AutoLock class for mutexes, but this class will obtain
232 //! \name Constructor/Destructor
235 * \param l The lock to use
236 * The constructor will obtain writer lock
238 AutoWRLock(RWLock& l)
245 * The destructor frees obtained write lock
261 * The Locked class can be used to make a class lockable
262 * by inheriting from both T and RWLock.
264 * \param T The class to make lockable
266 * Example: (Queue is queue of integers)
268 * Locked<Queue> queue_;
271 * AutoLock l(queue_);
277 class Locked: public T, public Mutex
282 Locked(MICO_Boolean locked, Attribute rec)
290 * The RWLocked class can be used to make a class lockable
291 * by inheriting from both T and RWLock.
293 * \param T The class type to make lockable.
296 class RWLocked: public T, public RWLock
302 // state controlled reference counting
307 * The StateRefCnt class is used to control stated reference counting for
308 * objects used by more than one thread.
311 * \li active_ref() will only succed if the object is "Active"
312 * \li active_deref() will wake threads waiting to change the objects state
313 * if the ref count is 0
314 * \li a StateChange will only succed after ref count is 0
320 * The ExecState defines the state of the reference count.
323 Init, //!< Initialized
325 InitShutdown, //!< Shutdown started
326 Shutdown, //!< Shut down
327 Terminated //!< Terminated
331 ExecState _current_state; //!< Current state
332 ExecState _new_state; //!< The new state
333 MICO_ULong _activerefs; //!< Active references
334 Mutex _mutex; //!< Lock for the ref counter
335 CondVar _cond; //!< Condition var fof the counter
338 //! \name Constructor/Destructor
341 * Default constructor.
344 : _current_state(Init), _new_state(Init), _activerefs(0),
356 * Increment the active reference count if the state is
359 * \return False if the object is not active.
366 if ((_current_state != _new_state) && (_current_state != Active)) {
374 * Decrement the active reference counts. If the count reaches
375 * 0, the condition variable is broadcasted on.
383 if ( (_activerefs == 0) && (_new_state != Active) )
388 * This function changes the current state to the requested
391 * \param s The requested state
392 * \return True on success, false on failure
395 state_change(ExecState s)
399 if ( s <= _current_state ) {
403 //wait until the state change has become effective
404 while (_activerefs != 0) {
407 if ( _new_state <= _current_state )
410 _current_state = _new_state;
415 * Get the current state.
417 * \return The current state
421 { return _current_state; };
424 * This method puts the state into InitShutdown if
427 * \return True on success, false on failure.
434 if (_new_state != Active ) {
437 _current_state = _new_state = InitShutdown;
443 #else // HAVE_THREADS
445 // The user should use following code for making code better portable
446 // between single and multi threaded environment i.e. the user can use
447 // Mutex, CondVar, Semaphore etc. classes even while building
448 // on single-threaded environment - so w/o any #ifdef HAVE_THREADS #endif
450 // Following code is w/o doxygen documentation because doxyfile defines
451 // HAVE_PTHREADS and so it's not used for generating of documentation
458 #endif // DEBUG_NAMES
467 Mutex(MICO_Boolean locked = FALSE, Attribute attr = MICOMT::Mutex::Normal)
489 #endif // DEBUG_NAMES
502 timedwait(MICO_ULong)
518 #endif // DEBUG_NAMES
543 #endif // DEBUG_NAMES
547 NoError, //!< No error on semaphore
548 NoPermission, //!< Permission denied
549 TryAgain, //!< Try again
550 SemInvalid, //!< Invalide semaphore
551 Interrupted, //!< Interrupted by signal
552 UnknownError //!< Unknow error
555 Semaphore(unsigned int)
566 { return MICOMT::Semaphore::NoError; };
577 AutoRDLock(RWLock& l)
587 AutoWRLock(RWLock& l)
595 class RWLocked: public T, public RWLock
611 class Locked: public T, public Mutex
616 Locked(MICO_Boolean locked, Attribute rec)
622 #endif // HAVE_THREADS
624 #endif // __OS_THREAD_H__