X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=docs%2Fclasses%2FDynamicClusterPool.html;h=53242a4961ac606d00edf78b736aea361a0beb91;hb=938d9c678aa8e70e5642feffb90604cf25c993fe;hp=eb83929c53eaaa756628630e017ee318324fde47;hpb=ed1ecf09c599769ed61771ec25d71c39c19ba70b;p=poolifier.git diff --git a/docs/classes/DynamicClusterPool.html b/docs/classes/DynamicClusterPool.html index eb83929c..53242a49 100644 --- a/docs/classes/DynamicClusterPool.html +++ b/docs/classes/DynamicClusterPool.html @@ -1,13 +1,15 @@ -
A cluster pool with a dynamic number of workers, but a guaranteed minimum number of workers.
This cluster pool creates new workers when the others are busy, up to the maximum number of workers. -When the maximum number of workers is reached, an event is emitted. If you want to listen to this event, use the pool's
- -emitter
.Template
of data sent to the worker. This can only be serializable data.
- -Template
of response of execution. This can only be serializable data.
+When the maximum number of workers is reached and workers are busy, an event is emitted. If you want to listen to this event, use the pool'semitter
.Author
Christopher Quadflieg
@@ -30,17 +28,21 @@ When the maximum number of workers is reached, an event is emitted. If you wantType Parameters
Data = unknown
Data = unknown
+Type of data sent to the worker. This can only be serializable data.
+Response = unknown
Response = unknown
+Type of execution response. This can only be serializable data.
+Hierarchy
-- FixedClusterPool<Data, Response>
+
- FixedClusterPool<Data, Response>
- DynamicClusterPool
@@ -48,59 +50,55 @@ When the maximum number of workers is reached, an event is emitted. If you want
constructor
+constructor
emitter?
-file Path
-max
-next Message Id
-number Of Workers
-opts
-promise Map
-worker Choice Strategy Context
-workers
-workers Tasks Usage
+emitter?
+file Path
+max
+number Of Workers
+opts
+promise Response Map
+worker Choice Strategy Context
+worker Nodes
busy
-number Of Running Tasks
-type
+busy
+full
+number Of Queued Tasks
+number Of Running Tasks
+type
after Promise Worker Response Hook
-after Worker Setup
-before Promise Worker Response Hook
-choose Worker
-create And Setup Worker
-create Worker
-destroy
-destroy Worker
-execute
-find Free Worker
-get Worker Average Tasks Run Time
-get Worker Index
-get Worker Running Tasks
-init Worker Tasks Usage
-internal Execute
-internal Get Busy Status
-is Main
-register Worker Message Listener
-remove Worker
-send To Worker
-set Worker Choice Strategy
-setup Hook
-worker Listener
+after Task Execution Hook
+after Worker Setup
+before Task Execution Hook
+choose Worker Node
+create And Setup Worker
+create Worker
+destroy
+destroy Worker
+enable Tasks Queue
+execute
+internal Busy
+is Main
+register Worker Message Listener
+send To Worker
+set Tasks Queue Options
+set Worker Choice Strategy
+set Worker Choice Strategy Options
+setup Hook
+worker Listener
+
+
-
-
-
-
-
-
-
-
-
+- Defined in src/pools/cluster/dynamic.ts:28
+
emitter?: PoolEmitter
-
-
+emitter?: PoolEmitter
+
-
+- Defined in src/pools/abstract-pool.ts:42
+
file Path: string
+file Path: string
+
-
+- Defined in src/pools/abstract-pool.ts:77
+
max: number
-
-
-
-
-next Message Id: number = 0
-max: number
+
-
-
+- Defined in src/pools/cluster/dynamic.ts:30
+
number Of Workers: number
+number Of Workers: number
+
-
+- Defined in src/pools/abstract-pool.ts:76
+
opts: ClusterPoolOptions = {}
+opts: ClusterPoolOptions = {}
+
-
-promise Map: Map<number, PromiseWorkerResponseWrapper<Worker, Response>> = ...
-- Defined in src/pools/cluster/fixed.ts:53
+
+promise Response Map: Map<string, PromiseResponseWrapper<Worker, Response>> = ...
+
-
-
+- Defined in src/pools/abstract-pool.ts:52
+
worker Choice Strategy Context: WorkerChoiceStrategyContext<Worker, Data, Response>
-worker Choice Strategy Context: WorkerChoiceStrategyContext<Worker, Data, Response>
+
-
-workers: Worker[] = []
-
-
-
-
-workers Tasks Usage: Map<Worker, TasksUsage> = ...
-
-
-
+- Defined in src/pools/abstract-pool.ts:62
+
+worker Nodes: WorkerNode<Worker, Data>[] = []
+
+
-
+
+
+
+
+
+- get numberOfRunningTasks(): number
-
-
-
+
-
+- Defined in src/pools/abstract-pool.ts:185
+
+- Defined in src/pools/cluster/dynamic.ts:38
-
+
-
\ No newline at end of file
+
\ No newline at end of file
Constructors
-Properties
-Accessors
-Methods
-Constructors
-constructor
--- new
Dynamic Cluster Pool<Data, Response>(min: number, max: number, filePath: string, opts??: ClusterPoolOptions): DynamicClusterPool<Data, Response>
+
+- new
Dynamic Cluster Pool<Data, Response>(min, max, filePath, opts?): DynamicClusterPool<Data, Response>
-
@@ -108,516 +106,506 @@ When the maximum number of workers is reached, an event is emitted. If you want
-
-
+
-
-
Constructs a new poolifier dynamic cluster pool.
Type Parameters
Data = unknown
Data = unknown
Response = unknown
Response = unknown
Parameters
min: number
+min: number
Minimum number of workers which are always active.
max: number
+max: number
Maximum number of workers that can be created by this pool.
filePath: string
+filePath: string
Path to an implementation of a
ClusterWorker
file, which can be relative or absolute.
+Optional
opts: ClusterPoolOptions = {}opts: ClusterPoolOptions = {}
Options for this dynamic cluster pool.
Returns DynamicClusterPool<Data, Response>
Properties
-
-Optional
Readonly
emitterInherit Doc
Emitter on which events can be listened to.
+Events that can currently be listened to:
++
+
+
+'full'
: Emitted when the pool is dynamic and full.'busy'
: Emitted when the pool is busy.Inherited from FixedClusterPool.emitter
-- Defined in src/pools/abstract-pool.ts:42
Path
-Readonly
filePath to the worker file.
+Inherited from FixedClusterPool.filePath
-- Defined in src/pools/abstract-pool.ts:85
-Readonly
maxInherit Doc
Inherited from FixedClusterPool.max
--- Defined in src/pools/cluster/dynamic.ts:30
Message Id
-Protected
nextId of the next message.
+Maximum number of workers that can be created by this pool.
Inherited from FixedClusterPool.nextMessageId
-- Defined in src/pools/abstract-pool.ts:63
Of Workers
-Readonly
numberNumber of workers that this pool should manage.
+Inherited from FixedClusterPool.numberOfWorkers
-- Defined in src/pools/abstract-pool.ts:84
-Readonly
optsOptions for this fixed cluster pool.
+Inherited from FixedClusterPool.opts
-- Defined in src/pools/cluster/fixed.ts:47
Map
-Protected
promiseThe promise map.
+ Response Map
+Protected
promiseThe execution response promise map.
-
-
+
+
-key
: This is the message Id of each submitted task.value
: An object that contains the worker, the resolve function and the reject function.key
: The message id of each submitted task.value
: An object that contains the worker, the execution response promise resolve and reject callbacks.When we receive a message from the worker we get a map entry and resolve/reject the promise based on the message.
+When we receive a message from the worker, we get a map entry with the promise resolve/reject bound to the message id.
Inherited from FixedClusterPool.promiseMap
+Inherited from FixedClusterPool.promiseResponseMap
-- Defined in src/pools/abstract-pool.ts:55
Choice Strategy Context
-Protected
workerWorker choice strategy instance implementing the worker choice algorithm.
-Default to a strategy implementing a round robin algorithm.
+Worker choice strategy context referencing a worker choice algorithm implementation.
+Default to a round robin algorithm.
Inherited from FixedClusterPool.workerChoiceStrategyContext
-- Defined in src/pools/abstract-pool.ts:70
-Readonly
workersInherit Doc
Inherited from FixedClusterPool.workers
--- Defined in src/pools/abstract-pool.ts:33
Tasks Usage
-Readonly
workersInherit Doc
Inherited from FixedClusterPool.workersTasksUsage
--- Defined in src/pools/abstract-pool.ts:36
Nodes
+Readonly
workerPool worker nodes.
+Inherited from FixedClusterPool.workerNodes
++- Defined in src/pools/abstract-pool.ts:39
Accessors
-busy
-+
+- get busy(): boolean
-
-
-
+
-
-
+Protected
busyInherit Doc
Whether the pool is busy or not.
+The pool busyness boolean status.
+Returns boolean
Overrides FixedClusterPool.busy
-- Defined in src/pools/cluster/dynamic.ts:43
number Of Running Tasks
-+- Defined in src/pools/cluster/dynamic.ts:48
+Protected
full+- get full(): boolean
+-
+
+
+
Whether the pool is full or not.
+The pool filling boolean status.
+Returns boolean
Overrides FixedClusterPool.full
++- Defined in src/pools/cluster/dynamic.ts:43
Of Queued Tasks
+Private
number+- get numberOfQueuedTasks(): number
+-
+
+
+
Number of tasks queued in the pool.
+Returns number
Inherited from FixedClusterPool.numberOfQueuedTasks
++- Defined in src/pools/abstract-pool.ts:195
Of Running Tasks
+Private
numberInherit Doc
Number of tasks running in the pool.
+Returns number
Inherited from FixedClusterPool.numberOfRunningTasks
-- Defined in src/pools/abstract-pool.ts:156
type
--- get type(): PoolType
+
+- get type(): PoolType
-
-
-
-
+
+
Inherit Doc
Returns PoolType
Pool type.
+If it is
+'dynamic'
, it provides themax
property.Returns PoolType
Overrides FixedClusterPool.type
-- Defined in src/pools/cluster/dynamic.ts:38
Methods
- Promise Worker Response Hook
-Protected
after-- after
Promise Worker Response Hook(message: MessageValue<Response, unknown>, promise: PromiseWorkerResponseWrapper<Worker, Response>): void
+
+
Task Execution Hook
+Protected
after+- after
Task Execution Hook(worker, message): void
-
-
-
-
-
-
-
-
+- Defined in src/pools/abstract-pool.ts:386
+
-
-
+
+
-
+- constructor
+- emitter
+- file
Path
+- max
+- number
Of Workers
+- opts
+- promise
Response Map
+- worker
Choice Strategy Context
+- worker
Nodes
+- busy
+- full
+- number
Of Queued Tasks
+- number
Of Running Tasks
+- type
+- after
Task Execution Hook
+- after
Worker Setup
+- before
Task Execution Hook
+- choose
Worker Node
+- create
And Setup Worker
+- create
Worker
+- destroy
+- destroy
Worker
+- enable
Tasks Queue
+- execute
+- internal
Busy
+- is
Main
+- register
Worker Message Listener
+- send
To Worker
+- set
Tasks Queue Options
+- set
Worker Choice Strategy
+- set
Worker Choice Strategy Options
+- setup
Hook
+- worker
Listener
+
+
Hook executed after the worker task promise resolution. +
Hook executed after the worker task execution. Can be overridden.
Parameters
message: MessageValue<Response, unknown>
-The received message.
+worker: Worker
+The worker.
promise: PromiseWorkerResponseWrapper<Worker, Response>
-The Promise response.
+message: MessageValue<Response, unknown>
+The received message.
Returns void
Inherited from FixedClusterPool.afterPromiseWorkerResponseHook
+Inherited from FixedClusterPool.afterTaskExecutionHook
-- Defined in src/pools/abstract-pool.ts:263
Worker Setup
-Protected
after-- after
Worker Setup(worker: Worker): void
+
+- after
Worker Setup(worker): void
-
-
-
+
-
-
+
Inherit Doc
Function that can be hooked up when a worker has been newly created and moved to the pool worker nodes.
+Can be used to update the
+maxListeners
or binding themain-worker
<->worker
connection if not bind by default.Parameters
worker: Worker
worker: Worker
+The newly created worker.
+Returns void
Inherited from FixedClusterPool.afterWorkerSetup
-- Defined in src/pools/cluster/fixed.ts:89
Promise Worker Response Hook
-Protected
before-- before
Promise Worker Response Hook(worker: Worker): void
+- Defined in src/pools/cluster/fixed.ts:93
Task Execution Hook
+Protected
before+- before
Task Execution Hook(workerNodeKey): void
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
-
Hook executed before the worker task promise resolution. +
Hook executed before the worker task execution. Can be overridden.
Parameters
worker: Worker
-The worker.
+workerNodeKey: number
+The worker node key.
Returns void
Inherited from FixedClusterPool.beforePromiseWorkerResponseHook
+Inherited from FixedClusterPool.beforeTaskExecutionHook
-- Defined in src/pools/abstract-pool.ts:252
Worker
-Protected
choose-- choose
Worker(): Worker
+- Defined in src/pools/abstract-pool.ts:375
Worker Node
+Protected
choose+- choose
Worker Node(): [number, WorkerNode<Worker, Data>]
-
-
-
-
+
-
+- Defined in src/pools/abstract-pool.ts:419
+
-
-
+
+
-
-
-
-
-
-
+
+
Chooses a worker for the next task.
-The default implementation uses a round robin algorithm to distribute the load.
+Chooses a worker node for the next task.
+The default uses a round robin algorithm to distribute the load.
-Returns
Worker.
+Returns
[worker node key, worker node].
Returns Worker
Inherited from FixedClusterPool.chooseWorker
+Returns [number, WorkerNode<Worker, Data>]
Inherited from FixedClusterPool.chooseWorkerNode
-- Defined in src/pools/abstract-pool.ts:290
And Setup Worker
-Protected
create-- create
And Setup Worker(): Worker
+
+- create
And Setup Worker(): Worker
-
-
-
+
-
+- Defined in src/pools/abstract-pool.ts:481
+
-
+- Defined in src/pools/cluster/fixed.ts:88
+
-
-
+
+
Creates a new worker for this pool and sets it up completely.
+Creates a new worker and sets it up completely in the pool worker nodes.
Returns
New, completely set up worker.
Returns Worker
Returns Worker
Inherited from FixedClusterPool.createAndSetupWorker
-- Defined in src/pools/abstract-pool.ts:344
Worker
-Protected
create-- create
Worker(): Worker
+
+- create
Worker(): Worker
-
-
-
-
+
+
Inherit Doc
Returns Worker
Returns a newly created worker.
+Returns Worker
Inherited from FixedClusterPool.createWorker
-- Defined in src/pools/cluster/fixed.ts:84
destroy
--- destroy(): Promise<void>
+
+- destroy(): Promise<void>
-
-
-
-
+
+
Inherit Doc
Returns Promise<void>
Shutdowns every current worker in this pool.
+Returns Promise<void>
Inherited from FixedClusterPool.destroy
-- Defined in src/pools/abstract-pool.ts:222
destroy Worker
--- destroy
Worker(worker: Worker): void
+- Defined in src/pools/abstract-pool.ts:338
Worker
+Protected
destroy+- destroy
Worker(worker): void
-
-
-
+
-
-
+
Inherit Doc
Shutdowns the given worker.
+Parameters
worker: Worker
worker: Worker
+A worker within
+workerNodes
.Returns void
Inherited from FixedClusterPool.destroyWorker
-- Defined in src/pools/cluster/fixed.ts:65
execute
--- execute(data: Data): Promise<Response>
+- Defined in src/pools/cluster/fixed.ts:69
enable Tasks Queue
++- enable
Tasks Queue(enable, tasksQueueOptions?): void
-
-
-
-
-
-
-
Inherit Doc
Parameters
---
-
data: Data
Returns Promise<Response>
Inherited from FixedClusterPool.execute
--- Defined in src/pools/abstract-pool.ts:210
find Free Worker
--- find
Free Worker(): false | Worker
--
-
-
-
-
Inherit Doc
Returns false | Worker
Inherited from FixedClusterPool.findFreeWorker
--- Defined in src/pools/abstract-pool.ts:199
get Worker Average Tasks Run Time
--- get
Worker Average Tasks Run Time(worker: Worker): undefined | number
--
-
-
+
-
-
-
-
Inherit Doc
Enables/disables the worker tasks queue in this pool.
+Parameters
worker: Worker
Returns undefined | number
Inherited from FixedClusterPool.getWorkerAverageTasksRunTime
--- Defined in src/pools/abstract-pool.ts:171
get Worker Index
--- get
Worker Index(worker: Worker): number
--
-
-
-
-
-
-
Inherit Doc
Parameters
-+
-
-
enable: boolean
+Whether to enable or disable the worker tasks queue.
+worker: Worker
Returns number
Inherited from FixedClusterPool.getWorkerIndex
+
+Optional
tasksQueueOptions: TasksQueueOptionsThe worker tasks queue options.
+Returns void
Inherited from FixedClusterPool.enableTasksQueue
-- Defined in src/pools/abstract-pool.ts:161
get Worker Running Tasks
--- get
Worker Running Tasks(worker: Worker): undefined | number
--
-
-
-
-
-
-
Inherit Doc
Parameters
---
-
worker: Worker
Returns undefined | number
Inherited from FixedClusterPool.getWorkerRunningTasks
--- Defined in src/pools/abstract-pool.ts:166
init Worker Tasks Usage
--- init
Worker Tasks Usage(worker: Worker): void
+- Defined in src/pools/abstract-pool.ts:254
execute
++- execute(data?): Promise<Response>
-
-
-
-
-
-
+
-
-
-
-
+
+
-
+- Defined in src/pools/abstract-pool.ts:298
+
-
-
+
+
-
-
+
-
-
-
-
-
-
+
+
-
+- Defined in src/pools/abstract-pool.ts:218
+
+
+
-
+- Defined in src/pools/cluster/fixed.ts:59
+
-
+- Defined in src/pools/abstract-pool.ts:504
+
+
-
-
Initializes tasks usage statistics.
+Executes the function specified in the worker constructor with the task data input parameter.
+ +Returns
Promise that will be fulfilled when the task is completed.
Parameters
worker: Worker
-The worker.
+
+Optional
data: DataThe task input data for the specified worker function. This can only be serializable data.
Returns void
Inherited from FixedClusterPool.initWorkerTasksUsage
+Returns Promise<Response>
Inherited from FixedClusterPool.execute
-- Defined in src/pools/abstract-pool.ts:470
Execute
-Protected
internal-- internal
Execute(worker: Worker, messageId: number): Promise<Response>
--
-
-
-
-
Parameters
---
-
--
-
worker: Worker
messageId: number
Returns Promise<Response>
Inherited from FixedClusterPool.internalExecute
--- Defined in src/pools/abstract-pool.ts:315
Get Busy Status
-Protected
internal-- internal
Get Busy Status(): boolean
+- Defined in src/pools/abstract-pool.ts:307
Busy
+Protected
internal+- internal
Busy(): boolean
-
-
Returns boolean
Inherited from FixedClusterPool.internalGetBusyStatus
+Inherited from FixedClusterPool.internalBusy
-- Defined in src/pools/abstract-pool.ts:191
Main
-Protected
is-- is
Main(): boolean
+
+- is
Main(): boolean
-
-
-
+
Inherit Doc
Should return whether the worker is the main worker or not.
+Returns boolean
Inherited from FixedClusterPool.isMain
-- Defined in src/pools/cluster/fixed.ts:60
register Worker Message Listener
--- register
Worker Message Listener<Message>(worker: Worker, listener: ((message: MessageValue<Message, unknown>) => void)): void
+- Defined in src/pools/cluster/fixed.ts:64
Worker Message Listener
+Protected
register+- register
Worker Message Listener<Message>(worker, listener): void
-
-
-
+
-
-
+
Inherit Doc
Registers a listener callback on the given worker.
+Type Parameters
Message
Message
Parameters
worker: Worker
worker: Worker
+The worker which should register a listener.
+listener: ((message: MessageValue<Message, unknown>) => void)
+listener: ((message) => void)
+The message listener callback.
+-- (message: MessageValue<Message, unknown>): void
+
+- (message): void
-
-
-
+
Parameters
message: MessageValue<Message, unknown>
message: MessageValue<Message, unknown>
Returns void
Returns void
Inherited from FixedClusterPool.registerWorkerMessageListener
-- Defined in src/pools/cluster/fixed.ts:76
Worker
-Protected
remove-- remove
Worker(worker: Worker): void
+- Defined in src/pools/cluster/fixed.ts:80
To Worker
+Protected
send+- send
To Worker(worker, message): void
-
-
-
-
+-
+
-
-
-
+
+
-
-
+- Defined in src/pools/abstract-pool.ts:266
+
Removes the given worker from the pool.
+Sends a message to the given worker.
Parameters
worker: Worker
-Worker that will be removed.
+worker: Worker
+The worker which should receive the message.
+message: MessageValue<Data, unknown>
+The message.
Returns void
Inherited from FixedClusterPool.removeWorker
+Inherited from FixedClusterPool.sendToWorker
-- Defined in src/pools/abstract-pool.ts:277
To Worker
-Protected
send-- send
To Worker(worker: Worker, message: MessageValue<Data, unknown>): void
+- Defined in src/pools/cluster/fixed.ts:75
set Tasks Queue Options
++- set
Tasks Queue Options(tasksQueueOptions): void
-
-
-
+
-
-
--
-
+
Inherit Doc
Sets the worker tasks queue options in this pool.
+Parameters
worker: Worker
message: MessageValue<Data, unknown>
tasksQueueOptions: TasksQueueOptions
+The worker tasks queue options.
+Returns void
Inherited from FixedClusterPool.sendToWorker
+Inherited from FixedClusterPool.setTasksQueueOptions
-- Defined in src/pools/cluster/fixed.ts:71
set Worker Choice Strategy
--- set
Worker Choice Strategy(workerChoiceStrategy: "ROUND_ROBIN" | "LESS_RECENTLY_USED" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN"): void
+
+- set
Worker Choice Strategy(workerChoiceStrategy, workerChoiceStrategyOptions?): void
-
-
-
+
-
-
+
+-
+
Inherit Doc
Sets the worker choice strategy in this pool.
+Parameters
workerChoiceStrategy: "ROUND_ROBIN" | "LESS_RECENTLY_USED" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN"
workerChoiceStrategy: "ROUND_ROBIN" | "LESS_USED" | "LESS_BUSY" | "FAIR_SHARE" | "WEIGHTED_ROUND_ROBIN"
+The worker choice strategy.
+
+Optional
workerChoiceStrategyOptions: WorkerChoiceStrategyOptionsThe worker choice strategy options.
+Returns void
Inherited from FixedClusterPool.setWorkerChoiceStrategy
-- Defined in src/pools/abstract-pool.ts:176
set Worker Choice Strategy Options
++- set
Worker Choice Strategy Options(workerChoiceStrategyOptions): void
+-
+
+
+
+
+
Sets the worker choice strategy options in this pool.
+Parameters
++-
+
workerChoiceStrategyOptions: WorkerChoiceStrategyOptions
+The worker choice strategy options.
+Returns void
Inherited from FixedClusterPool.setWorkerChoiceStrategyOptions
++- Defined in src/pools/abstract-pool.ts:244
Hook
-Protected
setup-- setup
Hook(): void
+
+- setup
Hook(): void
-
-
-
+
Inherit Doc
Setup hook to execute code before worker node are created in the abstract constructor. +Can be overridden
+Returns void
Inherited from FixedClusterPool.setupHook
-- Defined in src/pools/cluster/fixed.ts:53
Listener
-Protected
worker-- worker
Listener(): ((message: MessageValue<Response, unknown>) => void)
+
+- worker
Listener(): ((message) => void)
-
-
--
-
This function is the listener registered for each worker.
+This function is the listener registered for each worker message.
Returns
The listener function to execute when a message is received from a worker.
Returns ((message: MessageValue<Response, unknown>) => void)
+Returns ((message) => void)
-- (message: MessageValue<Response, unknown>): void
+
+- (message): void
-
-
@@ -625,15 +613,16 @@ Can be overridden.
-
-
+
This function is the listener registered for each worker.
+This function is the listener registered for each worker message.
Returns
The listener function to execute when a message is received from a worker.
Parameters
message: MessageValue<Response, unknown>
message: MessageValue<Response, unknown>
Returns void
Inherited from FixedClusterPool.workerListener
-- Defined in src/pools/abstract-pool.ts:368
-
+Settings
Settings
Member Visibility
Theme
+
On This Page
-- poolifier
-
Generated using TypeDoc