Example #1
0
void CBThreadPoolQueueAdd(CBThreadPoolQueue * self, CBQueueItem * item){
	item->next = NULL;
	item->active = false;
	item->cleared = false;
	// Find worker with least items to process
	uint16_t workerI = 0;
	for (uint16_t x = 1; x < self->numThreads; x++){
		CBMutexLock(self->workers[x].queueMutex);
		if (self->workers[x].queue.itemNum < self->workers[workerI].queue.itemNum)
			workerI = x;
		CBMutexUnlock(self->workers[x].queueMutex);
		// Queue may change in the meantime but this wont cause any problems
	}
	CBWorker * worker = self->workers + workerI;
	CBMutexLock(self->finishMutex);
	self->finished = false;
	CBMutexLock(worker->queueMutex);
	worker->queue.itemNum++;
	if (!worker->queue.start) {
		worker->queue.end = worker->queue.start = item;
		// We have added the first item to the queue so wake up the thread.
		assert(worker->queue.itemNum);
		CBConditionSignal(worker->waitCond);
	}else
		worker->queue.end = worker->queue.end->next = item;
	CBMutexUnlock(worker->queueMutex);
	CBMutexUnlock(self->finishMutex);
}
Example #2
0
void CBThreadPoolQueueClear(CBThreadPoolQueue * self){
	CBMutexLock(self->finishMutex);
	for (uint16_t x = 0; x < self->numThreads; x++) {
		CBMutexLock(self->workers[x].queueMutex);
		// Empty queue
		CBFreeQueue(&self->workers[x].queue, self->destroy);
		self->workers[x].queue.itemNum = 0;
		CBMutexUnlock(self->workers[x].queueMutex);
	}
	self->finished = true;
	CBConditionSignal(self->finishCond);
	CBMutexUnlock(self->finishMutex);
}
Example #3
0
void CBThreadPoolQueueThreadLoop(void * vself){
	CBWorker * self = vself;
	CBMutexLock(self->queueMutex);
	for (;;) {
		while (self->queue.itemNum == 0 && !self->threadPoolQueue->shutdown)
			// Wait for more items to process. We require a loop because when the condition is signaled, the mutex is unlocked but may not be given to this thread. Another thread may use the mutex to clear the queue again, so check in a loop.
			CBConditionWait(self->waitCond, self->queueMutex);
		assert(self->queue.itemNum || self->threadPoolQueue->shutdown);
		// Check to see if the thread should terminate
		if (self->threadPoolQueue->shutdown){
			CBMutexUnlock(self->queueMutex);
			return;
		}
		// Process the next item.
		CBQueueItem * item = self->queue.start;
		item->active = true; // Prevent deletion.
		CBMutexUnlock(self->queueMutex);
		self->threadPoolQueue->process(self->threadPoolQueue, item);
		// Now we have finished with the item, remove it from the queue
		CBMutexLock(self->queueMutex);
		// Maybe we cleared the queue. Check that it hasn't been.
		if (!item->cleared) {
			self->queue.start = item->next;
			if (--self->queue.itemNum == 0){
				// Look for complete emptiness
				CBMutexLock(self->threadPoolQueue->finishMutex);
				bool empty = true;
				for (uint16_t x = 0; x < self->threadPoolQueue->numThreads; x++)
					if (self->threadPoolQueue->workers[x].queue.itemNum) {
						empty = false;
						break;
					}
				if (empty){
					self->threadPoolQueue->finished = true;
					CBConditionSignal(self->threadPoolQueue->finishCond);
				}
				CBMutexUnlock(self->threadPoolQueue->finishMutex);
			}
		}
		// Now we can destroy the item.
		self->threadPoolQueue->destroy(item);
		free(item);
	}
}
Example #4
0
void CBDestroyNode(void * vself){
	CBNode * self = vself;
	// Exit thread.
	self->shutDownThread = true;
	CBMutexLock(self->messageProcessMutex);
	if (self->messageQueue == NULL)
		// The thread is waiting for messages so wake it.
		CBConditionSignal(self->messageProcessWaitCond);
	CBMutexUnlock(self->messageProcessMutex);
	CBThreadJoin(self->messageProcessThread);
	CBFreeBlockChainStorage(self->blockChainStorage);
	CBFreeAccounterStorage(self->accounterStorage);
	CBReleaseObject(self->validator);
	CBFreeMutex(self->blockAndTxMutex);
	CBFreeMutex(self->messageProcessMutex);
	CBFreeCondition(self->messageProcessWaitCond);
	CBFreeThread(self->messageProcessThread);
	CBDestroyNetworkCommunicator(vself);
}
Example #5
0
void CBDestroyThreadPoolQueue(CBThreadPoolQueue * self){
	self->shutdown = true;
	for (uint16_t x = 0; x < self->numThreads; x++) {
		CBMutexLock(self->workers[x].queueMutex);
		if (self->workers[x].queue.itemNum == 0)
			// The thread is waiting for items, so wake it.
			CBConditionSignal(self->workers[x].waitCond);
		CBMutexUnlock(self->workers[x].queueMutex);
		CBThreadJoin(self->workers[x].thread);
		CBFreeThread(self->workers[x].thread);
		CBFreeCondition(self->workers[x].waitCond);
		CBFreeMutex(self->workers[x].queueMutex);
		// Free queue
		CBFreeQueue(&self->workers[x].queue, self->destroy);
	}
	CBFreeCondition(self->finishCond);
	CBFreeMutex(self->finishMutex);
	free(self->workers);
}
Example #6
0
CBOnMessageReceivedAction CBNodeOnMessageReceived(CBNetworkCommunicator * comm, CBPeer * peer, CBMessage * message){
	CBNode * self = CBGetNode(comm);
	// Add message to queue
	CBRetainObject(message);
	CBRetainObject(peer);
	CBMutexLock(self->messageProcessMutex);
	if (self->messageQueue == NULL)
		self->messageQueue = self->messageQueueBack = malloc(sizeof(*self->messageQueueBack));
	else{
		self->messageQueueBack->next = malloc(sizeof(*self->messageQueueBack));
		self->messageQueueBack = self->messageQueueBack->next;
	}
	self->messageQueueBack->peer = peer;
	self->messageQueueBack->message = message;
	self->messageQueueBack->next = NULL;
	// Wakeup thread if this is the first in the queue
	if (self->messageQueue == self->messageQueueBack)
		// We have just added a block to the queue when there was not one before so wake-up the processing thread.
		CBConditionSignal(self->messageProcessWaitCond);
	CBMutexUnlock(self->messageProcessMutex);
	return CB_MESSAGE_ACTION_CONTINUE;
}