Files
handleaiuinew/env/LMI/include/kApi/Threads/kParallel.h
T

200 lines
7.8 KiB
C
Raw Normal View History

2024-05-18 23:53:26 +08:00
/**
* @file kParallel.h
* @brief Declares the kParallel type.
*
* @internal
* Copyright (C) 2017-2021 by LMI Technologies Inc.
* Licensed under the MIT License.
* Redistributed files must retain the above copyright notice.
*/
#ifndef K_API_PARALLEL_H
#define K_API_PARALLEL_H
#include <kApi/kApiDef.h>
/**
* @struct kParallelArgs
* @extends kValue
* @ingroup kApi-Threads
* @brief Arguments received by a kParallel data processing callback.
*/
typedef struct kParallelArgs
{
kPointer content; ///< Shared data content, to be processed by callbacks.
kSize index; ///< Index of current processing callback (0..count-1).
kSize count; ///< Total number of processing callbacks (1 or more).
} kParallelArgs;
/**
* Helper method that can be used to calculate the data start index within a kParallel callback.
*
* The kParallel class enables data processing to be distributed across multiple callbacks. This
* arrangement requires the dataset to be partitioned, with each callback performing a portion of the
* total required work.
*
* Assuming that the dataset can be represented by a linear range (e.g., elements in an array), the
* kParallelArgs_Begin method can optionally be used to calculate the lower bound (start index) of the
* data to be processed in the current kParallel callback invocation.
*
* @public @memberof kParallelArgs
* @param args Arguments received by a kParallel data processing callback.
* @param start First index of the overall range to be collectively processed.
* @param count Total count of elements to be collectively processed.
* @return Index of first element to be processed in this callback.
*/
kFx(kSize) kParallelArgs_Begin(const kParallelArgs* args, kSize start, kSize count);
/**
* Helper method that can be used to calculate the data end index within a kParallel callback.
*
* The kParallel class enables data processing to be distributed across multiple callbacks. This
* arrangement requires the dataset to be partitioned, with each callback performing a portion of the
* total required work.
*
* Assuming that the dataset can be represented by a linear range (e.g., elements in an array), the
* kParallelArgs_End method can optionally be used to calculate the upper bound (end index) of the
* data to be processed in the current kParallel callback invocation.
*
* @public @memberof kParallelArgs
* @param args Arguments received by a kParallel data processing callback.
* @param start First index of the overall range to be collectively processed.
* @param count Total count of elements to be collectively processed.
* @return One greater than the index of the last element to be processed in this callback.
*/
kFx(kSize) kParallelArgs_End(const kParallelArgs* args, kSize start, kSize count);
/** kParallel data processing callback signature. */
typedef kStatus(kCall* kParallelFx)(kPointer receiver, kParallel sender, kParallelArgs* args);
/**
* @struct kParallelTransaction
* @ingroup kApi-Threads
* @brief Opaque pointer to a kParallel transaction.
*/
typedef kPointer kParallelTransaction;
#include <kApi/Threads/kParallel.x.h>
/**
* @class kParallel
* @extends kObject
* @ingroup kApi-Threads
* @brief Declares the kParallel class.
*
* The kParallel class can be used to process a dataset using a thread pool.
@code {.c}
kStatus MyApp_ProcessImage(MyApp app, kImage image)
{
//distribute image processing across multiple concurrent callbacks; the number of threads
//is automatically selected, based on hardware resources
return kParallel_Execute(MyApp_ProcessImageSlice, app, image);
}
kStatus kCall MyApp_ProcessImageSlice(MyApp app, kParallel parallel, kParallelArgs* args)
{
kImage image = args->content;
kSize imageHeight = kImage_Height(image);
kSize beginRow = kParallelArgs_Begin(args, 0, imageHeight);
kSize endRow = kParallelArgs_End(args, 0, imageHeight);
kSize i;
kCheck(kImage_PixelType(image) == kTypeOf(k8u));
for (i = beginRow; i < endRow; ++i)
{
const k8u* row = kImage_RowAtT(image, i, k8u);
//process...
}
return kOK;
}
@endcode
*
*/
//typedef kObject kParallel; --forward-declared in kFsDef.x.h
/**
* Synchronously processes a dataset.
*
* On multicore systems, this method is equivalent to calling kParallel_BeginExecute followed
* by kParallel_EndExecute. On unicore systems, this method directly invokes the specified
* callback.
*
* This method is thread-safe.
*
* @public @memberof kParallel
* @param callback Data processing callback function.
* @param receiver Receiver argument to be provided to callback.
* @param content Content to be provided to callback via kParallelArgs.content.
* @return Operation status (kOK, or first error returned by a callback).
*/
kFx(kStatus) kParallel_Execute(kParallelFx callback, kPointer receiver, kPointer content);
/**
* Begins asynchronously processing a dataset.
*
* This function returns immediately, providing a transaction handle to represent the in-progress data processing.
* The kParallel_EndExecute function <em>must</em> be used to wait for execution to complete. Failure to call
* kParallel_EndExecute will result in leaks.
*
* This method is thread-safe.
*
* @public @memberof kParallel
* @param callback Data processing callback function.
* @param receiver Receiver argument to be provided to callback.
* @param content Content to be provided to callback via kParallelArgs.content.
* @param transaction Receives transaction handle, which must be passed to kParallel_EndExecute.
* @return Operation status.
*/
kFx(kStatus) kParallel_BeginExecute(kParallelFx callback, kPointer receiver, kPointer content, kParallelTransaction* transaction);
/**
* Blocks until execution of the specified kParallel transaction is complete.
*
* This method is thread-safe.
*
* @public @memberof kParallel
* @param transaction Transaction handle emitted by kParallel_BeginExecute.
* @return Operation status (kOK, or first error returned by a callback).
*/
kFx(kStatus) kParallel_EndExecute(kParallelTransaction transaction);
/**
* Directly invokes the specified callback without using the thread pool.
*
* This method can be used for testing purposes, to determine non-parallel execution time
* without having to significantly restructure the caller.
*
* This method is thread-safe.
*
* @public @memberof kParallel
* @param callback Data processing callback function.
* @param receiver Receiver argument to be provided to callback.
* @param content Content to be provided to callback via kParallelArgs.content.
* @return Operation status (kOK, or first error returned by a callback).
*/
kFx(kStatus) kParallel_ExecuteDirect(kParallelFx callback, kPointer receiver, kPointer content);
/**
* Reports the number of threads that will be used to process a parallel transaction.
*
* The number of threads used to process a parallel transaction can be determined from within a
* parallel processing callback by examining the kParallelArgs 'count' field. However, if an algorithm
* requires this information prior to calling kParallel_Execute or kParallel_BeginExecute, (e.g., to
* preallocate temporary data structures), the kParallel_ThreadCount method can be used instead.
*
* This method is thread-safe.
*
* @public @memberof kParallel
* @return Number of threads that will be used to process a parallel transaction.
*/
kInlineFx(kSize) kParallel_ThreadCount()
{
return kThreadPool_Count(kThreadPool_Default());
}
#endif