Files
pcas/src/libCom/pool/poolPriv.h
Michael Davidsaver 83dfc7980d thread pool: handle failure to create worker
epicsJobQueue() returns EAGAIN when the first worker
can't be lazily created.

Failure to create workers beyond the first is
silently ignored.
2014-07-24 18:50:19 -04:00

98 lines
2.9 KiB
C

/*************************************************************************\
* Copyright (c) 2014 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef POOLPRIV_H
#define POOLPRIV_H
#include "epicsThreadPool.h"
#include "ellLib.h"
#include "epicsThread.h"
#include "epicsEvent.h"
#include "epicsMutex.h"
struct epicsThreadPool {
ELLNODE sharedNode;
size_t sharedCount;
ELLLIST jobs; /* run queue */
ELLLIST owned; /* unqueued jobs. */
/* Worker state counters.
* The life cycle of a worker is
* Wakeup -> Awake -> Sleeping
* Newly created workers go into the wakeup state
*/
/* # of running workers which are not waiting for a wakeup event */
size_t threadsAreAwake;
/* # of sleeping workers which need to be awakened */
size_t threadsWaking;
/* # of workers waiting on the workerWakeup event */
size_t threadsSleeping;
/* # of threads started and not stopped */
size_t threadsRunning;
/* # of observers waiting on pool events */
size_t observerCount;
epicsEventId workerWakeup;
epicsEventId shutdownEvent;
epicsEventId observerWakeup;
/* Disallow epicsJobQueue */
unsigned int pauseadd:1;
/* Prevent workers from running new jobs */
unsigned int pauserun:1;
/* Prevent further changes to pool options */
unsigned int freezeopt:1;
/* tell workers to exit */
unsigned int shutdown:1;
epicsMutexId guard;
/* copy of config passed when created */
epicsThreadPoolConfig conf;
};
/* Called after manipulating counters to check that invariants are preserved */
#define CHECKCOUNT(pPool) do{if(!(pPool)->shutdown) { \
assert( (pPool)->threadsAreAwake + (pPool)->threadsSleeping == (pPool)->threadsRunning ); \
assert( (pPool)->threadsWaking <= (pPool)->threadsSleeping ); \
}}while(0)
/* When created a job is idle. queued and running are false
* and jobnode is in the thread pool's owned list.
*
* When the job is added, the queued flag is set and jobnode
* is in the jobs list.
*
* When the job starts running the queued flag is cleared and
* the running flag is set. jobnode is not in any list
* (held locally by worker).
*
* When the job has finished running, the running flag is cleared.
* The queued flag may be set if the job re-added itself.
* Based on the queued flag jobnode is added to the appropriate
* list.
*/
struct epicsJob {
ELLNODE jobnode;
epicsJobFunction func;
void *arg;
epicsThreadPool *pool;
unsigned int queued:1;
unsigned int running:1;
unsigned int freewhendone:1; /* lazy delete of running job */
unsigned int dead:1; /* flag to catch use of freed objects */
};
int createPoolThread(epicsThreadPool *pool);
#endif // POOLPRIV_H