You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libsxmp/include/sntl/pth_queue.h

118 lines
3.8 KiB
C

/*
* This is a proprietary software. See COPYING for further details.
*
* (c) 2013 Copyright Askele, inc. <http://askele.com>
* (c) 2013 Copyright Askele Ingria, inc. <http://askele-ingria.com>
* (c) 2014 Copyright Confident, inc. (granted permission to use in commercial software)
*/
/**
* @file pth_queue.h
* @author Alexander Vdolainen
* @date 4 Nov 2013, 20 Dec 2014 (dynamic polls)
* @brief queue implementation for threads intercommunication
*
*/
#ifndef __PTH_QUEUE_H__
#define __PTH_QUEUE_H__
#include <pthread.h>
#include <tdata/idx_allocator.h>
/* possible message types, ones with POLL_ prefix valid on for pth_dqtpoll_* */
#define SYS_MSG 0x0f0affee
#define USR_MSG 0x0afeeffe
#define POLL_DECREASE 0x0afafafe
#define POLL_INCREASE 0x0afaffff
#define NIL_MSG 0x0
#define END_MSG 0xdead0000
/* max amount of threads within the poll */
#define MAX_POLL_VALUE 32
typedef struct pth_msg_s {
void *data; /** < message payload */
unsigned int msgtype; /** < message type ID */
unsigned int qlength; /** < current queue length (actual on add moment),
* it makes no sense with few readers */
usrtc_node_t node;
} pth_msg_t;
typedef struct pth_queue_s {
unsigned int length;
/* sync */
pthread_mutex_t mutex;
pthread_cond_t cond;
/* queue data */
usrtc_t qtree;
/* cache */
usrtc_t msgcache;
} pth_queue_t;
int pth_queue_init(pth_queue_t *queue);
int pth_queue_add(pth_queue_t *queue, void *data, unsigned int msgtype);
int pth_queue_get(pth_queue_t *queue, const struct timespec *timeout,
pth_msg_t *msg);
unsigned int pth_queue_length(pth_queue_t *queue);
int pth_queue_destroy(pth_queue_t *queue, int freedata,
void (*free_msg)(void *));
/* dynamic queue thread poll ... bbrrr .... ok, ok with beer
* Dynamic queue thread poll is a queue like pth_queue,
* but also it has itäs own mamagement for threads - that's
* why dynamic.
* Ideally, the model is trying to achieve the following:
* 1. one thread in queue while no or very small amount of jobs in the queue
* 2. grow until max threads is reached while too many requests
* 3. gently slide down volume of threads after job heat
* 4. minimal additional drawbacks (i hate something periodically running,
* it's bad practice)
* The model is quite simple, we should make spurious wakeups equal to zero,
* if no - decrease poll value, and, if we don't have thread available -
* create it.
*/
typedef struct pth_dqtpoll_s {
pth_queue_t *queue; /** < Job queue */
pthread_t *poll; /** < Thread descriptors */
int (*jobdata_callback)(void *); /** < Callback to have a deal with data */
int flags; /** < Flags */
idx_allocator_t *idx; /** < index allocator for the poll threads */
pthread_rwlock_t stats_lock; /** < rwlock for stats data */
unsigned long spurious_wakeups; /** < amount of spurios wakeups */
int poll_value; /** < value of the poll (totally) */
struct timeval sched_time;
int msgop;
} pth_dqtpoll_t;
/* flags for poll */
#define DQTPOLL_RUNNING (1 << 1) /* poll is running */
#define DQTPOLL_DEADSTAGE (1 << 2) /* poll in the stage of destroy */
/* keep it stupid */
#define DQTPOLL_DELTAMS 500000
#define DQTPOLL_DELTASE 0
/* init poll, structure must be allocated */
int pth_dqtpoll_init(pth_dqtpoll_t*, int (*jobdata_callback)(void *));
/* run poll: poll */
int pth_dqtpoll_run(pth_dqtpoll_t*);
/* add the job to the queue: poll, job data, message type */
int pth_dqtpoll_add(pth_dqtpoll_t*, void*, unsigned int);
/* destroy the poll: poll, force flag
* if force flag is set (!= 0), give up
* about jobs, if no, do the job, but don't
* accept the new ones, and destroy all poll
* with last thread.
*/
int pth_dqtpoll_destroy(pth_dqtpoll_t*, int);
#endif /* __PTH_QUEUE_H__ */