Overview
Comment: | OFCondition: Support waiting for Exec Signals |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
92d63d636786258a1e0f1eef9553a1c8 |
User & Date: | js on 2019-09-01 13:49:06 |
Other Links: | manifest | tags |
Context
2019-09-01
| ||
15:09 | OFRunLoop: Add support for Exec Signals check-in: 816a96ff90 user: js tags: trunk | |
13:49 | OFCondition: Support waiting for Exec Signals check-in: 92d63d6367 user: js tags: trunk | |
12:50 | {condition,mutex,thread}.m: Set errno on error check-in: d7fd999fee user: js tags: trunk | |
Changes
Modified src/OFCondition.h from [d32472266f] to [71a90ae1ff].
︙ | ︙ | |||
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | * @ref broadcast. * * @note Waiting might have been interrupted by a signal. It is thus recommended * to check the condition again after @ref wait returned! */ - (void)wait; /*! * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast or the timeout is reached. * * @note Waiting might have been interrupted by a signal. It is thus recommended * to check the condition again after @ref waitForTimeInterval: returned! * * @param timeInterval The time interval until the timeout is reached * @return Whether the condition has been signaled */ - (bool)waitForTimeInterval: (of_time_interval_t)timeInterval; /*! * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast or the timeout is reached. * * @note Waiting might have been interrupted by a signal. It is thus recommended * to check the condition again after @ref waitUntilDate: returned! * * @param date The date at which the timeout is reached * @return Whether the condition has been signaled */ - (bool)waitUntilDate: (OFDate *)date; /*! * @brief Signals the next waiting thread to continue. */ - (void)signal; /*! * @brief Signals all threads to continue. */ - (void)broadcast; @end OF_ASSUME_NONNULL_END | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 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 | * @ref broadcast. * * @note Waiting might have been interrupted by a signal. It is thus recommended * to check the condition again after @ref wait returned! */ - (void)wait; #ifdef OF_AMIGAOS /*! * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast or an Exec Signal is received. * * @note This is only available on AmigaOS! * * @param signalMask A pointer to a signal mask of Exec Signals to receive. * This is modified and set to the mask of signals received. */ - (void)waitForConditionOrExecSignal: (ULONG *)signalMask; #endif /*! * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast or the timeout is reached. * * @note Waiting might have been interrupted by a signal. It is thus recommended * to check the condition again after @ref waitForTimeInterval: returned! * * @param timeInterval The time interval until the timeout is reached * @return Whether the condition has been signaled */ - (bool)waitForTimeInterval: (of_time_interval_t)timeInterval; #ifdef OF_AMIGAOS /*! * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast, the timeout is reached or an Exec Signal is received. * * @note This is only available on AmigaOS! * * @param timeInterval The time interval until the timeout is reached * @param signalMask A pointer to a signal mask of Exec Signals to receive. * This is modified and set to the mask of signals received. * @return Whether the condition has been signaled or a signal received */ - (bool)waitForTimeInterval: (of_time_interval_t)timeInterval orExecSignal: (ULONG *)signalMask; #endif /*! * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast or the timeout is reached. * * @note Waiting might have been interrupted by a signal. It is thus recommended * to check the condition again after @ref waitUntilDate: returned! * * @param date The date at which the timeout is reached * @return Whether the condition has been signaled */ - (bool)waitUntilDate: (OFDate *)date; #ifdef OF_AMIGAOS /*! * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast, the timeout is reached or an Exec Signal is received. * * @note This is only available on AmigaOS! * * @param date The date at which the timeout is reached * @param signalMask A pointer to a signal mask of Exec Signals to receive. * This is modified and set to the mask of signals received. * @return Whether the condition has been signaled or a signal received */ - (bool)waitUntilDate: (OFDate *)date orExecSignal: (ULONG *)signalMask; #endif /*! * @brief Signals the next waiting thread to continue. */ - (void)signal; /*! * @brief Signals all threads to continue. */ - (void)broadcast; @end OF_ASSUME_NONNULL_END |
Modified src/OFCondition.m from [f1fb27ae31] to [1f945c9c3c].
︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | - (void)wait { if (!of_condition_wait(&_condition, &_mutex)) @throw [OFConditionWaitFailedException exceptionWithCondition: self errNo: errno]; } - (bool)waitForTimeInterval: (of_time_interval_t)timeInterval { if (!of_condition_timed_wait(&_condition, &_mutex, timeInterval)) { if (errno == ETIMEDOUT) return false; else @throw [OFConditionWaitFailedException exceptionWithCondition: self errNo: errno]; } return true; } - (bool)waitUntilDate: (OFDate *)date { return [self waitForTimeInterval: date.timeIntervalSinceNow]; } - (void)signal { if (!of_condition_signal(&_condition)) @throw [OFConditionSignalFailedException exceptionWithCondition: self errNo: errno]; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 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 | - (void)wait { if (!of_condition_wait(&_condition, &_mutex)) @throw [OFConditionWaitFailedException exceptionWithCondition: self errNo: errno]; } #ifdef OF_AMIGAOS - (void)waitForConditionOrExecSignal: (ULONG *)signalMask { if (!of_condition_wait_or_signal(&_condition, &_mutex, signalMask)) @throw [OFConditionWaitFailedException exceptionWithCondition: self errNo: errno]; } #endif - (bool)waitForTimeInterval: (of_time_interval_t)timeInterval { if (!of_condition_timed_wait(&_condition, &_mutex, timeInterval)) { if (errno == ETIMEDOUT) return false; else @throw [OFConditionWaitFailedException exceptionWithCondition: self errNo: errno]; } return true; } #ifdef OF_AMIGAOS - (bool)waitForTimeInterval: (of_time_interval_t)timeInterval orExecSignal: (ULONG *)signalMask { if (!of_condition_timed_wait_or_signal(&_condition, &_mutex, timeInterval, signalMask)) { if (errno == ETIMEDOUT) return false; else @throw [OFConditionWaitFailedException exceptionWithCondition: self errNo: errno]; } return true; } #endif - (bool)waitUntilDate: (OFDate *)date { return [self waitForTimeInterval: date.timeIntervalSinceNow]; } #ifdef OF_AMIGAOS - (bool)waitUntilDate: (OFDate *)date orExecSignal: (ULONG *)signalMask { return [self waitForTimeInterval: date.timeIntervalSinceNow orExecSignal: signalMask]; } #endif - (void)signal { if (!of_condition_signal(&_condition)) @throw [OFConditionSignalFailedException exceptionWithCondition: self errNo: errno]; |
︙ | ︙ |
Modified src/condition.h from [e69c1f857d] to [788d08f5c1].
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | struct Task *task; uint8_t sigBit; struct of_condition_waiting_task *next; } *waitingTasks; } of_condition_t; #endif #ifdef __cplusplus extern "C" { #endif extern bool of_condition_new(of_condition_t *condition); extern bool of_condition_signal(of_condition_t *condition); extern bool of_condition_broadcast(of_condition_t *condition); extern bool of_condition_wait(of_condition_t *condition, of_mutex_t *mutex); extern bool of_condition_timed_wait(of_condition_t *condition, of_mutex_t *mutex, of_time_interval_t timeout); extern bool of_condition_free(of_condition_t *condition); #ifdef __cplusplus } #endif | > > > > > > > > > > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | struct Task *task; uint8_t sigBit; struct of_condition_waiting_task *next; } *waitingTasks; } of_condition_t; #endif OF_ASSUME_NONNULL_BEGIN #ifdef __cplusplus extern "C" { #endif extern bool of_condition_new(of_condition_t *condition); extern bool of_condition_signal(of_condition_t *condition); extern bool of_condition_broadcast(of_condition_t *condition); extern bool of_condition_wait(of_condition_t *condition, of_mutex_t *mutex); extern bool of_condition_timed_wait(of_condition_t *condition, of_mutex_t *mutex, of_time_interval_t timeout); #ifdef OF_AMIGAOS extern bool of_condition_wait_or_signal(of_condition_t *condition, of_mutex_t *mutex, ULONG *signalMask); extern bool of_condition_timed_wait_or_signal(of_condition_t *condition, of_mutex_t *mutex, of_time_interval_t timeout, ULONG *signalMask); #endif extern bool of_condition_free(of_condition_t *condition); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END |
Modified src/condition_amiga.m from [e20e2745b3] to [b2efd3b8bd].
︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | } return true; } bool of_condition_wait(of_condition_t *condition, of_mutex_t *mutex) { struct of_condition_waiting_task waitingTask = { .task = FindTask(NULL), .sigBit = AllocSignal(-1) }; bool ret; if (waitingTask.sigBit == -1) { errno = EAGAIN; return false; } Forbid(); if (!of_mutex_unlock(mutex)) { FreeSignal(waitingTask.sigBit); return false; } waitingTask.next = condition->waitingTasks; condition->waitingTasks = &waitingTask; | > > > > > > > > > > | < > | > > > > > > > > > > > > > > > > > > > > > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 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 | } return true; } bool of_condition_wait(of_condition_t *condition, of_mutex_t *mutex) { ULONG signalMask = 0; return of_condition_wait_or_signal(condition, mutex, &signalMask); } bool of_condition_wait_or_signal(of_condition_t *condition, of_mutex_t *mutex, ULONG *signalMask) { struct of_condition_waiting_task waitingTask = { .task = FindTask(NULL), .sigBit = AllocSignal(-1) }; bool ret; ULONG mask; if (waitingTask.sigBit == -1) { errno = EAGAIN; return false; } Forbid(); if (!of_mutex_unlock(mutex)) { FreeSignal(waitingTask.sigBit); return false; } waitingTask.next = condition->waitingTasks; condition->waitingTasks = &waitingTask; mask = Wait((1ul << waitingTask.sigBit) | *signalMask); if (mask & (1ul << waitingTask.sigBit)) ret = of_mutex_lock(mutex); else if (*signalMask &= mask) ret = true; else { /* * This should not happen - it means something interrupted the * Wait(), so the best we can do is return EINTR. */ ret = false; errno = EINTR; } FreeSignal(waitingTask.sigBit); Permit(); return ret; } bool of_condition_timed_wait(of_condition_t *condition, of_mutex_t *mutex, of_time_interval_t timeout) { ULONG signalMask = 0; return of_condition_timed_wait_or_signal(condition, mutex, timeout, &signalMask); } bool of_condition_timed_wait_or_signal(of_condition_t *condition, of_mutex_t *mutex, of_time_interval_t timeout, ULONG *signalMask) { struct of_condition_waiting_task waitingTask = { .task = FindTask(NULL), .sigBit = AllocSignal(-1) }; struct MsgPort port = { .mp_Node = { .ln_Type = NT_MSGPORT |
︙ | ︙ | |||
173 174 175 176 177 178 179 | } waitingTask.next = condition->waitingTasks; condition->waitingTasks = &waitingTask; SendIO((struct IORequest *)&request); | | > > > | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | } waitingTask.next = condition->waitingTasks; condition->waitingTasks = &waitingTask; SendIO((struct IORequest *)&request); mask = Wait((1ul << waitingTask.sigBit) | (1ul << port.mp_SigBit) | *signalMask); if (mask & (1ul << waitingTask.sigBit)) ret = of_mutex_lock(mutex); else if (mask & (1ul << port.mp_SigBit)) { ret = false; errno = ETIMEDOUT; } else if (*signalMask &= mask) ret = true; else { /* * This should not happen - it means something interrupted the * Wait(), so the best we can do is return EINTR. */ ret = false; errno = EINTR; } |
︙ | ︙ |