1 /* 2 * Copyright (c) 2005, Eric Crahen 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is furnished 9 * to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in all 12 * copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 * 21 */ 22 23 #ifndef __ZTBLOCKINGSTATE_H__ 24 #define __ZTBLOCKINGSTATE_H__ 25 26 #include <assert.h> 27 28 namespace ZThread { 29 30 /** 31 * @class Status 32 * @version 2.3.0 33 * 34 * A Status is associated with each Thread's Monitor. Monitors rely on a 35 * Status object for providing information that will affect a blocking operations. 36 */ 37 class Status { 38 public: 39 //! Aggregate of pending status changes 40 volatile unsigned short _pending; 41 42 //! Interest mask 43 volatile unsigned short _mask; 44 45 public: 46 47 //! State for the monitor 48 typedef enum { 49 50 // Default 51 INVALID = 0x00, 52 53 // Valid states 54 SIGNALED = 0x01, 55 INTERRUPTED = 0x02, 56 TIMEDOUT = 0x04, 57 CANCELED = 0x08, 58 59 // Mask 60 ANYTHING = (~INVALID & ~CANCELED) 61 62 } STATE; 63 Status()64 Status() : _pending(INVALID), _mask(ANYTHING) { } 65 66 /** 67 * Set the mask for the STATE's that next() will report. 68 * STATE's not covered by the interest mask can still be 69 * set, they just aren't reported until the mask is changed 70 * to cover that STATE. 71 * 72 * @param STATE 73 * @pre accessed ONLY by the owning thread. 74 */ interest(STATE mask)75 void interest(STATE mask) { 76 _mask = static_cast<unsigned short>(mask); 77 } 78 masked(STATE mask)79 bool masked(STATE mask) { 80 return (_mask & static_cast<unsigned short>(mask)) == 0; 81 } 82 83 /** 84 * Return true if next() will return a STATE covered 85 * by the current interest mask and by the mask given 86 * to this function. 87 * 88 * @param unsigned short 89 * @pre accessed ONLY by the owning thread. 90 */ pending(unsigned short mask)91 bool pending(unsigned short mask) { 92 93 assert(mask != INVALID); 94 return ((_pending & _mask) & mask) != INVALID; 95 96 } 97 98 /** 99 * Check the state without the interest mask. 100 * 101 * @param state 102 * @return true if the flag is set 103 * @pre access must be serial 104 */ examine(STATE state)105 bool examine(STATE state) { 106 return (_pending & static_cast<unsigned short>(state)) != INVALID; 107 } 108 109 /** 110 * Add the flags to the current state. 111 * 112 * @param interest - the flags to add to the current state. 113 * @pre access must be serial 114 */ push(STATE interest)115 void push(STATE interest) { 116 _pending |= interest; 117 } 118 119 /** 120 * Clear the flags from the current state 121 * 122 * @param interest - the flags to clear from the current state. 123 * @pre access must be serial 124 */ clear(STATE interest)125 void clear(STATE interest) { 126 127 assert(interest != INVALID); 128 assert(interest != ANYTHING); 129 assert(interest != CANCELED); 130 131 _pending &= ~interest; 132 133 } 134 135 /** 136 * Get the next state from set that has accumulated. The order STATES are 137 * reported in is SIGNALED, TIMEOUT, or INTERRUPTED. Setting the 138 * intrest mask allows certain state to be selectively ignored for 139 * a time - but not lost. The states will become visible again as soon 140 * as the interest mask is changed appropriately. The interest mask is 141 * generally used to create uninterruptable waits (waiting for threads 142 * to start, reacquiring a conditions predicate lock, etc) 143 * 144 * @return STATE 145 * @pre access must be serial 146 */ next()147 STATE next() { 148 149 STATE state = INVALID; 150 151 if(((_pending & _mask) & SIGNALED) != 0) { 152 153 // Absorb the timeout if it happens when a signal 154 // is available at the same time 155 _pending &= ~(SIGNALED|TIMEDOUT); 156 state = SIGNALED; 157 158 } else if(((_pending & _mask) & TIMEDOUT) != 0) { 159 160 _pending &= ~TIMEDOUT; 161 state = TIMEDOUT; 162 163 } else if(((_pending & _mask) & INTERRUPTED) != 0) { 164 165 _pending &= ~INTERRUPTED; 166 state = INTERRUPTED; 167 168 } 169 170 assert(state != INVALID); 171 return state; 172 173 } 174 175 }; 176 177 }; // namespace ZThread 178 179 #endif 180