//================================================================
// Threads header file
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-Aug-01 01:24:22
//
// Copyright (C) 1996-2026 By Gabor Nagy. All rights reserved.
//================================================================
#ifndef _EThreads_h
#define _EThreads_h


#include <pthread.h>

#include <ETypes.h>
#include <ELists.h>



#ifdef __cplusplus
extern "C" {
#endif


typedef struct EThreadSet_S  EThreadSet;

#define EThreadCore\
	EThreadSet*  ThreadSet;\
	int          Number;\
	pthread_t    PThread;\
	EBool        PThreadCreated

typedef struct
{
	EThreadCore;
} EThread;
EListA_t(EThread);

#define EThreadSetCore\
	pthread_mutex_t  ThreadStatus_mutex;\
	pthread_cond_t   Cond;\
\
	EBool            Initialized;  /* This helps avoid multiple initializations when an object with a ThreadSet (e.g. an E3dRenderer subclass) runs though its constructor chain */\
	EBool            RunThreads;   /* Set to TRUE by EThreads_Start and set to FALSE by EThreads_Stop/EThreads_StopAndWait */\
\
	EListA_s(, EThread, Threads);\
	EIndex           MaxNThreads;\
	int              ThreadStructSize, NumOfThreadsStartingUp, NumOfRunningThreads

struct EThreadSet_S
{
	EThreadSetCore;
};


// 1D-parallel thread shared data core with workload management
//
#define EThreadSet1DCore\
	EThreadSetCore;\
\
	pthread_mutex_t  GetWorkload_mutex;\
	EIndex           NWorkUnits;\
	EIndex           NextWorkUnit;\
	ETime            ProgressSamplingInterval_us;\
\
  void (*ProgressMessageFunc)(EPointer PCustomData, const char* PMessage, ...);const char* ProgressMessage;\
  void (*ProgressFunc)(const float PComplete, EPointer PCustomData, void (*PAbortCallback)(EPointer PCustomData), EPointer PAbortFuncCustomData);EPointer ProgressFuncCustomData;\
  void (*AbortCallback)(EPointer PCustomData);EPointer AbortFuncCustomData

typedef struct
{
	EThreadSet1DCore;
} EThreadSet1D;


extern void   EThreadSet_Init(EThreadSet* PThreadSet, const int PThreadStructSize, const EBool PForceInit);
extern void   EThreadSet_Clear(EThreadSet* PThreadSet);
extern void   EThreadSet_FreeContents(EThreadSet* PThreadSet);

extern void   EThreadSet1D_Init(EThreadSet1D* PThreadSet);
extern void   EThreadSet1D_FreeContents(EThreadSet1D* PThreadSet);

extern void   EThreads_Init(EThreadSet* PThreadSet, const int PNumOfThreads);
extern void   EThreads_Start(EThreadSet* PThreadSet, void *(*PStartRoutine)(void*));
extern EBool  EThreads_WaitForFinish(EThreadSet* PThreadSet);
extern EBool  EThreads_Stop(EThreadSet* PThreadSet);
extern EBool  EThreads_StopAndWait(EThreadSet* PThreadSet);

extern void   EThreadSet1D_Run(EThreadSet1D* PThreadSet, const EIndex PNWorkUnits,  const size_t PThreadSize, void (PThreadInit)(EThread* PThread), void (PThreadFree)(EThread* PThread),  void* (*PThreadMain)(void* PThread));

extern EIndex EThreads_OptimalThreadCount(const EIndex PMax);

#ifdef __cplusplus
}	// Close scope of 'extern "C"' declaration
#endif


#endif // _EThreads_h
