* Number of operations that can be concurrently
* active in this queue.
*/
- unsigned int active;
+ unsigned int active;
};
+/**
+ * Operation state
+ */
enum OperationState
- {
+{
/**
* The operation is currently waiting for resources
*/
- OP_STATE_WAITING,
+ OP_STATE_WAITING,
/**
* The operation has started
*/
- OP_STATE_STARTED,
- };
-
-
+ OP_STATE_STARTED
+};
/**
* not have been started yet).
*/
OperationRelease release;
-
+
/**
* Closure for callbacks.
*/
*/
struct OperationQueue **queues;
- /**
- * The Operation ID
- */
- uint64_t id;
-
/**
* The id of the task which calls OperationStart for this operation
*/
/**
* The state of the operation
*/
- enum OperationState state;
-
+ enum OperationState state;
+
};
*/
static void
call_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
+{
struct GNUNET_TESTBED_Operation *op = cls;
-
- op->start_task_id = GNUNET_SCHEDULER_NO_TASK;
+
+ op->start_task_id = GNUNET_SCHEDULER_NO_TASK;
+ op->state = OP_STATE_STARTED;
if (NULL != op->start)
{
op->start (op->cb_cls);
}
- op->state = OP_STATE_STARTED;
}
*/
static void
check_readiness (struct GNUNET_TESTBED_Operation *op)
-{
+{
unsigned int i;
-
+
+ if (GNUNET_SCHEDULER_NO_TASK != op->start_task_id)
+ return;
for (i = 0; i < op->nqueues; i++)
{
if (0 == op->queues[i]->active)
{
op->queues[i]->active--;
}
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == op->start_task_id);
- op->start_task_id = GNUNET_SCHEDULER_add_now (&call_start, op);
+ op->start_task_id = GNUNET_SCHEDULER_add_now (&call_start, op);
+}
+
+
+/**
+ * Create an 'operation' to be performed.
+ *
+ * @param cls closure for the callbacks
+ * @param start function to call to start the operation
+ * @param release function to call to close down the operation
+ * @return handle to the operation
+ */
+struct GNUNET_TESTBED_Operation *
+GNUNET_TESTBED_operation_create_ (void *cls, OperationStart start,
+ OperationRelease release)
+{
+ struct GNUNET_TESTBED_Operation *op;
+
+ op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation));
+ op->start = start;
+ op->release = release;
+ op->cb_cls = cls;
+ op->start_task_id = GNUNET_SCHEDULER_NO_TASK;
+ return op;
}
void
GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue)
{
- GNUNET_assert (NULL == queue->head);
- GNUNET_assert (NULL == queue->tail);
+ GNUNET_break (NULL == queue->head);
+ GNUNET_break (NULL == queue->tail);
GNUNET_free (queue);
}
* Add an operation to a queue. An operation can be in multiple
* queues at once. Once all queues permit the operation to become
* active, the operation will be activated. The actual activation
- * will occur in a separate task (thus allowing multiple queue
+ * will occur in a separate task (thus allowing multiple queue
* insertions to be made without having the first one instantly
- * trigger the operation if the first queue has sufficient
+ * trigger the operation if the first queue has sufficient
* resources).
*
* @param queue queue to add the operation to
*/
void
GNUNET_TESTBED_operation_queue_insert_ (struct OperationQueue *queue,
- struct GNUNET_TESTBED_Operation *operation)
+ struct GNUNET_TESTBED_Operation
+ *operation)
{
struct QueueEntry *entry;
entry->op = operation;
GNUNET_CONTAINER_DLL_insert_tail (queue->head, queue->tail, entry);
operation->queues =
- GNUNET_realloc (operation->queues,
- sizeof (struct OperationQueue *) * (++operation->nqueues));
+ GNUNET_realloc (operation->queues,
+ sizeof (struct OperationQueue *) *
+ (++operation->nqueues));
operation->queues[operation->nqueues - 1] = queue;
check_readiness (operation);
}
*/
void
GNUNET_TESTBED_operation_queue_remove_ (struct OperationQueue *queue,
- struct GNUNET_TESTBED_Operation *operation)
+ struct GNUNET_TESTBED_Operation
+ *operation)
{
struct QueueEntry *entry;
struct QueueEntry *entry2;
-
+
for (entry = queue->head; NULL != entry; entry = entry->next)
if (entry->op == operation)
break;
GNUNET_assert (NULL != entry);
if (OP_STATE_STARTED == operation->state)
queue->active++;
- GNUNET_CONTAINER_DLL_remove (queue->head, queue->tail, entry);
entry2 = entry->next;
+ GNUNET_CONTAINER_DLL_remove (queue->head, queue->tail, entry);
GNUNET_free (entry);
for (; NULL != entry2; entry2 = entry2->next)
if (OP_STATE_STARTED != entry2->op->state)
GNUNET_TESTBED_operation_release_ (struct GNUNET_TESTBED_Operation *operation)
{
unsigned int i;
-
+
if (GNUNET_SCHEDULER_NO_TASK != operation->start_task_id)
{
GNUNET_SCHEDULER_cancel (operation->start_task_id);
operation->start_task_id = GNUNET_SCHEDULER_NO_TASK;
}
- if (NULL != operation->release)
- operation->release (operation->cb_cls);
for (i = 0; i < operation->nqueues; i++)
GNUNET_TESTBED_operation_queue_remove_ (operation->queues[i], operation);
+ GNUNET_free (operation->queues);
+ if (NULL != operation->release)
+ operation->release (operation->cb_cls);
+ GNUNET_free (operation);
}