paysages : Parallel processing helpers.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@483 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
8474b348a4
commit
14fcc1883e
5 changed files with 267 additions and 58 deletions
|
@ -9,8 +9,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "../system.h"
|
#include "../system.h"
|
||||||
|
#include "../tools.h"
|
||||||
#include "../tools/cache.h"
|
#include "../tools/cache.h"
|
||||||
#include "../tools/texture.h"
|
#include "../tools/texture.h"
|
||||||
|
#include "../tools/parallel.h"
|
||||||
|
|
||||||
/*********************** Constants ***********************/
|
/*********************** Constants ***********************/
|
||||||
|
|
||||||
|
@ -78,12 +80,6 @@ static const vec3 betaMSca = vec3(3e-3);
|
||||||
static const vec3 betaMEx = betaMSca / 0.9;
|
static const vec3 betaMEx = betaMSca / 0.9;
|
||||||
static const float mieG = 0.65;*/
|
static const float mieG = 0.65;*/
|
||||||
|
|
||||||
/*********************** Layer variables ***********************/
|
|
||||||
|
|
||||||
static double _r;
|
|
||||||
static Color _dhdH;
|
|
||||||
static int _layer;
|
|
||||||
|
|
||||||
/*********************** Shader helpers ***********************/
|
/*********************** Shader helpers ***********************/
|
||||||
|
|
||||||
#define step(_a_,_b_) ((_a_) < (_b_) ? 0 : 1)
|
#define step(_a_,_b_) ((_a_) < (_b_) ? 0 : 1)
|
||||||
|
@ -441,7 +437,7 @@ static void _precomputeIrrDeltaETexture()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _setLayer(int layer)
|
static void _getLayerParams(int layer, double* _r, Color* _dhdH)
|
||||||
{
|
{
|
||||||
double r = layer / (RES_R - 1.0);
|
double r = layer / (RES_R - 1.0);
|
||||||
r = r * r;
|
r = r * r;
|
||||||
|
@ -451,12 +447,11 @@ static void _setLayer(int layer)
|
||||||
double dminp = r - Rg;
|
double dminp = r - Rg;
|
||||||
double dmaxp = sqrt(r * r - Rg * Rg);
|
double dmaxp = sqrt(r * r - Rg * Rg);
|
||||||
|
|
||||||
_r = r;
|
*_r = r;
|
||||||
_dhdH.r = dmin;
|
_dhdH->r = dmin;
|
||||||
_dhdH.g = dmax;
|
_dhdH->g = dmax;
|
||||||
_dhdH.b = dminp;
|
_dhdH->b = dminp;
|
||||||
_dhdH.a = dmaxp;
|
_dhdH->a = dmaxp;
|
||||||
_layer = layer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************** inscatter1.glsl ***********************/
|
/*********************** inscatter1.glsl ***********************/
|
||||||
|
@ -519,8 +514,21 @@ static void _inscatter1(double r, double mu, double muS, double nu, Color* ray,
|
||||||
mie->b *= betaMSca.z;
|
mie->b *= betaMSca.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _inscatter1Prog(Texture3D* tex_rayleigh, Texture3D* tex_mie)
|
typedef struct
|
||||||
{
|
{
|
||||||
|
Texture3D* ray;
|
||||||
|
Texture3D* mie;
|
||||||
|
} Inscatter1Params;
|
||||||
|
|
||||||
|
static int _inscatter1Worker(ParallelWork* work, int layer, void* data)
|
||||||
|
{
|
||||||
|
Inscatter1Params* params = (Inscatter1Params*)data;
|
||||||
|
UNUSED(work);
|
||||||
|
|
||||||
|
double r;
|
||||||
|
Color dhdH;
|
||||||
|
_getLayerParams(layer, &r, &dhdH);
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
||||||
{
|
{
|
||||||
|
@ -532,14 +540,15 @@ static void _inscatter1Prog(Texture3D* tex_rayleigh, Texture3D* tex_mie)
|
||||||
Color ray = COLOR_BLACK;
|
Color ray = COLOR_BLACK;
|
||||||
Color mie = COLOR_BLACK;
|
Color mie = COLOR_BLACK;
|
||||||
double mu, muS, nu;
|
double mu, muS, nu;
|
||||||
_getMuMuSNu((double)x, (double)y, _r, _dhdH, &mu, &muS, &nu);
|
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
||||||
_inscatter1(_r, mu, muS, nu, &ray, &mie);
|
_inscatter1(r, mu, muS, nu, &ray, &mie);
|
||||||
/* store separately Rayleigh and Mie contributions, WITHOUT the phase function factor
|
/* store separately Rayleigh and Mie contributions, WITHOUT the phase function factor
|
||||||
* (cf "Angular precision") */
|
* (cf "Angular precision") */
|
||||||
texture3DSetPixel(tex_rayleigh, x, y, _layer, ray);
|
texture3DSetPixel(params->ray, x, y, layer, ray);
|
||||||
texture3DSetPixel(tex_mie, x, y, _layer, mie);
|
texture3DSetPixel(params->mie, x, y, layer, mie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************** inscatterS.glsl ***********************/
|
/*********************** inscatterS.glsl ***********************/
|
||||||
|
@ -642,8 +651,21 @@ static Color _inscatterS(double r, double mu, double muS, double nu, int first)
|
||||||
return raymie;
|
return raymie;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _jProg(Texture3D* result, int first)
|
typedef struct
|
||||||
{
|
{
|
||||||
|
Texture3D* result;
|
||||||
|
int first;
|
||||||
|
} jParams;
|
||||||
|
|
||||||
|
static int _jWorker(ParallelWork* work, int layer, void* data)
|
||||||
|
{
|
||||||
|
jParams* params = (jParams*)data;
|
||||||
|
UNUSED(work);
|
||||||
|
|
||||||
|
double r;
|
||||||
|
Color dhdH;
|
||||||
|
_getLayerParams(layer, &r, &dhdH);
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
||||||
{
|
{
|
||||||
|
@ -651,11 +673,12 @@ static void _jProg(Texture3D* result, int first)
|
||||||
{
|
{
|
||||||
Color raymie;
|
Color raymie;
|
||||||
double mu, muS, nu;
|
double mu, muS, nu;
|
||||||
_getMuMuSNu((double)x, (double)y, _r, _dhdH, &mu, &muS, &nu);
|
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
||||||
raymie = _inscatterS(_r, mu, muS, nu, first);
|
raymie = _inscatterS(r, mu, muS, nu, params->first);
|
||||||
texture3DSetPixel(result, x, y, _layer, raymie);
|
texture3DSetPixel(params->result, x, y, layer, raymie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************** irradianceN.glsl ***********************/
|
/*********************** irradianceN.glsl ***********************/
|
||||||
|
@ -747,40 +770,61 @@ static Color _inscatterN(double r, double mu, double muS, double nu)
|
||||||
return raymie;
|
return raymie;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _inscatterNProg(Texture3D* result)
|
static int _inscatterNWorker(ParallelWork* work, int layer, void* data)
|
||||||
{
|
{
|
||||||
|
UNUSED(work);
|
||||||
|
|
||||||
|
double r;
|
||||||
|
Color dhdH;
|
||||||
|
_getLayerParams(layer, &r, &dhdH);
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
||||||
{
|
{
|
||||||
for (y = 0; y < RES_MU; y++)
|
for (y = 0; y < RES_MU; y++)
|
||||||
{
|
{
|
||||||
double mu, muS, nu;
|
double mu, muS, nu;
|
||||||
_getMuMuSNu((double)x, (double)y, _r, _dhdH, &mu, &muS, &nu);
|
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
||||||
texture3DSetPixel(result, x, y, _layer, _inscatterN(_r, mu, muS, nu));
|
texture3DSetPixel((Texture3D*)data, x, y, layer, _inscatterN(r, mu, muS, nu));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************** copyInscatterN.glsl ***********************/
|
/*********************** copyInscatterN.glsl ***********************/
|
||||||
|
|
||||||
static void _copyInscatterNProg(Texture3D* source, Texture3D* destination)
|
typedef struct
|
||||||
{
|
{
|
||||||
|
Texture3D* source;
|
||||||
|
Texture3D* destination;
|
||||||
|
} CopyInscatterNParams;
|
||||||
|
|
||||||
|
static int _copyInscatterNWorker(ParallelWork* work, int layer, void* data)
|
||||||
|
{
|
||||||
|
CopyInscatterNParams* params = (CopyInscatterNParams*)data;
|
||||||
|
UNUSED(work);
|
||||||
|
|
||||||
|
double r;
|
||||||
|
Color dhdH;
|
||||||
|
_getLayerParams(layer, &r, &dhdH);
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
||||||
{
|
{
|
||||||
for (y = 0; y < RES_MU; y++)
|
for (y = 0; y < RES_MU; y++)
|
||||||
{
|
{
|
||||||
double mu, muS, nu;
|
double mu, muS, nu;
|
||||||
_getMuMuSNu((double)x, (double)y, _r, _dhdH, &mu, &muS, &nu);
|
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
||||||
Color col1 = texture3DGetLinear(source, x / (double)(RES_MU_S * RES_NU), y / (double)(RES_MU), _layer + 0.5 / (double)(RES_R));
|
Color col1 = texture3DGetLinear(params->source, x / (double)(RES_MU_S * RES_NU), y / (double)(RES_MU), layer + 0.5 / (double)(RES_R));
|
||||||
Color col2 = texture3DGetPixel(destination, x, y, _layer);
|
Color col2 = texture3DGetPixel(params->destination, x, y, layer);
|
||||||
col2.r += col1.r * 0.1 / _phaseFunctionR(nu);
|
col2.r += col1.r * 0.1 / _phaseFunctionR(nu);
|
||||||
col2.g += col1.g * 0.1 / _phaseFunctionR(nu);
|
col2.g += col1.g * 0.1 / _phaseFunctionR(nu);
|
||||||
col2.b += col1.b * 0.1 / _phaseFunctionR(nu);
|
col2.b += col1.b * 0.1 / _phaseFunctionR(nu);
|
||||||
col2.a = 1.0;
|
col2.a = 1.0;
|
||||||
texture3DSetPixel(destination, x, y, _layer, col2);
|
texture3DSetPixel(params->destination, x, y, layer, col2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************** Final getters ***********************/
|
/*********************** Final getters ***********************/
|
||||||
|
@ -1019,10 +1063,10 @@ static void _saveCache3D(Texture3D* tex, const char* tag, int order)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************** Public methods ***********************/
|
/*********************** Public methods ***********************/
|
||||||
|
|
||||||
void brunetonInit()
|
void brunetonInit()
|
||||||
{
|
{
|
||||||
int layer, x, y, z, order;
|
int x, y, z, order;
|
||||||
|
ParallelWork* work;
|
||||||
|
|
||||||
/* TODO Deletes */
|
/* TODO Deletes */
|
||||||
|
|
||||||
|
@ -1048,12 +1092,11 @@ void brunetonInit()
|
||||||
_deltaSMTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
_deltaSMTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
||||||
if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", 0) || !_tryLoadCache3D(_deltaSMTexture, "deltaSM", 0))
|
if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", 0) || !_tryLoadCache3D(_deltaSMTexture, "deltaSM", 0))
|
||||||
{
|
{
|
||||||
for (layer = 0; layer < RES_R; ++layer)
|
Inscatter1Params params = {_deltaSRTexture, _deltaSMTexture};
|
||||||
{
|
work = parallelWorkCreate(_inscatter1Worker, RES_R, ¶ms);
|
||||||
printf("deltaS %d\n", layer);
|
parallelWorkPerform(work, -1);
|
||||||
_setLayer(layer);
|
parallelWorkDelete(work);
|
||||||
_inscatter1Prog(_deltaSRTexture, _deltaSMTexture);
|
|
||||||
}
|
|
||||||
_saveCache3D(_deltaSRTexture, "deltaSR", 0);
|
_saveCache3D(_deltaSRTexture, "deltaSR", 0);
|
||||||
_saveCache3D(_deltaSMTexture, "deltaSM", 0);
|
_saveCache3D(_deltaSMTexture, "deltaSM", 0);
|
||||||
}
|
}
|
||||||
|
@ -1090,12 +1133,11 @@ void brunetonInit()
|
||||||
_deltaJTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
_deltaJTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
||||||
if (!_tryLoadCache3D(_deltaJTexture, "deltaJ", order))
|
if (!_tryLoadCache3D(_deltaJTexture, "deltaJ", order))
|
||||||
{
|
{
|
||||||
for (layer = 0; layer < RES_R; ++layer)
|
jParams params = {_deltaJTexture, order == 2};
|
||||||
{
|
work = parallelWorkCreate(_jWorker, RES_R, ¶ms);
|
||||||
printf("deltaJ %d %d\n", order, layer);
|
parallelWorkPerform(work, -1);
|
||||||
_setLayer(layer);
|
parallelWorkDelete(work);
|
||||||
_jProg(_deltaJTexture, order == 2);
|
|
||||||
}
|
|
||||||
_saveCache3D(_deltaJTexture, "deltaJ", order);
|
_saveCache3D(_deltaJTexture, "deltaJ", order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1110,12 +1152,10 @@ void brunetonInit()
|
||||||
/* computes deltaS (line 9 in algorithm 4.1) */
|
/* computes deltaS (line 9 in algorithm 4.1) */
|
||||||
if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", order))
|
if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", order))
|
||||||
{
|
{
|
||||||
for (layer = 0; layer < RES_R; ++layer)
|
work = parallelWorkCreate(_inscatterNWorker, RES_R, _deltaSRTexture);
|
||||||
{
|
parallelWorkPerform(work, -1);
|
||||||
printf("deltaS %d %d\n", order, layer);
|
parallelWorkDelete(work);
|
||||||
_setLayer(layer);
|
|
||||||
_inscatterNProg(_deltaSRTexture);
|
|
||||||
}
|
|
||||||
_saveCache3D(_deltaSRTexture, "deltaSR", order);
|
_saveCache3D(_deltaSRTexture, "deltaSR", order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1129,11 +1169,11 @@ void brunetonInit()
|
||||||
/* adds deltaS into inscatter texture S (line 11 in algorithm 4.1) */
|
/* adds deltaS into inscatter texture S (line 11 in algorithm 4.1) */
|
||||||
if (!_tryLoadCache3D(_inscatterTexture, "inscatter", order))
|
if (!_tryLoadCache3D(_inscatterTexture, "inscatter", order))
|
||||||
{
|
{
|
||||||
for (layer = 0; layer < RES_R; ++layer)
|
CopyInscatterNParams params = {_deltaSRTexture, _inscatterTexture};
|
||||||
{
|
work = parallelWorkCreate(_copyInscatterNWorker, RES_R, ¶ms);
|
||||||
_setLayer(layer);
|
parallelWorkPerform(work, -1);
|
||||||
_copyInscatterNProg(_deltaSRTexture, _inscatterTexture);
|
parallelWorkDelete(work);
|
||||||
}
|
|
||||||
_saveCache3D(_inscatterTexture, "inscatter", order);
|
_saveCache3D(_inscatterTexture, "inscatter", order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ void autoSetDaytimeFraction(double daytime)
|
||||||
|
|
||||||
void autoGenRealisticLandscape(int seed)
|
void autoGenRealisticLandscape(int seed)
|
||||||
{
|
{
|
||||||
TerrainDefinition terrain;
|
|
||||||
WaterDefinition water;
|
WaterDefinition water;
|
||||||
CloudsDefinition clouds;
|
CloudsDefinition clouds;
|
||||||
TexturesDefinition textures;
|
TexturesDefinition textures;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
142
lib_paysages/tools/parallel.c
Normal file
142
lib_paysages/tools/parallel.c
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
#include "parallel.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
#define PARALLEL_MAX_THREADS 20
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PARALLEL_WORKER_STATUS_VOID,
|
||||||
|
PARALLEL_WORKER_STATUS_RUNNING,
|
||||||
|
PARALLEL_WORKER_STATUS_DONE
|
||||||
|
} ParallelWorkerStatus;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Thread* thread;
|
||||||
|
ParallelWork* work;
|
||||||
|
ParallelWorkerStatus status;
|
||||||
|
int unit;
|
||||||
|
int result;
|
||||||
|
} ParallelWorker;
|
||||||
|
|
||||||
|
struct ParallelWork
|
||||||
|
{
|
||||||
|
int units;
|
||||||
|
int running;
|
||||||
|
ParallelUnitFunction unit_function;
|
||||||
|
ParallelWorker workers[PARALLEL_MAX_THREADS];
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
ParallelWork* parallelWorkCreate(ParallelUnitFunction func, int units, void* data)
|
||||||
|
{
|
||||||
|
ParallelWork* result;
|
||||||
|
|
||||||
|
result = (ParallelWork*)malloc(sizeof(ParallelWork));
|
||||||
|
result->units = units;
|
||||||
|
result->running = 0;
|
||||||
|
result->unit_function = func;
|
||||||
|
result->data = data;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void parallelWorkDelete(ParallelWork* work)
|
||||||
|
{
|
||||||
|
assert(!work->running);
|
||||||
|
free(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* _workerThreadCallback(ParallelWorker* worker)
|
||||||
|
{
|
||||||
|
worker->result = worker->work->unit_function(worker->work, worker->unit, worker->work->data);
|
||||||
|
worker->status = PARALLEL_WORKER_STATUS_DONE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _runNextWorker(ParallelWorker workers[], int worker_count, int unit)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
for (i = 0; i < worker_count; i++)
|
||||||
|
{
|
||||||
|
ParallelWorker* worker = workers + i;
|
||||||
|
if (worker->status == PARALLEL_WORKER_STATUS_VOID)
|
||||||
|
{
|
||||||
|
worker->status = PARALLEL_WORKER_STATUS_RUNNING;
|
||||||
|
worker->result = 0;
|
||||||
|
worker->unit = unit;
|
||||||
|
worker->thread = threadCreate((ThreadFunction)_workerThreadCallback, worker);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (worker->status == PARALLEL_WORKER_STATUS_DONE)
|
||||||
|
{
|
||||||
|
int result = worker->result;
|
||||||
|
|
||||||
|
worker->status = PARALLEL_WORKER_STATUS_RUNNING;
|
||||||
|
worker->result = 0;
|
||||||
|
worker->unit = unit;
|
||||||
|
threadJoin(worker->thread);
|
||||||
|
worker->thread = threadCreate((ThreadFunction)_workerThreadCallback, worker);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timeSleepMs(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int parallelWorkPerform(ParallelWork* work, int workers)
|
||||||
|
{
|
||||||
|
int i, done, result;
|
||||||
|
assert(!work->running);
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
if (workers <= 0)
|
||||||
|
{
|
||||||
|
workers = systemGetCoreCount();
|
||||||
|
}
|
||||||
|
if (workers > PARALLEL_MAX_THREADS)
|
||||||
|
{
|
||||||
|
workers = PARALLEL_MAX_THREADS;
|
||||||
|
}
|
||||||
|
work->running = 1;
|
||||||
|
|
||||||
|
/* Init workers */
|
||||||
|
for (i = 0; i < workers; i++)
|
||||||
|
{
|
||||||
|
work->workers[i].status = PARALLEL_WORKER_STATUS_VOID;
|
||||||
|
work->workers[i].work = work;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform run */
|
||||||
|
for (done = 0; done < work->units; done++)
|
||||||
|
{
|
||||||
|
if (_runNextWorker(work->workers, workers, done))
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait and clean up workers */
|
||||||
|
for (i = 0; i < workers; i++)
|
||||||
|
{
|
||||||
|
if (work->workers[i].status != PARALLEL_WORKER_STATUS_VOID)
|
||||||
|
{
|
||||||
|
threadJoin(work->workers[i].thread);
|
||||||
|
if (work->workers[i].result)
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
work->running = 0;
|
||||||
|
return result;
|
||||||
|
}
|
30
lib_paysages/tools/parallel.h
Normal file
30
lib_paysages/tools/parallel.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef _PAYSAGES_TOOLS_PARALLEL_H_
|
||||||
|
#define _PAYSAGES_TOOLS_PARALLEL_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parallel processing helpers.
|
||||||
|
*
|
||||||
|
* Several units of work can be accomplished by a given number of parallel workers.
|
||||||
|
* Workers are implemented by threads so thread-safety must be ensured while accessing
|
||||||
|
* shared data from unit functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct ParallelWork ParallelWork;
|
||||||
|
typedef int (*ParallelUnitFunction)(ParallelWork* work, int unit, void* data);
|
||||||
|
|
||||||
|
/*void parallelInit();
|
||||||
|
void parallelQuit();*/
|
||||||
|
|
||||||
|
ParallelWork* parallelWorkCreate(ParallelUnitFunction func, int units, void* data);
|
||||||
|
void parallelWorkDelete(ParallelWork* work);
|
||||||
|
int parallelWorkPerform(ParallelWork* work, int workers);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue