Notifications#
Being a fiber-based system, things like profiling may need to know additional context about what is running on a thread.
To facilitate this, carb.tasking.plugin will load all instances of a special notification interface: IFiberEvents
.
This notification interface will be called by carb.tasking.plugin on worker threads when they start and stop running fibers. Consider the use case of a profiler: the profiler took a timestamp at the beginning of an operation. If the thread that was running that operation swaps to a different fiber, the profiler would need to know that. Likewise, if the fiber was resumed on a different thread, the profiler would have to keep track of that as well. By paying attention to these events, when the operation completes (possibly on a different thread), the profiler can be aware even if the fiber changed threads.
Note
carb.tasking.plugin only gathers carb::tasking::IFiberEvents
interfaces at startup, or when
carb::tasking::ITasking::changeParameters
is called, or when carb::tasking::ITasking::reloadFiberEvents
is called.
If you register a plugin that exports the carb::tasking::IFiberEvents
interface, perform one of these actions
in order to ensure that you receive notifications.
How it works#
Whenever a carb.tasking thread starts running a fiber, the carb::tasking::IFiberEvents::notifyFiberStart
function is called within the context of the task thread. When the fiber yields execution back to the thread, the carb::tasking::IFiberEvents::notifyFiberStop
function is called within the context of the task thread.
Implementing IFiberEvents#
Your plugin can implement the IFiberEvents interface easily. The first step is using the CARB_PLUGIN_IMPL
macro:
#include <carb/Defines.h>
#include <carb/PluginUtils.h>
#include <carb/tasking/IFiberEvents.h>
#define PLUGIN_IMPL_NAME "carb.fibereventtest.plugin"
const struct carb::PluginImplDesc kPluginImpl = { PLUGIN_IMPL_NAME, "FiberEvent test", "NVIDIA",
carb::PluginHotReload::eDisabled, "dev" };
CARB_PLUGIN_IMPL_EX(kPluginImpl, carb::tasking::IFiberEvents, carb::fibereventtest::FiberEventTest)
CARB_PLUGIN_IMPL_NO_DEPS()
Then implement a fillInterface
function:
template <>
bool fillInterface<carb::tasking::IFiberEvents>(carb::Version* ver, void* iface)
{
using namespace carb::fibereventtest;
// clang-format off
new (iface) carb::tasking::IFiberEvents
{
notifyFiberStart,
notifyFiberStop,
};
// clang-format on
return true;
}
A common usage pattern is to track the fiber ID as thread-local data, or to report an event to the profiler.
This example merely counts the start and stop events for testing purposes:
void notifyFiberStart(const uint64_t fiberId)
{
startEvents.fetch_add(1, std::memory_order_release);
}
void notifyFiberStop(const uint64_t fiberId)
{
stopEvents.fetch_add(1, std::memory_order_release);
}
Attention
Keep your notification functions as fast as possible because they are called in the context of the carb.tasking worker threads.
Warning
Your notification functions will likely be called from several carb.tasking worker threads simultaneously. You are required to ensure thread safety!