Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use tbb::task_group::defer in FinalWaitingTask #38715

Merged
merged 1 commit into from
Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions FWCore/Concurrency/interface/FinalWaitingTask.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifndef FWCore_Concurrency_FinalWaitingTask_h
#define FWCore_Concurrency_FinalWaitingTask_h
// -*- C++ -*-
//
// Package: FWCore/Concurrency
// Class : FinalWaitingTask
//
/**\class FinalWaitingTask FinalWaitingTask.h "FWCore/Concurrency/interface/FinalWaitingTask.h"

Description: [one line class summary]

Usage:
Use this class on the stack to signal the final task to be run.
Call done() to check to see if the task was run and check value of
exceptionPtr() to see if an exception was thrown by any task in the group.

*/
//
// Original Author: Christopher Jones
// Created: Tue, 12 Jul 2022 18:45:15 GMT
//

// system include files
#include "oneapi/tbb/task_group.h"

// user include files
#include "FWCore/Concurrency/interface/WaitingTask.h"

// forward declarations
namespace edm {
class FinalWaitingTask : public WaitingTask {
public:
FinalWaitingTask() = delete;
explicit FinalWaitingTask(tbb::task_group& iGroup)
: m_group{&iGroup}, m_handle{iGroup.defer([]() {})}, m_done{false} {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if always adding an empty deferred task could add any visible overhead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is only used when shutting down the event loop so I doubt it can be seen at all.


void execute() final { m_done = true; }

[[nodiscard]] bool done() const noexcept { return m_done.load(); }

void wait() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about having similar nomenclature with SYCL queues? (asking since SYCL/DPC++ is part of the oneAPI) There the wait() does not throw, and one has to ask wait_and_throw() explicitly to have exceptions (from asynchronous processing) to throw.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we care at all. I went with consistency with tbb::task_group::wait which can throw.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, consistency with oneTBB's nomenclature is more important.

m_group->wait();
if (exceptionPtr()) {
std::rethrow_exception(exceptionPtr());
}
}
std::exception_ptr waitNoThrow() {
m_group->wait();
return exceptionPtr();
}

private:
void recycle() final { m_group->run(std::move(m_handle)); }
tbb::task_group* m_group;
tbb::task_handle m_handle;
std::atomic<bool> m_done;
};

} // namespace edm
#endif
17 changes: 0 additions & 17 deletions FWCore/Concurrency/interface/WaitingTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,6 @@ namespace edm {
std::atomic<bool> m_ptrSet = false;
};

/** Use this class on the stack to signal the final task to be run.
Call done() to check to see if the task was run and check value of
exceptionPtr() to see if an exception was thrown by any task in the group.
*/
class FinalWaitingTask : public WaitingTask {
public:
FinalWaitingTask() : m_done{false} {}

void execute() final { m_done = true; }

bool done() const { return m_done.load(); }

private:
void recycle() final {}
std::atomic<bool> m_done;
};

template <typename F>
class FunctorWaitingTask : public WaitingTask {
public:
Expand Down
Loading