Skip to content

Commit

Permalink
WorkQueue should inherit from SerialFunctionDispatcher
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=260779
rdar://114535523

Reviewed by Kimmo Kinnunen.

Make WorkQueue inherit from SerialFunctionDispatcher so that it can be
used similarly to RunLoop and WorkerOrWorkletThread.

Needed for this change to compile:
- Export the whole class to get the multiple inheritance to
  work across binaries.
- When exporting WorkQueue, it will export function with OSObjectPtr<dispatch_queue_t>.
  This has different type in Obj-C and in C++. If the type is used in both,
  then there will be unresolved symbol since C++ type is used when creating
  the library (WorkQueue.cpp), as such remove method prototype from WorkQueue
  and have a single WorkQueue constructor taking an enum instead.

Ideally, we would implement only bug 261080, but there are futher issues
getting it done. So to not block other works depending on this change,
we push this version first.

* Source/WTF/wtf/FunctionDispatcher.h:
* Source/WTF/wtf/SuspendableWorkQueue.cpp:
(WTF::SuspendableWorkQueue::stateString):
* Source/WTF/wtf/SuspendableWorkQueue.h:
* Source/WTF/wtf/WorkQueue.cpp:
(WTF::WorkQueue::main):
(WTF::WorkQueue::dispatch):
(WTF::WorkQueue::assertIsCurrent const):
(WTF::ConcurrentWorkQueue::dispatch):
* Source/WTF/wtf/WorkQueue.h:
(WTF::WTF_ASSERTS_ACQUIRED_CAPABILITY): Deleted.
* Source/WTF/wtf/cocoa/WorkQueueCocoa.cpp:
(WTF::WorkQueue::WorkQueue):
(WTF::WorkQueue::constructMainWorkQueue): Deleted.
* Source/WTF/wtf/generic/WorkQueueGeneric.cpp:
(WTF::WorkQueue::WorkQueue):
(WTF::WorkQueue::constructMainWorkQueue): Deleted.

Canonical link: https://commits.webkit.org/267623@main
  • Loading branch information
jyavenard committed Sep 5, 2023
1 parent e6190f0 commit 4cc06b4
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 83 deletions.
10 changes: 5 additions & 5 deletions Source/WTF/wtf/FunctionDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,20 @@ namespace WTF {
// FunctionDispatcher is an abstract representation of something that functions can be
// dispatched to. This can for example be a run loop or a work queue.

class FunctionDispatcher {
class WTF_EXPORT_PRIVATE FunctionDispatcher {
public:
WTF_EXPORT_PRIVATE virtual ~FunctionDispatcher();
virtual ~FunctionDispatcher();

virtual void dispatch(Function<void ()>&&) = 0;

protected:
WTF_EXPORT_PRIVATE FunctionDispatcher();
FunctionDispatcher();
};

class WTF_CAPABILITY("is current") SerialFunctionDispatcher : public FunctionDispatcher {
class WTF_CAPABILITY("is current") WTF_EXPORT_PRIVATE SerialFunctionDispatcher : public FunctionDispatcher {
public:
#if ASSERT_ENABLED
WTF_EXPORT_PRIVATE virtual void assertIsCurrent() const = 0;
virtual void assertIsCurrent() const = 0;
#endif
};

Expand Down
2 changes: 1 addition & 1 deletion Source/WTF/wtf/SuspendableWorkQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ SuspendableWorkQueue::SuspendableWorkQueue(const char* name, QOS qos, ShouldLog
ASSERT(isMainThread());
}

inline const char* SuspendableWorkQueue::stateString(State state)
const char* SuspendableWorkQueue::stateString(State state)
{
switch (state) {
case State::Running:
Expand Down
14 changes: 7 additions & 7 deletions Source/WTF/wtf/SuspendableWorkQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@

namespace WTF {

class SuspendableWorkQueue final : public WorkQueue {
class WTF_EXPORT_PRIVATE SuspendableWorkQueue final : public WorkQueue {
public:
using QOS = WorkQueue::QOS;
enum class ShouldLog : bool { No, Yes };
WTF_EXPORT_PRIVATE static Ref<SuspendableWorkQueue> create(const char* name, QOS = QOS::Default, ShouldLog = ShouldLog::No);
WTF_EXPORT_PRIVATE void suspend(Function<void()>&& suspendFunction, CompletionHandler<void()>&& suspensionCompletionHandler);
WTF_EXPORT_PRIVATE void resume();
WTF_EXPORT_PRIVATE void dispatch(Function<void()>&&) final;
WTF_EXPORT_PRIVATE void dispatchAfter(Seconds, Function<void()>&&) final;
WTF_EXPORT_PRIVATE void dispatchSync(Function<void()>&&) final;
static Ref<SuspendableWorkQueue> create(const char* name, QOS = QOS::Default, ShouldLog = ShouldLog::No);
void suspend(Function<void()>&& suspendFunction, CompletionHandler<void()>&& suspensionCompletionHandler);
void resume();
void dispatch(Function<void()>&&) final;
void dispatchAfter(Seconds, Function<void()>&&) final;
void dispatchSync(Function<void()>&&) final;

private:
SuspendableWorkQueue(const char* name, QOS, ShouldLog);
Expand Down
55 changes: 41 additions & 14 deletions Source/WTF/wtf/WorkQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,6 @@

namespace WTF {

WorkQueue& WorkQueue::main()
{
static NeverDestroyed<RefPtr<WorkQueue>> mainWorkQueue;
static std::once_flag onceKey;
std::call_once(onceKey, [&] {
mainWorkQueue.get() = constructMainWorkQueue();
});
return *mainWorkQueue.get();
}

WorkQueueBase::WorkQueueBase(const char* name, Type type, QOS qos)
{
platformInitialize(name, type, qos);
Expand All @@ -60,14 +50,14 @@ WorkQueueBase::~WorkQueueBase()
platformInvalidate();
}

Ref<WorkQueue> WorkQueue::create(const char* name, QOS qos)
Ref<ConcurrentWorkQueue> ConcurrentWorkQueue::create(const char* name, QOS qos)
{
return adoptRef(*new WorkQueue(name, qos));
return adoptRef(*new ConcurrentWorkQueue(name, qos));
}

Ref<ConcurrentWorkQueue> ConcurrentWorkQueue::create(const char* name, QOS qos)
void ConcurrentWorkQueue::dispatch(Function<void()>&& function)
{
return adoptRef(*new ConcurrentWorkQueue(name, qos));
WorkQueueBase::dispatch(WTFMove(function));
}

#if !PLATFORM(COCOA)
Expand Down Expand Up @@ -185,4 +175,41 @@ void ConcurrentWorkQueue::apply(size_t iterations, WTF::Function<void(size_t ind
}
#endif

WorkQueue& WorkQueue::main()
{
static NeverDestroyed<RefPtr<WorkQueue>> mainWorkQueue;
static std::once_flag onceKey;
std::call_once(onceKey, [&] {
mainWorkQueue.get() = adoptRef(*new WorkQueue(CreateMain));
});
return *mainWorkQueue.get();
}

Ref<WorkQueue> WorkQueue::create(const char* name, QOS qos)
{
return adoptRef(*new WorkQueue(name, qos));
}

WorkQueue::WorkQueue(const char* name, QOS qos)
: WorkQueueBase(name, Type::Serial, qos)
{
}

void WorkQueue::dispatch(Function<void()>&& function)
{
WorkQueueBase::dispatch(WTFMove(function));
}

#if ASSERT_ENABLED
void WorkQueue::assertIsCurrent() const
{
WTF::assertIsCurrent(threadLikeAssertion());
}
#endif

ConcurrentWorkQueue::ConcurrentWorkQueue(const char* name, QOS qos)
: WorkQueueBase(name, Type::Concurrent, qos)
{
}

}
69 changes: 27 additions & 42 deletions Source/WTF/wtf/WorkQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@

namespace WTF {

class WorkQueueBase : public FunctionDispatcher, public ThreadSafeRefCounted<WorkQueueBase>, protected ThreadLike {
class WorkQueueBase : public ThreadSafeRefCounted<WorkQueueBase>, protected ThreadLike {
public:
using QOS = Thread::QOS;

~WorkQueueBase() override;
WTF_EXPORT_PRIVATE virtual ~WorkQueueBase();

WTF_EXPORT_PRIVATE void dispatch(Function<void()>&&) override;
WTF_EXPORT_PRIVATE void dispatch(Function<void()>&&);
WTF_EXPORT_PRIVATE void dispatchWithQOS(Function<void()>&&, QOS);
WTF_EXPORT_PRIVATE virtual void dispatchAfter(Seconds, Function<void()>&&);
WTF_EXPORT_PRIVATE virtual void dispatchSync(Function<void()>&&);
Expand All @@ -68,17 +68,17 @@ class WorkQueueBase : public FunctionDispatcher, public ThreadSafeRefCounted<Wor
explicit WorkQueueBase(RunLoop&);
#endif

void platformInitialize(const char* name, Type, QOS);
void platformInvalidate();

#if USE(COCOA_EVENT_LOOP)
OSObjectPtr<dispatch_queue_t> m_dispatchQueue;
#else
RunLoop* m_runLoop;
#endif
#if ASSERT_ENABLED
uint32_t m_threadID { 0 };
#endif
#endif
private:
void platformInitialize(const char* name, Type, QOS);
void platformInvalidate();
};

/**
Expand All @@ -88,57 +88,42 @@ class WorkQueueBase : public FunctionDispatcher, public ThreadSafeRefCounted<Wor
* They may be executed on different threads but can safely be used by objects that aren't already threadsafe.
* Use `assertIsCurrent(m_myQueue);` in a runnable to assert that the runnable runs in a specific queue.
*/
class WTF_CAPABILITY("is current") WorkQueue : public WorkQueueBase {
class WTF_CAPABILITY("is current") WTF_EXPORT_PRIVATE WorkQueue : public WorkQueueBase, public SerialFunctionDispatcher {
public:
WTF_EXPORT_PRIVATE static WorkQueue& main();

WTF_EXPORT_PRIVATE static Ref<WorkQueue> create(const char* name, QOS = QOS::Default);
static WorkQueue& main();
static Ref<WorkQueue> create(const char* name, QOS = QOS::Default);
void dispatch(Function<void()>&&) override;
#if ASSERT_ENABLED
void assertIsCurrent() const final;
ThreadLikeAssertion threadLikeAssertion() const; // public as used in API tests.
#else
ThreadLikeAssertion threadLikeAssertion() const { return { }; }; // NOLINT
#endif

#if !USE(COCOA_EVENT_LOOP)
RunLoop& runLoop() const { return *m_runLoop; }
#endif

#if ASSERT_ENABLED
WTF_EXPORT_PRIVATE ThreadLikeAssertion threadLikeAssertion() const;
#else
ThreadLikeAssertion threadLikeAssertion() const { return { }; };
#endif
protected:
WorkQueue(const char* name, QOS qos)
: WorkQueueBase(name, Type::Serial, qos)
{
}
WorkQueue(const char* name, QOS);
private:
#if USE(COCOA_EVENT_LOOP)
explicit WorkQueue(OSObjectPtr<dispatch_queue_t>&&);
#else
explicit WorkQueue(RunLoop&);
#endif
static Ref<WorkQueue> constructMainWorkQueue();

#if ASSERT_ENABLED
friend void assertIsCurrent(const WorkQueue&);
#endif
enum MainTag : bool {
CreateMain
};
explicit WorkQueue(MainTag);
};

inline void assertIsCurrent(const WorkQueue& workQueue) WTF_ASSERTS_ACQUIRED_CAPABILITY(workQueue)
{
assertIsCurrent(workQueue.threadLikeAssertion());
}

/**
* A ConcurrentWorkQueue unlike a WorkQueue doesn't guarantee the order in which the dispatched runnable will run
* and each can run concurrently on different threads.
*/
class ConcurrentWorkQueue final : public WorkQueueBase {
class WTF_EXPORT_PRIVATE ConcurrentWorkQueue final : public WorkQueueBase, public FunctionDispatcher {
public:
WTF_EXPORT_PRIVATE static Ref<ConcurrentWorkQueue> create(const char* name, QOS = QOS::Default);
WTF_EXPORT_PRIVATE static void apply(size_t iterations, WTF::Function<void(size_t index)>&&);
static Ref<ConcurrentWorkQueue> create(const char* name, QOS = QOS::Default);
static void apply(size_t iterations, WTF::Function<void(size_t index)>&&);
void dispatch(Function<void()>&&) override;
private:
ConcurrentWorkQueue(const char* name, QOS qos)
: WorkQueueBase(name, Type::Concurrent, qos)
{
}
ConcurrentWorkQueue(const char*, QOS);
};

}
Expand Down
9 changes: 2 additions & 7 deletions Source/WTF/wtf/cocoa/WorkQueueCocoa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,12 @@ void WorkQueueBase::platformInvalidate()
{
}

WorkQueue::WorkQueue(OSObjectPtr<dispatch_queue_t>&& queue)
: WorkQueueBase(WTFMove(queue))
WorkQueue::WorkQueue(MainTag)
: WorkQueueBase(dispatch_get_main_queue())
{
// Note: for main work queue we do not create a sequence id, the main thread id will be used.
}

Ref<WorkQueue> WorkQueue::constructMainWorkQueue()
{
return adoptRef(*new WorkQueue(dispatch_get_main_queue()));
}

#if ASSERT_ENABLED
ThreadLikeAssertion WorkQueue::threadLikeAssertion() const
{
Expand Down
9 changes: 2 additions & 7 deletions Source/WTF/wtf/generic/WorkQueueGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,11 @@ void WorkQueueBase::dispatchAfter(Seconds delay, Function<void()>&& function)
});
}

WorkQueue::WorkQueue(RunLoop& loop)
: WorkQueueBase(loop)
WorkQueue::WorkQueue(MainTag)
: WorkQueueBase(RunLoop::main())
{
}

Ref<WorkQueue> WorkQueue::constructMainWorkQueue()
{
return adoptRef(*new WorkQueue(RunLoop::main()));
}

#if ASSERT_ENABLED
ThreadLikeAssertion WorkQueue::threadLikeAssertion() const
{
Expand Down

0 comments on commit 4cc06b4

Please sign in to comment.