2 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 // dispatch - libdispatch wrapper
28 #include <security_utilities/errors.h>
33 ExceptionAwareEnqueuing::ExceptionAwareEnqueuing()
34 : mExceptionPending(false)
37 void ExceptionAwareEnqueuing::enqueueWithDispatcher(void (^dispatcher
)(dispatch_block_t
), dispatch_block_t block
)
39 if (mExceptionPending
)
43 if (mExceptionPending
)
48 StLock
<Mutex
> _(mLock
);
49 mExceptionPending
= true;
50 mException
= std::current_exception();
55 void ExceptionAwareEnqueuing::throwPendingException()
57 if (mExceptionPending
) {
58 mExceptionPending
= false;
59 std::rethrow_exception(mException
);
65 Queue::Queue(const char *label
, bool concurrent
, dispatch_qos_class_t qos_class
)
67 dispatch_queue_attr_t attr
= concurrent
? DISPATCH_QUEUE_CONCURRENT
: DISPATCH_QUEUE_SERIAL
;
68 attr
= dispatch_queue_attr_make_with_qos_class(attr
, qos_class
, 0);
69 mQueue
= dispatch_queue_create(label
, attr
);
74 dispatch_barrier_sync(mQueue
, ^{});
75 dispatch_release(mQueue
);
78 void Queue::enqueue(dispatch_block_t block
)
80 enqueuing
.enqueueWithDispatcher(^(dispatch_block_t block
){ dispatch_async(mQueue
, block
); }, block
);
85 dispatch_barrier_sync(mQueue
, ^{});
86 enqueuing
.throwPendingException();
93 mGroup
= dispatch_group_create();
98 dispatch_group_wait(mGroup
, DISPATCH_TIME_FOREVER
);
99 dispatch_release(mGroup
);
102 void Group::enqueue(dispatch_queue_t queue
, dispatch_block_t block
)
104 enqueuing
.enqueueWithDispatcher(^(dispatch_block_t block
){ dispatch_group_async(mGroup
, queue
, block
); }, block
);
109 dispatch_group_wait(mGroup
, DISPATCH_TIME_FOREVER
);
110 enqueuing
.throwPendingException();
115 Semaphore::Semaphore(long count
) {
116 mSemaphore
= dispatch_semaphore_create(count
);
119 Semaphore::Semaphore(Semaphore
& semaphore
)
120 : mSemaphore(semaphore
.mSemaphore
)
122 dispatch_retain(mSemaphore
);
125 Semaphore::~Semaphore() {
126 dispatch_release(mSemaphore
);
129 bool Semaphore::signal() {
130 return dispatch_semaphore_signal(mSemaphore
) == 0;
133 bool Semaphore::wait(dispatch_time_t timeout
) {
134 return dispatch_semaphore_wait(mSemaphore
, timeout
) == 0;
138 // Transfer ownership of held resource.
139 SemaphoreWait::SemaphoreWait(SemaphoreWait
&originalWait
)
140 : mSemaphore(originalWait
.mSemaphore
), mAcquired(originalWait
.mAcquired
)
142 originalWait
.mAcquired
= false;
145 SemaphoreWait::SemaphoreWait(Semaphore
&semaphore
, dispatch_time_t timeout
)
146 : mSemaphore(semaphore
)
148 mAcquired
= mSemaphore
.wait(timeout
);
151 SemaphoreWait::~SemaphoreWait()
158 } // end namespace Dispatch
159 } // end namespace Security