Beispiel #1
0
int a3d_workq_run(a3d_workq_t* self, void* task,
                  int priority)
{
	assert(self);
	assert(task);
	LOGD("debug task=%p, priority=%i", task, priority);

	pthread_mutex_lock(&self->mutex);

	// find the node containing the task or create a new one
	int status = A3D_WORKQ_ERROR;
	a3d_listitem_t*  iter = NULL;
	a3d_listitem_t*  pos  = NULL;
	a3d_workqnode_t* tmp  = NULL;
	a3d_workqnode_t* node = NULL;
	if((iter = a3d_list_find(self->queue_complete, task,
	                         a3d_taskcmp_fn)) != NULL)
	{
		// task completed
		node = (a3d_workqnode_t*) a3d_list_remove(self->queue_complete,
		                                          &iter);
		status = node->status;
		a3d_workqnode_delete(&node);
	}
	else if((iter = a3d_list_find(self->queue_active, task,
	                              a3d_taskcmp_fn)) != NULL)
	{
		node = (a3d_workqnode_t*) a3d_list_peekitem(iter);
		node->purge_id = self->purge_id;
		status = A3D_WORKQ_PENDING;
	}
	else if((iter = a3d_list_find(self->queue_pending, task,
	                              a3d_taskcmp_fn)) != NULL)
	{
		node = (a3d_workqnode_t*) a3d_list_peekitem(iter);
		node->purge_id = self->purge_id;
		if(priority > node->priority)
		{
			// move up
			pos = a3d_list_prev(iter);
			while(pos)
			{
				tmp = (a3d_workqnode_t*) a3d_list_peekitem(pos);
				if(tmp->priority >= node->priority)
				{
					break;
				}
				pos = a3d_list_prev(pos);
			}

			if(pos)
			{
				// move after pos
				a3d_list_moven(self->queue_pending, iter, pos);
			}
			else
			{
				// move to head of list
				a3d_list_move(self->queue_pending, iter, NULL);
			}
		}
		else if(priority < node->priority)
		{
			// move down
			pos = a3d_list_next(iter);
			while(pos)
			{
				tmp = (a3d_workqnode_t*) a3d_list_peekitem(pos);
				if(tmp->priority < node->priority)
				{
					break;
				}
				pos = a3d_list_next(pos);
			}

			if(pos)
			{
				// move before pos
				a3d_list_move(self->queue_pending, iter, pos);
			}
			else
			{
				// move to tail of list
				a3d_list_moven(self->queue_pending, iter, NULL);
			}
		}
		node->priority = priority;
		status = A3D_WORKQ_PENDING;
	}
	else
	{
		// create new node
		node = a3d_workqnode_new(task, self->purge_id, priority);
		if(node == NULL)
		{
			goto fail_node;
		}
		else
		{
			// find the insert position
			pos = a3d_list_tail(self->queue_pending);
			while(pos)
			{
				tmp = (a3d_workqnode_t*) a3d_list_peekitem(pos);
				if(tmp->priority >= node->priority)
				{
					break;
				}
				pos = a3d_list_prev(pos);
			}

			if(pos)
			{
				// append after pos
				if(a3d_list_append(self->queue_pending, pos,
				                   (const void*) node) == NULL)
				{
					goto fail_queue;
				}
			}
			else
			{
				// insert at head of queue
				// first item or highest priority
				if(a3d_list_insert(self->queue_pending, NULL,
				                   (const void*) node) == NULL)
				{
					goto fail_queue;
				}
			}

			status = A3D_WORKQ_PENDING;

			// wake up workq thread
			pthread_cond_signal(&self->cond_pending);
		}
	}

	pthread_mutex_unlock(&self->mutex);

	// success
	return status;

	// failure
	fail_queue:
		a3d_workqnode_delete(&node);
	fail_node:
		pthread_mutex_unlock(&self->mutex);
	return A3D_WORKQ_ERROR;
}
Beispiel #2
0
int a3d_multimap_add(a3d_multimap_t* self,
                     const void* val,
                     const char* key)
{
	assert(self);
	assert(val);
	assert(key);

	a3d_listitem_t* item;

	// check if the list already exists
	a3d_hashmapIter_t iter;
	a3d_list_t* list;
	list = (a3d_list_t*)
	       a3d_hashmap_find(self->hash,
	                        &iter, key);
	if(list && self->compare)
	{
		item = a3d_list_insertSorted(list,
		                             self->compare,
		                             val);
		if(item == NULL)
		{
			return 0;
		}

		return 1;
	}
	else if(list)
	{
		item = a3d_list_append(list, NULL, val);
		if(item == NULL)
		{
			return 0;
		}

		return 1;
	}

	// create a new list and add to hash
	list = a3d_list_new();
	if(list == NULL)
	{
		return 0;
	}

	item = a3d_list_append(list, NULL, val);
	if(item == NULL)
	{
		goto fail_append;
	}

	if(a3d_hashmap_add(self->hash,
	                   (const void*) list,
	                   key) == 0)
	{
		goto fail_add;
	}

	// success
	return 1;

	// failure
	fail_add:
		a3d_list_remove(list, &item);
	fail_append:
		a3d_list_delete(&list);
	return 0;
}