Skip to content

Commit 08cfbd0

Browse files
committed
Linux portability for BlockUtil and CoDispatch (#1)
1 parent e0d7d95 commit 08cfbd0

File tree

2 files changed

+75
-66
lines changed

2 files changed

+75
-66
lines changed

include/objc-helpers/BlockUtil.h

+38-30
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <type_traits>
1818
#include <cstdlib>
1919
#include <cassert>
20+
#include <cstddef>
21+
#include <utility>
2022

2123
#include <Block.h>
2224

@@ -531,45 +533,51 @@ namespace BlockUtil
531533
auto makeMutableBlock(Callable && callable) {
532534
return makeBlockHelper<true>(std::forward<Callable>(callable), (CallType *) nullptr);
533535
}
536+
537+
#if __has_feature(objc_arc)
534538

535-
/**
536-
Convert strong pointer to a weak pointer of the same type
537-
538-
Usage:
539-
@code
540-
[foo doBar:BlockWrapper([weakSelf = makeWeak(self)] () {
541-
542-
}];
543-
@endcode
544-
*/
545-
template<class T>
546-
auto makeWeak(T * __strong obj) -> T * __weak
547-
{ return obj; }
539+
/**
540+
Convert strong pointer to a weak pointer of the same type
541+
542+
Usage:
543+
@code
544+
[foo doBar:BlockWrapper([weakSelf = makeWeak(self)] () {
545+
546+
}];
547+
@endcode
548+
*/
549+
template<class T>
550+
auto makeWeak(T * __strong obj) -> T * __weak
551+
{ return obj; }
548552

549-
/**
550-
Convert weak pointer to a strong pointer of the same type
551-
552-
Usage:
553-
@code
554-
[foo doBar:BlockWrapper([weakSelf = makeWeak(self)] () {
555-
auto self = makeStrong(self);
556-
if (!self)
557-
return;
558-
}];
559-
@endcode
560-
*/
561-
template<class T>
562-
auto makeStrong(T * __weak obj) -> T * __strong
563-
{ return obj; }
553+
/**
554+
Convert weak pointer to a strong pointer of the same type
555+
556+
Usage:
557+
@code
558+
[foo doBar:BlockWrapper([weakSelf = makeWeak(self)] () {
559+
auto self = makeStrong(self);
560+
if (!self)
561+
return;
562+
}];
563+
@endcode
564+
*/
565+
template<class T>
566+
auto makeStrong(T * __weak obj) -> T * __strong
567+
{ return obj; }
568+
569+
#endif
564570

565571
}
566572
}
567573

568574
using BlockUtil::BlockWithCallable;
569575
using BlockUtil::makeBlock;
570576
using BlockUtil::makeMutableBlock;
571-
using BlockUtil::makeWeak;
572-
using BlockUtil::makeStrong;
577+
#if __has_feature(objc_arc)
578+
using BlockUtil::makeWeak;
579+
using BlockUtil::makeStrong;
580+
#endif
573581

574582

575583

include/objc-helpers/CoDispatch.h

+37-36
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <memory>
2525
#include <atomic>
2626
#include <cassert>
27+
#include <limits>
2728

2829
#include <dispatch/dispatch.h>
2930
#ifndef __OBJC__
@@ -71,8 +72,8 @@ inline namespace CO_DISPATCH_NS {
7172
This is a very simple intrusive refcounting smart pointer to avoid pulling some external library in
7273
*/
7374

74-
template<class T> struct Ref { T * __nullable ptr; };
75-
template<class T> struct Noref { T * __nullable ptr; };
75+
template<class T> struct Ref { T * _Nullable ptr; };
76+
template<class T> struct Noref { T * _Nullable ptr; };
7677

7778
template<class T>
7879
class [[clang::trivial_abi]] RefcntPtr {
@@ -107,23 +108,23 @@ inline namespace CO_DISPATCH_NS {
107108
m_ptr = nullptr;
108109
}
109110

110-
auto operator->() const noexcept -> T * __nullable
111+
auto operator->() const noexcept -> T * _Nullable
111112
{ return m_ptr; }
112113
auto operator*() const noexcept -> T &
113114
{ return *m_ptr; }
114-
auto get() const noexcept -> T * __nullable
115+
auto get() const noexcept -> T * _Nullable
115116
{ return m_ptr; }
116117
operator bool() const noexcept
117118
{ return m_ptr != nullptr; }
118119
private:
119-
T * __nullable m_ptr;
120+
T * _Nullable m_ptr;
120121
};
121122

122123
template<class T>
123-
auto ref(T * __nullable ptr) noexcept
124+
auto ref(T * _Nullable ptr) noexcept
124125
{ return RefcntPtr{Ref<T>{ptr}}; }
125126
template<class T>
126-
auto noref(T * __nullable ptr) noexcept
127+
auto noref(T * _Nullable ptr) noexcept
127128
{ return RefcntPtr{Noref<T>{ptr}}; }
128129

129130
//MARK: - Dispatch object holders
@@ -132,7 +133,7 @@ inline namespace CO_DISPATCH_NS {
132133

133134
#if OS_OBJECT_USE_OBJC
134135
template<class D>
135-
using DispatchHolder = D __nullable;
136+
using DispatchHolder = D _Nullable;
136137

137138
#else
138139
template<class D>
@@ -383,7 +384,7 @@ inline namespace CO_DISPATCH_NS {
383384
/**
384385
Resumes execution for generators or coroutines that start suspended
385386
*/
386-
auto resumeExecution(dispatch_queue_t __nullable queue) noexcept {
387+
auto resumeExecution(dispatch_queue_t _Nullable queue) noexcept {
387388
m_value.clear();
388389
m_awaiterOnResumeQueue = false;
389390
[[maybe_unused]] auto oldstate = m_state.exchange(s_runningMarker, std::memory_order_acq_rel);
@@ -467,7 +468,7 @@ inline namespace CO_DISPATCH_NS {
467468
/**
468469
Specify a queue on which resume client
469470
*/
470-
void setResumeQueue(dispatch_queue_t __nullable queue, dispatch_time_t when) noexcept {
471+
void setResumeQueue(dispatch_queue_t _Nullable queue, dispatch_time_t when) noexcept {
471472
m_resumeQueue = queue;
472473
m_when = when;
473474
}
@@ -510,14 +511,14 @@ inline namespace CO_DISPATCH_NS {
510511
//the only way to optimize unnecessary dispatches.
511512
//Setting the key is probably not cheap but likely much cheaper than suspending and
512513
//scheduling dispatch when none is needed.
513-
auto isCurrentQueue(dispatch_queue_t __nonnull queue) const {
514+
auto isCurrentQueue(dispatch_queue_t _Nonnull queue) const {
514515
dispatch_queue_set_specific(queue, this, const_cast<BasicPromise *>(this), nullptr);
515516
bool ret = (dispatch_get_specific(this) == this);
516517
dispatch_queue_set_specific(queue, this, nullptr, nullptr);
517518
return ret;
518519
}
519520

520-
void resumeHandleAsync(void * __nonnull handleAddr) {
521+
void resumeHandleAsync(void * _Nonnull handleAddr) {
521522

522523
auto resumer = [](void * addr) {
523524
std::coroutine_handle<>::from_address(addr).resume();
@@ -544,7 +545,7 @@ inline namespace CO_DISPATCH_NS {
544545

545546
template<class Promise>
546547
struct PromiseClientAbandoner {
547-
void operator()(Promise * __nonnull ptr) const noexcept
548+
void operator()(Promise * _Nonnull ptr) const noexcept
548549
{ ptr->clientAbandon(); }
549550
};
550551
template<class Promise>
@@ -633,21 +634,21 @@ inline namespace CO_DISPATCH_NS {
633634
#ifndef __OBJC__
634635
template<class Ret>
635636
struct StateForFunc<Ret (^)()> : State {
636-
StateForFunc(Ret (^ __nonnull block)()) noexcept:
637+
StateForFunc(Ret (^ _Nonnull block)()) noexcept:
637638
func(Block_copy(block))
638639
{}
639640
~StateForFunc() noexcept
640641
{ Block_release(func); }
641642
StateForFunc(StateForFunc &&) = delete;
642643
StateForFunc(const StateForFunc &) = delete;
643644

644-
Ret (^ __nonnull func)();
645+
Ret (^ _Nonnull func)();
645646
};
646647
#endif
647648
public:
648649
class Promise {
649650
public:
650-
Promise(State * __nonnull state):
651+
Promise(State * _Nonnull state):
651652
m_sharedState(noref(state))
652653
{}
653654

@@ -687,7 +688,7 @@ inline namespace CO_DISPATCH_NS {
687688
return awaiter{std::move(m_sharedState)};
688689
}
689690

690-
auto resumeOn(dispatch_queue_t __nullable queue,
691+
auto resumeOn(dispatch_queue_t _Nullable queue,
691692
dispatch_time_t when = DISPATCH_TIME_NOW) && noexcept -> DispatchAwaitable && {
692693
m_sharedState->setResumeQueue(queue, when);
693694
return std::move(*this);
@@ -697,7 +698,7 @@ inline namespace CO_DISPATCH_NS {
697698

698699
template<class Func>
699700
requires(std::is_invocable_v<FunctionFromReference<Func>>)
700-
static auto invokeOnQueue(dispatch_queue_t __nonnull queue, Func && func) -> DispatchAwaitable {
701+
static auto invokeOnQueue(dispatch_queue_t _Nonnull queue, Func && func) -> DispatchAwaitable {
701702
auto * state = new StateForFunc<FunctionFromReference<Func>>(std::forward<Func>(func));
702703
dispatch_async_f(queue, state, DispatchAwaitable::invokeFromState<Func>);
703704
return DispatchAwaitable(state);
@@ -722,13 +723,13 @@ inline namespace CO_DISPATCH_NS {
722723
}
723724

724725
private:
725-
DispatchAwaitable(State * __nonnull state) noexcept :
726+
DispatchAwaitable(State * _Nonnull state) noexcept :
726727
m_sharedState(state)
727728
{}
728729

729730
template<class Func>
730731
requires(std::is_invocable_v<FunctionFromReference<Func>>)
731-
static void invokeFromState(void * __nonnull ptr) noexcept {
732+
static void invokeFromState(void * _Nonnull ptr) noexcept {
732733
auto * state = static_cast<StateForFunc<FunctionFromReference<Func>> *>(ptr);
733734
Promise promise(state);
734735
#ifdef __cpp_exceptions
@@ -805,7 +806,7 @@ inline namespace CO_DISPATCH_NS {
805806
*/
806807
template<class Func>
807808
requires(std::is_invocable_v<Func>)
808-
auto co_dispatch(dispatch_queue_t __nonnull queue, Func && func) {
809+
auto co_dispatch(dispatch_queue_t _Nonnull queue, Func && func) {
809810
return DispatchAwaitableFor<Func>::invokeOnQueue(queue, std::forward<Func>(func));
810811
}
811812

@@ -891,15 +892,15 @@ inline namespace CO_DISPATCH_NS {
891892
}
892893

893894

894-
auto resumeOn(dispatch_queue_t __nullable queue, dispatch_time_t when = DISPATCH_TIME_NOW) && noexcept -> DispatchTask && {
895+
auto resumeOn(dispatch_queue_t _Nullable queue, dispatch_time_t when = DISPATCH_TIME_NOW) && noexcept -> DispatchTask && {
895896
m_promise->setResumeQueue(queue, when);
896897
return std::move(*this);
897898
}
898899
auto resumeOnMainQueue(dispatch_time_t when = DISPATCH_TIME_NOW) && noexcept -> DispatchTask &&
899900
{ return std::move(*this).resumeOn(dispatch_get_main_queue(), when); }
900901

901902
private:
902-
DispatchTask(Promise * __nonnull promise) noexcept :
903+
DispatchTask(Promise * _Nonnull promise) noexcept :
903904
m_promise(promise)
904905
{}
905906

@@ -995,13 +996,13 @@ inline namespace CO_DISPATCH_NS {
995996
};
996997
struct NextAwaitable {
997998
Util::ClientAbandonPtr<Promise> promise;
998-
Iterator * __nonnull it;
999+
Iterator * _Nonnull it;
9991000

10001001
void operator co_await() & = delete;
10011002
void operator co_await() const & = delete;
10021003
auto operator co_await() && noexcept {
10031004
struct awaiter : AwaiterBase {
1004-
Iterator * __nonnull it;
1005+
Iterator * _Nonnull it;
10051006
void await_resume() noexcept(noexcept(it->m_promise->getValueToken())) {
10061007
it->m_promise = std::move(AwaiterBase::promise);
10071008
it->m_valueToken = it->m_promise->getValueToken();
@@ -1024,7 +1025,7 @@ inline namespace CO_DISPATCH_NS {
10241025
return m_valueToken;
10251026
}
10261027
private:
1027-
Iterator(Util::ClientAbandonPtr<Promise> && promise, dispatch_queue_t __nullable queue, DelayedValue::ValueToken valueToken):
1028+
Iterator(Util::ClientAbandonPtr<Promise> && promise, dispatch_queue_t _Nullable queue, DelayedValue::ValueToken valueToken):
10281029
m_promise(std::move(promise)),
10291030
m_queue(queue),
10301031
m_valueToken(valueToken)
@@ -1035,7 +1036,7 @@ inline namespace CO_DISPATCH_NS {
10351036
DelayedValue::ValueToken m_valueToken;
10361037
};
10371038

1038-
auto beginOn(dispatch_queue_t __nullable queue) && noexcept {
1039+
auto beginOn(dispatch_queue_t _Nullable queue) && noexcept {
10391040
m_promise->resumeExecution(queue);
10401041
return typename Iterator::FirstAwaitable{{std::move(m_promise)}, Util::QueueHolder{queue}};
10411042
}
@@ -1046,15 +1047,15 @@ inline namespace CO_DISPATCH_NS {
10461047
auto beginSync() && noexcept
10471048
{ return std::move(*this).beginOn(nullptr); }
10481049

1049-
auto resumingOn(dispatch_queue_t __nullable queue) && noexcept -> DispatchGenerator && {
1050+
auto resumingOn(dispatch_queue_t _Nullable queue) && noexcept -> DispatchGenerator && {
10501051
m_promise->setResumeQueue(queue, DISPATCH_TIME_NOW);
10511052
return std::move(*this);
10521053
}
10531054
auto resumingOnMainQueue() && noexcept -> DispatchGenerator &&
10541055
{ return std::move(*this).resumingOn(dispatch_get_main_queue()); }
10551056

10561057
private:
1057-
DispatchGenerator(Promise * __nonnull promise) noexcept :
1058+
DispatchGenerator(Promise * _Nonnull promise) noexcept :
10581059
m_promise(promise)
10591060
{}
10601061

@@ -1071,7 +1072,7 @@ inline namespace CO_DISPATCH_NS {
10711072
If you pass your current queue and non default `when` this is equivalent to an asynchronous sleep
10721073
until `when` - now.
10731074
*/
1074-
inline auto resumeOn(dispatch_queue_t __nonnull queue, dispatch_time_t when = DISPATCH_TIME_NOW) noexcept {
1075+
inline auto resumeOn(dispatch_queue_t _Nonnull queue, dispatch_time_t when = DISPATCH_TIME_NOW) noexcept {
10751076
struct Awaitable
10761077
{
10771078
dispatch_queue_t queue;
@@ -1115,7 +1116,7 @@ inline namespace CO_DISPATCH_NS {
11151116
struct DispatchIOResult {
11161117
DispatchIOResult() noexcept = default;
11171118

1118-
DispatchIOResult(dispatch_data_t __nullable data, int error) noexcept:
1119+
DispatchIOResult(dispatch_data_t _Nullable data, int error) noexcept:
11191120
m_data(data),
11201121
m_error(error)
11211122
{}
@@ -1126,7 +1127,7 @@ inline namespace CO_DISPATCH_NS {
11261127
For reads this is the data read. For writes the data that could not be written.
11271128
Can be nullptr
11281129
*/
1129-
auto data() const noexcept -> dispatch_data_t __nullable
1130+
auto data() const noexcept -> dispatch_data_t _Nullable
11301131
{ return m_data; }
11311132
/**
11321133
This value is 0 if the data was read/written successfully. If an error occurred, it contains the error number.
@@ -1146,7 +1147,7 @@ inline namespace CO_DISPATCH_NS {
11461147
want to monitor the operation progress. The final result is returned as coroutine result.
11471148
@return DispatchIOResult object with operation result
11481149
*/
1149-
inline auto co_dispatch_io_read(dispatch_io_t __nonnull channel, off_t offset, size_t length, dispatch_queue_t __nonnull queue, dispatch_io_handler_t __nullable progressHandler = nullptr) {
1150+
inline auto co_dispatch_io_read(dispatch_io_t _Nonnull channel, off_t offset, size_t length, dispatch_queue_t _Nonnull queue, dispatch_io_handler_t _Nullable progressHandler = nullptr) {
11501151
return makeAwaitable<DispatchIOResult, SupportsExceptions::No>([channel, offset, length, queue, progressHandler](auto promise) {
11511152
dispatch_io_read(channel, offset, length, queue, ^ (bool done, dispatch_data_t data, int error){
11521153
if (progressHandler)
@@ -1163,7 +1164,7 @@ inline namespace CO_DISPATCH_NS {
11631164
11641165
@return DispatchIOResult object with operation result
11651166
*/
1166-
inline auto co_dispatch_read(dispatch_fd_t fd, size_t length, dispatch_queue_t __nonnull queue) {
1167+
inline auto co_dispatch_read(dispatch_fd_t fd, size_t length, dispatch_queue_t _Nonnull queue) {
11671168
return makeAwaitable<DispatchIOResult, SupportsExceptions::No>([fd, length, queue](auto promise) {
11681169
dispatch_read(fd, length, queue, ^ (dispatch_data_t data, int error) {
11691170
promise.success(data, error);
@@ -1180,7 +1181,7 @@ inline namespace CO_DISPATCH_NS {
11801181
11811182
@return DispatchIOResult object with operation result
11821183
*/
1183-
inline auto co_dispatch_io_write(dispatch_io_t __nonnull channel, off_t offset, dispatch_data_t __nonnull data, dispatch_queue_t __nonnull queue, dispatch_io_handler_t __nullable progressHandler = nullptr) {
1184+
inline auto co_dispatch_io_write(dispatch_io_t _Nonnull channel, off_t offset, dispatch_data_t _Nonnull data, dispatch_queue_t _Nonnull queue, dispatch_io_handler_t _Nullable progressHandler = nullptr) {
11841185
return makeAwaitable<DispatchIOResult, SupportsExceptions::No>([channel, offset, data, queue, progressHandler](auto promise) {
11851186
dispatch_io_write(channel, offset, data, queue, ^ (bool done, dispatch_data_t dataRemaining, int error){
11861187
if (progressHandler)
@@ -1197,7 +1198,7 @@ inline namespace CO_DISPATCH_NS {
11971198
11981199
@return DispatchIOResult object with operation result
11991200
*/
1200-
inline auto co_dispatch_write(dispatch_fd_t fd, dispatch_data_t __nonnull data, dispatch_queue_t __nonnull queue) {
1201+
inline auto co_dispatch_write(dispatch_fd_t fd, dispatch_data_t _Nonnull data, dispatch_queue_t _Nonnull queue) {
12011202
return makeAwaitable<DispatchIOResult, SupportsExceptions::No>([fd, data, queue](auto promise) {
12021203
dispatch_write(fd, data, queue, ^ (dispatch_data_t dataRemaining, int error) {
12031204
promise.success(dataRemaining, error);

0 commit comments

Comments
 (0)