001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
413:
414:
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426:
427:
428:
429:
430:
431:
432:
433:
434:
435:
436:
437:
438:
439:
440:
441:
442:
443:
444:
445:
446:
447:
448:
449:
450:
451:
452:
453:
454:
455:
456:
457:
458:
459:
460:
461:
462:
463:
464:
465:
466:
467:
468:
469:
470:
471:
472:
473:
474:
475:
476:
477:
478:
479:
480:
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506:
507:
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
520:
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553:
554:
555:
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567:
568:
569:
570:
571:
572:
573:
574:
575:
576:
577:
578:
579:
580:
581:
582:
583:
584:
585:
586:
587:
588:
589:
590:
591:
592:
593:
594:
595:
596:
597:
598:
599:
600:
601:
602:
603:
604:
605:
606:
607:
608:
609:
610:
611:
612:
613:
614:
615:
616:
617:
618:
619:
620:
621:
622:
623:
624:
625:
626:
627:
628:
629:
630:






















































































































































































































































































































































































































































































































































































































































/*
* This file is part of the Omni C++ framework
*
* Copyright (c) 2016, Zeriph Enterprises, LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of Zeriph, Zeriph Enterprises, LLC, nor the names
* of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ZERIPH AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ZERIPH AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(OMNI_THREAD_T_HPP)
#define OMNI_THREAD_T_HPP 1
#include <omni/defs/global.hpp>
#include <omni/defs/thread_def.hpp>
#include <omni/types/string_t.hpp>
#include <omni/util/bits.hpp>
#include <omni/generic_ptr.hpp>
#include <omni/chrono/tick.hpp>
#include <omni/delegate/0.hpp>
#include <omni/delegate/1.hpp>
#include <omni/delegate/2.hpp>
#include <omni/defs/consts.hpp>

namespace omni {
    namespace sync {
        /** The priority structure defines enum values for the scheduling priority of a process or thread. */
        typedef struct thread_priority {
            /** The underlying enum type exposed via the parent priority structure */
            typedef enum enum_t {
                /** Defines an idle thread priority */
                IDLE = -15,
                /** Defines a low thread priority */
                LOWEST = -2,
                /** Defines a below normal thread priority */
                BELOW_NORMAL = -1,
                /** Defines a normal thread priority */
                NORMAL = 0,
                /** Defines an above normal thread priority */
                ABOVE_NORMAL = 1,
                /** Defines a highest thread priority */
                HIGHEST = 2,
                /** Defines a real time thread priority */
                REAL_TIME = 15
            } enum_t;
            /** Defines the number of elements in the priority enum */
            static const unsigned short COUNT = 7;
            
            /** Converts the enum to its string representation */
            static const std::string to_string(const enum_t& v)
            {
                switch (v) {
                    OMNI_E2S_FW(IDLE);
                    OMNI_E2S_FW(LOWEST);
                    OMNI_E2S_FW(BELOW_NORMAL);
                    OMNI_E2S_FW(NORMAL);
                    OMNI_E2S_FW(ABOVE_NORMAL);
                    OMNI_E2S_FW(HIGHEST);
                    OMNI_E2S_FW(REAL_TIME);
                    default: break;
                }
                return "UNKNOWN";
            }
            
            /** Converts the enum to its wide string representation */
            static const std::wstring to_wstring(const enum_t& v)
            {
                switch (v) {
                    OMNI_E2WS_FW(IDLE);
                    OMNI_E2WS_FW(LOWEST);
                    OMNI_E2WS_FW(BELOW_NORMAL);
                    OMNI_E2WS_FW(NORMAL);
                    OMNI_E2WS_FW(ABOVE_NORMAL);
                    OMNI_E2WS_FW(HIGHEST);
                    OMNI_E2WS_FW(REAL_TIME);
                    default: break;
                }
                return OMNI_WSTR("UNKNOWN");
            }
            
            friend std::ostream& operator<<(std::ostream& s, const enum_t& c)
            { s << to_string(c); return s; }
            friend std::wostream& operator<<(std::wostream& s, const enum_t& c)
            { s << to_wstring(c); return s; }
        } thread_priority;
        
        /** The thread start type (immediate or user) */
        typedef struct thread_start_type {
            /** The underlying enum type expected */
            typedef enum enum_t {
                /** Defines the thread will start when the user calls the start method */
                USER = 0,
                /** Defines the thread will start after construction is complete */
                NOW = 1
            } enum_t;
            /** Defines the number of elements in the start_type enum */
            static const unsigned short COUNT = 2;
            
            /** Converts the enum to its string representation */
            static const std::string to_string(const enum_t& v)
            {
                switch (v) {
                    OMNI_E2S_FW(USER);
                    OMNI_E2S_FW(NOW);
                    default: break;
                }
                return "UNKNOWN";
            }
            
            /** Converts the enum to its wide string representation */
            static const std::wstring to_wstring(const enum_t& v)
            {
                switch (v) {
                    OMNI_E2WS_FW(USER);
                    OMNI_E2WS_FW(NOW);
                    default: break;
                }
                return OMNI_WSTR("UNKNOWN");
            }
            
            friend std::ostream& operator<<(std::ostream& s, const enum_t& c)
            { s << to_string(c); return s; }
            friend std::wostream& operator<<(std::wostream& s, const enum_t& c)
            { s << to_wstring(c); return s; }
        } thread_start_type;
        
        /** The state structure defines enum values for the execution status of thread types */
        typedef struct thread_state {
            /** The underlying enum type exposed via the parent state structure */
            typedef enum enum_t {
                /** Defines a thread as unstarted (default when created) */
                UNSTARTED = 0,
                /** Defines a thread is attempting to spawn */
                START_REQUESTED = 1,
                /** Defines a thread is running (method has been called) */
                RUNNING = 2,
                /** Defines a thread has completed its function (method complete) */
                COMPLETED = 4,
                /** Defines a thread has a stop request (kill request) */
                STOP_REQUESTED = 8,
                /** Defines a thread is stopped (killed) */
                STOPPED = 16,
                /** Defines a thread has an abort request */
                ABORT_REQUESTED = 32,
                /** Defines a thread has been aborted */
                ABORTED = 64,
                /** Defines a thread has a state that can not be determined (when creating threads from handles for instance) */
                UNKNOWN = 255
            } enum_t;
            
            /** Defines the number of elements in the state enum */
            static const unsigned short COUNT = 9;
            
            /** Converts the enum to its string representation */
            static const std::string to_string(const enum_t& v)
            {
                switch (v) {
                    OMNI_E2S_FW(UNSTARTED);
                    OMNI_E2S_FW(START_REQUESTED);
                    OMNI_E2S_FW(RUNNING);
                    OMNI_E2S_FW(COMPLETED);
                    OMNI_E2S_FW(STOP_REQUESTED);
                    OMNI_E2S_FW(STOPPED);
                    OMNI_E2S_FW(ABORT_REQUESTED);
                    OMNI_E2S_FW(ABORTED);
                    OMNI_E2S_FW(UNKNOWN); // pedant
                    default: break;
                }
                return "UNKNOWN";
            }
            
            /** Converts the enum to its wide string representation */
            static const std::wstring to_wstring(const enum_t& v)
            {
                switch (v) {
                    OMNI_E2WS_FW(UNSTARTED);
                    OMNI_E2WS_FW(START_REQUESTED);
                    OMNI_E2WS_FW(RUNNING);
                    OMNI_E2WS_FW(COMPLETED);
                    OMNI_E2WS_FW(STOP_REQUESTED);
                    OMNI_E2WS_FW(STOPPED);
                    OMNI_E2WS_FW(ABORT_REQUESTED);
                    OMNI_E2WS_FW(ABORTED);
                    OMNI_E2WS_FW(UNKNOWN); // pedant
                    default: break;
                }
                return OMNI_WSTR("UNKNOWN");
            }
            
            friend std::ostream& operator<<(std::ostream& s, const enum_t& c)
            { s << to_string(c); return s; }
            friend std::wostream& operator<<(std::wostream& s, const enum_t& c)
            { s << to_wstring(c); return s; }
        } thread_state;
        
        /** Defines the thread options structure allowing finer control of a thread object */
        typedef struct thread_option {
            /** The underlying enum type exposed via the parent thread_option structure */
            typedef enum enum_t {
                /** Defines the option to set if the thread shall allow reuse of the thread */
                ALLOW_THREAD_REUSE = 1,
                /** Defines the option to auto join a thread on destruction */
                AUTO_JOIN = 2,
                DETACH_ON_DESTROY = 4, // default
                ABORT_ON_DESTROY = 8,
                KILL_ON_DESTROY = 16,
                DETACH_ON_ASSIGN = 32, // default
                ABORT_ON_ASSIGN = 64,
                KILL_ON_ASSIGN = 128,
                /** Defines the option to set if the thread shall have a specified stack size */
                STACK_SIZE = 256,
                /** Defines the option to set if the thread timeout for join operation on kill_on_eop */
                AUTO_JOIN_TIMEOUT = 512
            } enum_t;
            
            /** Defines the number of elements in the thread_option enum */
            static const unsigned short COUNT = 10;
            
            /** Converts the enum to its string representation */
            static const std::string to_string(const enum_t& v)
            {
                switch (v) {
                    OMNI_E2S_FW(ALLOW_THREAD_REUSE);
                    OMNI_E2S_FW(AUTO_JOIN);
                    OMNI_E2S_FW(DETACH_ON_DESTROY);
                    OMNI_E2S_FW(ABORT_ON_DESTROY);
                    OMNI_E2S_FW(KILL_ON_DESTROY);
                    OMNI_E2S_FW(DETACH_ON_ASSIGN);
                    OMNI_E2S_FW(ABORT_ON_ASSIGN);
                    OMNI_E2S_FW(KILL_ON_ASSIGN);
                    OMNI_E2S_FW(STACK_SIZE);
                    OMNI_E2S_FW(AUTO_JOIN_TIMEOUT);
                    default: break;
                }
                return "UNKNOWN";
            }
            
            /** Converts the enum to its wide string representation */
            static const std::wstring to_wstring(const enum_t& v)
            {
                switch (v) {
                    OMNI_E2WS_FW(ALLOW_THREAD_REUSE);
                    OMNI_E2WS_FW(AUTO_JOIN);
                    OMNI_E2WS_FW(DETACH_ON_DESTROY);
                    OMNI_E2WS_FW(ABORT_ON_DESTROY);
                    OMNI_E2WS_FW(KILL_ON_DESTROY);
                    OMNI_E2WS_FW(DETACH_ON_ASSIGN);
                    OMNI_E2WS_FW(ABORT_ON_ASSIGN);
                    OMNI_E2WS_FW(KILL_ON_ASSIGN);
                    OMNI_E2WS_FW(STACK_SIZE);
                    OMNI_E2WS_FW(AUTO_JOIN_TIMEOUT);
                    default: break;
                }
                return OMNI_WSTR("UNKNOWN");
            }
            
            friend std::ostream& operator<<(std::ostream& s, const enum_t& c)
            { s << to_string(c); return s; }
            friend std::wostream& operator<<(std::wostream& s, const enum_t& c)
            { s << to_wstring(c); return s; }
        } thread_option;
        
        /** Defines the union type used to set specific thread options. */
        typedef union thread_option_union {
            /** Defines the std::size_t value of this union */
            std::size_t s_val;
            /** Defines the boolean value of this union */
            bool b_val;
            
            /**
             * This constructor is templated to avoid ambiguous name resolution errors
             * with the more specialized bool/std::size_t constructors. A compile error
             * will be generated if this template constructor is utilized since it's
             * an error to initialize both members of a union in a constructor.
             *
             * @param val Not used
             * @tparam T    Not used
             */
            template < typename T >
            thread_option_union(T val) : s_val(0), b_val(false) {}
            
            /**
             * Create a new union based on the specified numeric value.
             *
             * @param val The value to set to this union
             */
            thread_option_union(int val) : s_val(val) {}
            
            /**
             * Create a new union based on the specified numeric value.
             *
             * @param val The value to set to this union
             */
            thread_option_union(long val) : s_val(val) {}
            
            /**
             * Create a new union based on the specified numeric value.
             *
             * @param val The value to set to this union
             */
            thread_option_union(std::size_t val) : s_val(val) {}
            
            /**
             * Create a new union based on the specified boolean value.
             *
             * @param val The value to set to this union
             */
            thread_option_union(bool val) : b_val(val) {}
        } thread_option_union;
        
        /** Defines the thread option flag structure allowing finer control of a thread object */
        typedef struct thread_flags {
            public:
                /** The default constructor */
                thread_flags() : m_stack(0), m_timeout(0), m_flags(0) { }
                
                /**
                 * The copy constructor
                 *
                 * @param cp    The other structure to copy
                 */
                thread_flags(const omni::sync::thread_flags &cp) :
                    m_stack(cp.m_stack),
                    m_timeout(cp.m_timeout),
                    m_flags(cp.m_flags)
                { }
                
                /**
                 * Stack size constructor; initializes the structure with specified stack size
                 * (specifically non-explicit constructor)
                 *
                 * @param stack    The stack size to set
                 */
                thread_flags(std::size_t stack) :
                    m_stack(stack),
                    m_timeout(0),
                    m_flags(0)
                { }
                
                /**
                 * Initializes the class with specified stack size and timeout
                 *
                 * @param stack    The stack size to set
                 * @param timeout The timeout on auto-join
                 */
                thread_flags(std::size_t stack, std::size_t timeout) :
                    m_stack(stack),
                    m_timeout(timeout),
                    m_flags(0)
                { }
                
                /**
                 * Initializes the class with specified stack size and timeout
                 *
                 * @param stack     The stack size to set
                 * @param timeout The timeout on auto-join
                 * @param flags     The flag bit mask to set
                 */
                thread_flags(std::size_t stack, std::size_t timeout, unsigned char flags) :
                    m_stack(stack),
                    m_timeout(timeout),
                    m_flags(flags)
                { }
                
                /**
                 * Initializes the class with specified stack size and timeout
                 *
                 * @param stack     The stack size to set
                 * @param timeout The timeout on auto-join
                 * @param flag     The flag bit to set
                 */
                thread_flags(std::size_t stack, std::size_t timeout, omni::sync::thread_option::enum_t flag) :
                    m_stack(stack),
                    m_timeout(timeout),
                    m_flags(0)
                {
                    this->set_flag(flag, true);
                }
                
                inline bool allow_reuse() const
                {
                    return OMNI_VAL_HAS_FLAG_BIT(this->m_flags, omni::sync::thread_option::ALLOW_THREAD_REUSE);
                }
                
                inline bool auto_join() const
                {
                    return OMNI_VAL_HAS_FLAG_BIT(this->m_flags, omni::sync::thread_option::AUTO_JOIN);
                }
                
                inline std::size_t auto_join_timeout() const
                {
                    return this->m_timeout;
                }
                
                inline bool abort_on_assign() const
                {
                    return OMNI_VAL_HAS_FLAG_BIT(this->m_flags, omni::sync::thread_option::ABORT_ON_ASSIGN);
                }
                
                inline bool abort_on_destroy() const
                {
                    return OMNI_VAL_HAS_FLAG_BIT(this->m_flags, omni::sync::thread_option::ABORT_ON_DESTROY);
                }
                
                inline bool detach_on_destroy() const
                {
                    return OMNI_VAL_HAS_FLAG_BIT(this->m_flags, omni::sync::thread_option::DETACH_ON_DESTROY);
                }
                
                inline bool detach_on_assign() const
                {
                    return OMNI_VAL_HAS_FLAG_BIT(this->m_flags, omni::sync::thread_option::DETACH_ON_ASSIGN);
                }
                
                inline bool kill_on_destroy() const
                {
                    return OMNI_VAL_HAS_FLAG_BIT(this->m_flags, omni::sync::thread_option::KILL_ON_DESTROY);
                }
                
                inline bool kill_on_assign() const
                {
                    return OMNI_VAL_HAS_FLAG_BIT(this->m_flags, omni::sync::thread_option::KILL_ON_ASSIGN);
                }
                
                void set_flag(omni::sync::thread_option::enum_t flag, bool val)
                {
                    switch (flag) {
                        case omni::sync::thread_option::ALLOW_THREAD_REUSE:
                            OMNI_VAL_SET_FLAG_BOOL(this->m_flags, omni::sync::thread_option::ALLOW_THREAD_REUSE, val);
                            break;
                        case omni::sync::thread_option::AUTO_JOIN:
                            OMNI_VAL_SET_FLAG_BOOL(this->m_flags, omni::sync::thread_option::AUTO_JOIN, val);
                            break;
                        case omni::sync::thread_option::DETACH_ON_DESTROY:
                            OMNI_VAL_SET_FLAG_BOOL(this->m_flags, omni::sync::thread_option::DETACH_ON_DESTROY, val);
                            break;
                        case omni::sync::thread_option::ABORT_ON_DESTROY:
                            OMNI_VAL_SET_FLAG_BOOL(this->m_flags, omni::sync::thread_option::ABORT_ON_DESTROY, val);
                            break;
                        case omni::sync::thread_option::KILL_ON_DESTROY:
                            OMNI_VAL_SET_FLAG_BOOL(this->m_flags, omni::sync::thread_option::KILL_ON_DESTROY, val);
                            break;
                        case omni::sync::thread_option::DETACH_ON_ASSIGN:
                            OMNI_VAL_SET_FLAG_BOOL(this->m_flags, omni::sync::thread_option::DETACH_ON_ASSIGN, val);
                            break;
                        case omni::sync::thread_option::ABORT_ON_ASSIGN:
                            OMNI_VAL_SET_FLAG_BOOL(this->m_flags, omni::sync::thread_option::ABORT_ON_ASSIGN, val);
                            break;
                        case omni::sync::thread_option::KILL_ON_ASSIGN:
                            OMNI_VAL_SET_FLAG_BOOL(this->m_flags, omni::sync::thread_option::KILL_ON_ASSIGN, val);
                            break;
                        case omni::sync::thread_option::STACK_SIZE:
                        case omni::sync::thread_option::AUTO_JOIN_TIMEOUT:
                        default:
                            OMNI_ERRV_FW("invalid option: ", flag, omni::invalid_thread_option(static_cast<std::size_t>(flag)))
                            break;
                    }
                }
                
                inline std::size_t stack_size() const
                {
                    return this->m_stack;
                }
                
                inline void set_auto_join_timeout(std::size_t timeout)
                {
                    this->m_timeout = timeout;
                }
                
                inline void set_stack_size(std::size_t stack)
                {
                    this->m_stack = stack;
                }
                
                /**
                 * Equality operator tests if objects are equal
                 *
                 * @param o     The other structure to test
                 */
                bool operator==(const omni::sync::thread_flags& o) const
                {
                    return
                    (this->m_stack == o.m_stack &&
                    this->m_timeout == o.m_timeout &&
                    this->m_flags == o.m_flags);
                }
                
                /**
                 * Assignment operator sets values from the other object
                 *
                 * @param o     The other structure to assign from
                 */
                omni::sync::thread_flags& operator=(const omni::sync::thread_flags& o)
                {
                    if (this != &o) {
                        this->m_stack = o.m_stack;
                        this->m_timeout = o.m_timeout;
                        this->m_flags = o.m_flags;
                    }
                    return *this;
                }
                
            private:
                /**
                 * The threads stack size. If the thread is in running state,
                 * the new stack size will not take effect until the next run.
                 */
                std::size_t m_stack;
                /**
                 * If timeout_on_eop is >0 and kill_on_eop has been set for a thread,
                 * when an external operation is being applied, the thread will attempt
                 * to abort and join for the specified timeout before killing the thread
                 */
                std::size_t m_timeout;
                /**
                 * The underlying bit mask for the flags of this structure. A bit
                 * mask on an unsigned char is used to conserve space instead of
                 * using 9 bool types, we use 1 char type, additionally, the checks
                 * for the various flags do not (should not) be called in any sort of loop.
                 */
                unsigned char m_flags;
        } thread_flags;
        
        // Types
        /** Defines the platform infinite time out value */
        const unsigned long INFINITE_TIMEOUT = OMNI_INFINITE_TIMEOUT;
        /** Defines the signature for a thread start delegate taking no arguments */
        typedef omni::delegate<void> thread_start;
        /** Defines the signature for a thread start delegate taking the default void* argument */
        typedef omni::delegate1<void, omni::generic_ptr> parameterized_thread_start;
        /** Defines the platform thread type */
        typedef OMNI_THREAD_T thread_t;
        /** Defines the platform thread handle type */
        typedef OMNI_THREAD_HANDLE_T thread_handle_t;
        /** Defines the platform thread function pointer type (void* / int, etc) */
        typedef OMNI_THREAD_FNPTR_T thread_fnptr_t;
        /** Defines the platform thread function return type */
        typedef OMNI_THREAD_RET_T thread_ret_t;
        /** Defines an alias to the priority enum type */
        typedef omni::sync::thread_priority::enum_t thread_priority_t;
        /** Defines an alias to the start_type enum type */
        typedef omni::sync::thread_start_type::enum_t thread_start_type_t;
        /** Defines an alias to the state enum type */
        typedef omni::sync::thread_state::enum_t thread_state_t;
        /** Defines an alias to the thread_option enum type */
        typedef omni::sync::thread_option::enum_t thread_option_t;
        /** An alias type to the omni::thread_option_union */
        typedef omni::sync::thread_option_union thread_union_t;
        
        #if defined(OMNI_THROW)
            extern omni::action unhandled_thread_exception;
            extern omni::event1<void, const @exception.html">omni::exception&> user_thread_exception;
        #endif
        
        /**
         * Blocks the calling thread until the thread passed in has finished
         * executing (by normal means or cancellation) or the specified timeout
         * has been reached, which ever happens first.
         *
         * @param timeout The timeout (in milliseconds) to wait for a thread to finish
         *
         * @return True if the thread has been joined successfully, false if the operation
         *         times out or there was an error
         */
        inline bool join_thread(omni::sync::thread_handle_t handle, unsigned long timeout)
        {
            if (handle == 0) {
                OMNI_ERR_RETV_FW(OMNI_INVALID_THREAD_HANDLE_STR, omni::invalid_thread_handle(), false)
            }
            #if defined(OMNI_OS_WIN)
                return (::WaitForSingleObject(OMNI_WIN_TOHNDL_FW(handle), timeout) == 0); // Returns 0 on success
            #else
                /* There is not a portable mechanism with pthreads to wait on a specific thread without
                implementing a timed_wait condition variable. We don't want the user to have to implement
                a seperate variable based on system, so we implement a 'timeout' loop*/
                if (timeout != omni::sync::INFINITE_TIMEOUT) {
                    omni::chrono::tick_t ts = omni::chrono::monotonic_tick();
                    OMNI_SLEEP_INIT();
                    volatile bool iav = true;
                    //iav = (::pthread_kill(handle, 0) != ESRCH); // == "alive"
                    while ((iav = (::pthread_kill(handle, 0) != ESRCH)) && (omni::chrono::elapsed_ms(ts) < timeout)) {
                        OMNI_SLEEP1();
                    }
                    return (::pthread_kill(handle, 0) == ESRCH); // == "dead"
                }
                return (::pthread_join(handle, NULL) == 0); // Returns 0 on success
            #endif
        }
        
        /**
         * Blocks the calling thread until the thread passed in has finished
         * executing (by normal means or cancellation).
         *
         * @return True on success, false otherwise
         */
        inline bool join_thread(omni::sync::thread_handle_t handle)
        {
            if (handle == 0) {
                OMNI_ERR_RETV_FW(OMNI_INVALID_THREAD_HANDLE_STR, omni::invalid_thread_handle(), false)
            }
            #if defined(OMNI_OS_WIN)
                return (::WaitForSingleObject(OMNI_WIN_TOHNDL_FW(handle), INFINITE) == 0); // Returns 0 on success
            #else
                return (::pthread_join(handle, NULL) == 0); // Returns 0 on success
            #endif
        }

    }
}

#endif // OMNI_THREAD_T_HPP