]> git.sur5r.net Git - freertos/commitdiff
Update the task pool demo to show re-use of recyclable jobs
authorgaurav-aws <gaurav-aws@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Fri, 19 Jul 2019 00:02:45 +0000 (00:02 +0000)
committergaurav-aws <gaurav-aws@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Fri, 19 Jul 2019 00:02:45 +0000 (00:02 +0000)
The example now creates a recyclable job, schedules it and returns it
back to the task pool when it is done. It then again creates a
recyclable job and ensures that the task pool the same job present
it its cache.

git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2687 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/task_pool/DemoTasks/SimpleTaskPoolExamples.c

index 49924537e8a2316a95912e4d6ee36d4c5c853dfb..e7fb1e070cca3fadb4b3c0c791c76d6ef1f9be0b 100644 (file)
 created. */\r
 #define tpTASK_POOL_WORKER_PRIORITY            1\r
 \r
-/* The number of jobs created in the example functions that create more than\r
-one job. */\r
-#define tpJOBS_TO_CREATE       5\r
-\r
 /*\r
  * Prototypes for the functions that demonstrate the task pool API.\r
  * See the implementation of the prvTaskPoolDemoTask() function within this file\r
@@ -75,27 +71,27 @@ static void prvTaskPoolDemoTask( void *pvParameters );
 /*-----------------------------------------------------------*/\r
 \r
 /* Parameters used to create the system task pool - see TBD for more information\r
-as the task pool used in this example is a slimmed down version of the full\r
-library - the slimmed down version being intended specifically for FreeRTOS\r
-kernel use cases. */\r
+ * as the task pool used in this example is a slimmed down version of the full\r
+ * library - the slimmed down version being intended specifically for FreeRTOS\r
+ * kernel use cases. */\r
 static const IotTaskPoolInfo_t xTaskPoolParameters = {\r
                                                                                                                /* Minimum number of threads in a task pool.\r
-                                                                                                               Note the slimmed down version of the task\r
-                                                                                                               pool used by this library does not autoscale\r
-                                                                                                               the number of tasks in the pool so in this\r
-                                                                                                               case this sets the number of tasks in the\r
-                                                                                                               pool. */\r
+                                                                                                                * Note the slimmed down version of the task\r
+                                                                                                                * pool used by this library does not autoscale\r
+                                                                                                                * the number of tasks in the pool so in this\r
+                                                                                                                * case this sets the number of tasks in the\r
+                                                                                                                * pool. */\r
                                                                                                                2,\r
                                                                                                                /* Maximum number of threads in a task pool.\r
-                                                                                                               Note the slimmed down version of the task\r
-                                                                                                               pool used by this library does not autoscale\r
-                                                                                                               the number of tasks in the pool so in this\r
-                                                                                                               case this parameter is just ignored. */\r
+                                                                                                                * Note the slimmed down version of the task\r
+                                                                                                                * pool used by this library does not autoscale\r
+                                                                                                                * the number of tasks in the pool so in this\r
+                                                                                                                * case this parameter is just ignored. */\r
                                                                                                                2,\r
                                                                                                                /* Stack size for every task pool thread - in\r
-                                                                                                               bytes, hence multiplying by the number of bytes\r
-                                                                                                               in a word as configMINIMAL_STACK_SIZE is\r
-                                                                                                               specified in words. */\r
+                                                                                                                * bytes, hence multiplying by the number of bytes\r
+                                                                                                                * in a word as configMINIMAL_STACK_SIZE is\r
+                                                                                                                * specified in words. */\r
                                                                                                                configMINIMAL_STACK_SIZE * sizeof( portSTACK_TYPE ),\r
                                                                                                                /* Priority for every task pool thread. */\r
                                                                                                                tpTASK_POOL_WORKER_PRIORITY,\r
@@ -106,13 +102,13 @@ static const IotTaskPoolInfo_t xTaskPoolParameters = {
 void vStartSimpleTaskPoolDemo( void )\r
 {\r
        /* This example uses a single application task, which in turn is used to\r
-       create and send jobs to task pool tasks. */\r
+        * create and send jobs to task pool tasks. */\r
        xTaskCreate( prvTaskPoolDemoTask,               /* Function that implements the task. */\r
                                 "PoolDemo",                            /* Text name for the task - only used for debugging. */\r
                                 configMINIMAL_STACK_SIZE,      /* Size of stack (in words, not bytes) to allocate for the task. */\r
                                 NULL,                                          /* Task parameter - not used in this case. */\r
                                 tskIDLE_PRIORITY,                      /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */\r
-                                NULL );                                        /* Used to pass out a handle to the created tsak - not used in this case. */\r
+                                NULL );                                        /* Used to pass out a handle to the created task - not used in this case. */\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -125,49 +121,49 @@ uint32_t ulLoops = 0;
        ( void ) pvParameters;\r
 \r
        /* The task pool must be created before it can be used.  The system task\r
-       pool is the task pool managed by the task pool library itself - the storage\r
-       used by the task pool is provided by the library. */\r
+        * pool is the task pool managed by the task pool library itself - the storage\r
+        * used by the task pool is provided by the library. */\r
        xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\r
        configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
        /* Attempting to create the task pool again should then appear to succeed\r
-       (in case it is initialised by more than one library), but have no effect. */\r
+        * (in case it is initialised by more than one library), but have no effect. */\r
        xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\r
        configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
        for( ;; )\r
        {\r
                /* Demonstrate the most basic use case where a non persistent job is\r
-               created and scheduled to run immediately.  The task pool worker tasks\r
-               (in which the job callback function executes) have a priority above the\r
-               priority of this task so the job's callback executes as soon as it is\r
-               scheduled. */\r
+                * created and scheduled to run immediately.  The task pool worker tasks\r
+                * (in which the job callback function executes) have a priority above the\r
+                * priority of this task so the job's callback executes as soon as it is\r
+                * scheduled. */\r
                prvExample_BasicSingleJob();\r
 \r
                /* Demonstrate a job being scheduled to run at some time in the\r
-               future, and how a job scheduled to run in the future can be cancelled if\r
-               it has not yet started executing.  */\r
+                * future, and how a job scheduled to run in the future can be cancelled\r
+                * if it has not yet started executing.  */\r
                prvExample_DeferredJobAndCancellingJobs();\r
 \r
                /* Demonstrate the most basic use of a recyclable job.  This is similar\r
-               to prvExample_BasicSingleJob() but using a recyclable job.  Creating a\r
-               recyclable job will re-use a previously created and now spare job from\r
-               the task pool's job cache if one is available, or otherwise dynamically\r
-               create a new job if a spare job is not available in the cache but space\r
-               remains in the cache. */\r
+                * to prvExample_BasicSingleJob() but using a recyclable job.  Creating a\r
+                * recyclable job will re-use a previously created and now spare job from\r
+                * the task pool's job cache if one is available, or otherwise dynamically\r
+                * create a new job if a spare job is not available in the cache but space\r
+                * remains in the cache. */\r
                prvExample_BasicRecyclableJob();\r
 \r
-               /* Demonstrate multiple recyclable jobs being created, used, and then\r
-               re-used.  In this the task pool worker tasks (in which the job callback\r
-               functions execute) have a priority above the priority of this task so\r
-               the job's callback functions execute as soon as they are scheduled. */\r
+               /* Demonstrate a recyclable job being created, used, and then re-used.\r
+                * In this the task pool worker tasks (in which the job callback\r
+                * functions execute) have a priority above the priority of this task so\r
+                * the job's callback functions execute as soon as they are scheduled. */\r
                prvExample_ReuseRecyclableJobFromLowPriorityTask();\r
 \r
-               /* Again demonstrate multiple recyclable jobs being used, but this time\r
-               the priority of the task pool worker tasks (in which the job callback\r
-               functions execute) are lower than the priority of this task so the job's\r
-               callback functions don't execute until this task enteres the blocked\r
-               state. */\r
+               /* Again demonstrate a recyclable job being created, used, and then\r
+                * re-usedbut this time the priority of the task pool worker tasks (in\r
+                * which the job callback functions execute) are lower than the priority\r
+                * of this task so the job's callback functions don't execute until this\r
+                * task enters the blocked state. */\r
                prvExample_ReuseRecyclableJobFromHighPriorityTask();\r
 \r
                ulLoops++;\r
@@ -183,7 +179,7 @@ uint32_t ulLoops = 0;
 static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext )\r
 {\r
 /* The jobs context is the handle of the task to which a notification should\r
-be sent. */\r
+ * be sent. */\r
 TaskHandle_t xTaskToNotify = ( TaskHandle_t ) pUserContext;\r
 \r
        /* Remove warnings about unused parameters. */\r
@@ -207,15 +203,15 @@ size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();
 IotTaskPoolJobStatus_t xJobStatus;\r
 \r
        /* Don't expect any notifications to be pending yet. */\r
-       configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
 \r
        /* Create and schedule a job using the handle of this task as the job's\r
-       context and the function that sends a notification to the task handle as\r
-       the jobs callback function.  This is not a recyclable job so the storage\r
-       required to hold information about the job is provided by this task - in\r
-       this case the storage is on the stack of this task so no memory is allocated\r
-       dynamically but the stack frame must remain in scope for the lifetime of\r
-       the job. */\r
+        * context and the function that sends a notification to the task handle as\r
+        * the job's callback function.  This is not a recyclable job so the storage\r
+        * required to hold information about the job is provided by this task - in\r
+        * this case the storage is on the stack of this task so no memory is allocated\r
+        * dynamically but the stack frame must remain in scope for the lifetime of\r
+        * the job. */\r
        xResult = IotTaskPool_CreateJob(  prvSimpleTaskNotifyCallback, /* Callback function. */\r
                                                                          ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */\r
                                                                          &xJobStorage,\r
@@ -227,22 +223,22 @@ IotTaskPoolJobStatus_t xJobStatus;
        configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
 \r
        /* This is not a persistent (recyclable) job and its storage is on the\r
-       stack of this function, so the amount of heap space available should not\r
-       have chanced since entering this function. */\r
+        * stack of this function, so the amount of heap space available should not\r
+        * have changed since entering this function. */\r
        configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() );\r
 \r
        /* In the full task pool implementation the first parameter is used to\r
-       pass the handle of the task pool to schedule.  The lean task pool\r
-       implementation used in this demo only supports a single task pool, which\r
-       is created internally within the library, so the first parameter is NULL. */\r
+        * pass the handle of the task pool to schedule.  The lean task pool\r
+        * implementation used in this demo only supports a single task pool, which\r
+        * is created internally within the library, so the first parameter is NULL. */\r
        xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags );\r
        configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
        /* Look for the notification coming from the job's callback function.  The\r
-       priority of the task pool worker task that executes the callback is higher\r
-       than the priority of this task so a block time is not needed - the task pool\r
-       worker task     pre-empts this task and sends the notification (from the job's\r
-       callback) as soon as the job is scheduled. */\r
+        * priority of the task pool worker task that executes the callback is higher\r
+        * than the priority of this task so a block time is not needed - the task pool\r
+        * worker task preempts this task and sends the notification (from the job's\r
+        * callback) as soon as the job is scheduled. */\r
        ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay );\r
        configASSERT( ulReturn );\r
 \r
@@ -265,12 +261,12 @@ size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();
 IotTaskPoolJobStatus_t xJobStatus;\r
 \r
        /* Don't expect any notifications to be pending yet. */\r
-       configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
 \r
        /* Create a job using the handle of this task as the job's context and the\r
-       function that sends a notification to the task handle as the jobs callback\r
-       function.  The job is created using storage allocated on the stack of this\r
-       function - so no memory is allocated. */\r
+        * function that sends a notification to the task handle as the job's callback\r
+        * function.  The job is created using storage allocated on the stack of this\r
+        * function - so no memory is allocated. */\r
        xResult = IotTaskPool_CreateJob(  prvSimpleTaskNotifyCallback, /* Callback function. */\r
                                                                          ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */\r
                                                                          &xJobStorage,\r
@@ -282,49 +278,49 @@ IotTaskPoolJobStatus_t xJobStatus;
        configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
 \r
        /* This is not a persistent (recyclable) job and its storage is on the\r
-       stack of this function, so the amount of heap space available should not\r
-       have chanced since entering this function. */\r
+        * stack of this function, so the amount of heap space available should not\r
+        * have changed since entering this function. */\r
        configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() );\r
 \r
-       /* Schedule the job to run its callback in xShortDelay_ms milliseconds time.\r
-       In the full task pool implementation the first parameter is used to     pass the\r
-       handle of the task pool to schedule.  The lean task pool implementation used\r
-       in this demo only supports a single task pool, which is created internally\r
-       within the library, so the first parameter is NULL. */\r
+       /* Schedule the job to run its callback in ulShortDelay_ms milliseconds time.\r
+        * In the full task pool implementation the first parameter is used to  pass the\r
+        * handle of the task pool to schedule.  The lean task pool implementation used\r
+        * in this demo only supports a single task pool, which is created internally\r
+        * within the library, so the first parameter is NULL. */\r
        xResult = IotTaskPool_ScheduleDeferred( NULL, xJob, ulShortDelay_ms );\r
        configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
        /* The scheduled job should not have executed yet, so don't expect any\r
-       notifications and expect the job's status to be 'deferred'. */\r
+        * notifications and expect the job's status to be 'deferred'. */\r
        ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay );\r
        configASSERT( ulReturn == 0 );\r
        IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
        configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_DEFERRED );\r
 \r
-       /* As the job has not yet been executed it can be stopped. */\r
+       /* As the job has not yet been executed it can be cancelled. */\r
        xResult = IotTaskPool_TryCancel( NULL, xJob, &xJobStatus );\r
        configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
        IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
        configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_CANCELED );\r
 \r
        /* Schedule the job again, and this time wait until its callback is\r
-       executed (the callback function sends a notification to this task) to see\r
-       that it executes at the right time. */\r
+        * executed (the callback function sends a notification to this task) to see\r
+        * that it executes at the right time. */\r
        xTimeBefore = xTaskGetTickCount();\r
        xResult = IotTaskPool_ScheduleDeferred( NULL, xJob, ulShortDelay_ms );\r
        configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
        /* Wait twice the deferred execution time to ensure the callback is executed\r
-       before the call below times out. */\r
+        * before the call below times out. */\r
        ulReturn = ulTaskNotifyTake( pdTRUE, pdMS_TO_TICKS( ulShortDelay_ms * 2UL ) );\r
        xElapsedTime = xTaskGetTickCount() - xTimeBefore;\r
 \r
-       /* A single notification should not have been received... */\r
+       /* A single notification should have been received... */\r
        configASSERT( ulReturn == 1 );\r
 \r
        /* ...and the time since scheduling the job should be greater than or\r
-       equal to the deferred execution time - which is converted to ticks for\r
-       comparison. */\r
+        * equal to the deferred execution time - which is converted to ticks for\r
+        * comparison. */\r
        xShortDelay_ticks = pdMS_TO_TICKS( ulShortDelay_ms );\r
        configASSERT( ( xElapsedTime >= xShortDelay_ticks ) && ( xElapsedTime  < ( xShortDelay_ticks + xAllowableMargin ) ) );\r
 }\r
@@ -340,19 +336,19 @@ const TickType_t xNoDelay = ( TickType_t ) 0;
 size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
 \r
        /* Don't expect any notifications to be pending yet. */\r
-       configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
 \r
        /* Create and schedule a job using the handle of this task as the job's\r
-       context and the function that sends a notification to the task handle as\r
-       the jobs callback function.  The job is created as a recyclable job and in\r
-       this case the memory used to hold the job status is allocated inside the\r
-       create function.  As the job is persistent it can be used multiple times,\r
-       as demonstrated in other examples within this demo.  In the full task pool\r
-       implementation the first parameter is used to pass the handle of the task\r
-       pool this recyclable job is to be associated with.  In the lean\r
-       implementation of the task pool used by this demo there is only one task\r
-       pool (the system task pool created within the task pool library) so the\r
-       first parameter is NULL. */\r
+        * context and the function that sends a notification to the task handle as\r
+        * the job's callback function.  The job is created as a recyclable job and in\r
+        * this case the memory used to hold the job status is allocated inside the\r
+        * create function.  As the job is persistent it can be used multiple times,\r
+        * as demonstrated in other examples within this demo.  In the full task pool\r
+        * implementation the first parameter is used to pass the handle of the task\r
+        * pool this recyclable job is to be associated with.  In the lean\r
+        * implementation of the task pool used by this demo there is only one task\r
+        * pool (the system task pool created within the task pool library) so the\r
+        * first parameter is NULL. */\r
        xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
                                                                                           prvSimpleTaskNotifyCallback,\r
                                                                                           (void * ) xTaskGetCurrentTaskHandle(),\r
@@ -360,34 +356,34 @@ size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();
        configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
        /* This recyclable job is persistent, and in this case created dynamically,\r
-       so expect there to be less heap space then when entering the function. */\r
+        * so expect there to be less heap space than when entering the function. */\r
        configASSERT( xPortGetFreeHeapSize() < xFreeHeapBeforeCreatingJob );\r
 \r
        /* In the full task pool implementation the first parameter is used to\r
-       pass the handle of the task pool to schedule.  The lean task pool\r
-       implementation used in this demo only supports a single task pool, which\r
-       is created internally within the library, so the first parameter is NULL. */\r
+        * pass the handle of the task pool to schedule.  The lean task pool\r
+        * implementation used in this demo only supports a single task pool, which\r
+        * is created internally within the library, so the first parameter is NULL. */\r
        xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags );\r
        configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
        /* Look for the notification coming from the job's callback function.  The\r
-       priority of the task pool worker task that executes the callback is higher\r
-       than the priority of this task so a block time is not needed - the task pool\r
-       worker task     pre-empts this task and sends the notification (from the job's\r
-       callback) as soon as the job is scheduled. */\r
+        * priority of the task pool worker task that executes the callback is higher\r
+        * than the priority of this task so a block time is not needed - the task pool\r
+        * worker task  preempts this task and sends the notification (from the job's\r
+        * callback) as soon as the job is scheduled. */\r
        ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay );\r
        configASSERT( ulReturn );\r
 \r
        /* Clean up recyclable job.  In the full implementation of the task pool\r
-       the first parameter is used to pass a handle to the task pool the job is\r
-       associated with.  In the lean implementation of the task pool used by this\r
-       demo there is only one task pool (the system task pool created in the\r
-       task pool library itself) so the first parameter is NULL. */\r
+        * the first parameter is used to pass a handle to the task pool the job is\r
+        * associated with.  In the lean implementation of the task pool used by this\r
+        * demo there is only one task pool (the system task pool created in the\r
+        * task pool library itself) so the first parameter is NULL. */\r
        IotTaskPool_DestroyRecyclableJob( NULL, xJob );\r
 \r
        /* Once the job has been deleted the memory used to hold the job is\r
-       returned, so the available heap should be exactly as when entering this\r
-       function. */\r
+        * returned, so the available heap should be exactly as when entering this\r
+        * function. */\r
        configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob );\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -395,106 +391,127 @@ size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();
 static void prvExample_ReuseRecyclableJobFromLowPriorityTask( void )\r
 {\r
 IotTaskPoolError_t xResult;\r
-uint32_t x, xIndex, ulNotificationValue;\r
+uint32_t ulNotificationValue;\r
 const uint32_t ulNoFlags = 0UL;\r
-IotTaskPoolJob_t xJobs[ tpJOBS_TO_CREATE ];\r
-size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
+IotTaskPoolJob_t xJob, xJobRecycled;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(), xFreeHeapAfterCreatingJob = 0;\r
 IotTaskPoolJobStatus_t xJobStatus;\r
 \r
        /* Don't expect any notifications to be pending yet. */\r
-       configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
-\r
-       /* Create tpJOBS_TO_CREATE jobs using the handle of this task as the job's\r
-       context and the function that sends a notification to the task handle as\r
-       the jobs callback function.  The jobs are created as a recyclable job and\r
-       in this case the memory to store the job information is allocated within\r
-       the create function as at this time there are no recyclable jobs in the\r
-       task pool jobs cache. As the jobs are persistent they can be used multiple\r
-       times.  In the full task pool implementation the first parameter is used to\r
-       pass the handle of the task pool this recyclable job is to be associated\r
-       with.  In the lean implementation of the task pool used by this demo there\r
-       is only one task pool (the system task pool created within the task pool\r
-       library) so the first parameter is NULL. */\r
-       for( x = 0; x < tpJOBS_TO_CREATE; x++ )\r
-       {\r
-               xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
-                                                                                                  prvSimpleTaskNotifyCallback,\r
-                                                                                                  (void * ) xTaskGetCurrentTaskHandle(),\r
-                                                                                                  &( xJobs[ x ] ) );\r
-               configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
-\r
-               /* The job has been created but not scheduled so is now ready. */\r
-               IotTaskPool_GetStatus( NULL, xJobs[ x ], &xJobStatus );\r
-               configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
-       }\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
+\r
+       /* Create a recycleable job using the handle of this task as the job's\r
+        * context and the function that sends a notification to the task handle as\r
+        * the job's callback function.  In the full task pool implementation the\r
+        * first parameter is used to pass the handle of the task pool this\r
+        * recyclable job is to be associated with.  In the lean implementation of\r
+        * the task pool used by this demo there is only one task pool (the system\r
+        * task pool created within the task pool library) so the first parameter is\r
+        * NULL. */\r
+       xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+                                                                                          prvSimpleTaskNotifyCallback,\r
+                                                                                          (void * ) xTaskGetCurrentTaskHandle(),\r
+                                                                                          &( xJob ) );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
-       /* Demonstrate that the jobs can be recycled by performing twice the number\r
-       of iterations of scheduling jobs than there actually are created jobs.  This\r
-       works because the task pool task priorities are above the priority of this\r
-       task, so the tasks that run the jobs pre-empt this task as soon as a job is\r
-       ready. */\r
-       for( x = 0; x < ( tpJOBS_TO_CREATE * 2UL ); x++ )\r
-       {\r
-               /* Make sure array index does not go out of bounds. */\r
-               xIndex = x % tpJOBS_TO_CREATE;\r
-\r
-               xResult = IotTaskPool_Schedule( NULL, xJobs[ xIndex ], ulNoFlags );\r
-               configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
-\r
-               /* The priority of the task pool task(s) is higher than the priority\r
-               of this task, so the job's callback function should have already\r
-               executed, sending a notification to this task, and incrementing this\r
-               task's notification value. */\r
-               xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
-                                                0UL, /* Don't clear any bits on exit. */\r
-                                                &ulNotificationValue, /* Obtain the notification value. */\r
-                                                0UL ); /* No block time, return immediately. */\r
-               configASSERT( ulNotificationValue == ( x + 1 ) );\r
-\r
-               /* The job's callback has executed so the job is now completed. */\r
-               IotTaskPool_GetStatus( NULL, xJobs[ xIndex ], &xJobStatus );\r
-               configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
-\r
-               /* To leave the list of jobs empty we can stop re-creating jobs half\r
-               way through iterations of this loop. */\r
-               if( x < tpJOBS_TO_CREATE )\r
-               {\r
-                       /* Recycle the job so it can be used again.  In the full task pool\r
-                       implementation the first parameter is used to pass the handle of the\r
-                       task pool this job will be associated with.  In this lean task pool\r
-                       implementation only the system task pool exists (the task pool created\r
-                       internally to the task pool library) so the first parameter is just\r
-                       passed as NULL. *//*_RB_ Why not recycle it automatically? */\r
-                       IotTaskPool_RecycleJob( NULL, xJobs[ xIndex ] );\r
-                       xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
-                                                                                                          prvSimpleTaskNotifyCallback,\r
-                                                                                                          (void * ) xTaskGetCurrentTaskHandle(),\r
-                                                                                                          &( xJobs[ xIndex ] ) );\r
-                       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
-               }\r
-       }\r
+       /* The job is created as a recyclable job and in this case the memory to\r
+        * store the job information is allocated within the create function as at\r
+        * this time there are no recyclable jobs in the task pool jobs cache. So\r
+        * expect there to be less heap space than when entering the function. */\r
+       xFreeHeapAfterCreatingJob = xPortGetFreeHeapSize();\r
+       configASSERT( xFreeHeapAfterCreatingJob < xFreeHeapBeforeCreatingJob );\r
+\r
+       /* The job has been created but not scheduled so is now ready. */\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
+\r
+       /* In the full task pool implementation the first parameter is used to\r
+        * pass the handle of the task pool to schedule.  The lean task pool\r
+        * implementation used in this demo only supports a single task pool, which\r
+        * is created internally within the library, so the first parameter is NULL. */\r
+       xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* The priority of the task pool task(s) is higher than the priority\r
+        * of this task, so the job's callback function should have already\r
+        * executed, sending a notification to this task, and incrementing this\r
+        * task's notification value. */\r
+       xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                        0UL, /* Don't clear any bits on exit. */\r
+                                        &ulNotificationValue, /* Obtain the notification value. */\r
+                                        xNoDelay ); /* No block time, return immediately. */\r
+       configASSERT( ulNotificationValue == 1 );\r
+\r
+       /* The job's callback has executed so the job is now completed. */\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
 \r
-       /* Clear all the notification value bits again. */\r
+       /* Return the job to the task pool's job cache. */\r
+       IotTaskPool_RecycleJob( NULL, xJob );\r
+\r
+       /* Create a recycleable job again using the handle of this task as the job's\r
+        * context and the function that sends a notification to the task handle as\r
+        * the job's callback function.  In the full task pool implementation the\r
+        * first parameter is used to pass the handle of the task pool this\r
+        * recyclable job is to be associated with.  In the lean implementation of\r
+        * the task pool used by this demo there is only one task pool (the system\r
+        * task pool created within the task pool library) so the first parameter is\r
+        * NULL. */\r
+       xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+                                                                                          prvSimpleTaskNotifyCallback,\r
+                                                                                          (void * ) xTaskGetCurrentTaskHandle(),\r
+                                                                                          &( xJobRecycled ) );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* Since this time the task pool's job cache had a recycleable job, it must\r
+        * have been re-used. Thefore expect the free heap space to be same as after\r
+        * the creation of first job */\r
+       configASSERT( xPortGetFreeHeapSize() == xFreeHeapAfterCreatingJob );\r
+\r
+       /* Expect the task pool to re-use the job in its cache as opposed to\r
+        * allocating a new one. */\r
+       configASSERT( xJobRecycled == xJob );\r
+\r
+       /* In the full task pool implementation the first parameter is used to\r
+        * pass the handle of the task pool to schedule.  The lean task pool\r
+        * implementation used in this demo only supports a single task pool, which\r
+        * is created internally within the library, so the first parameter is NULL. */\r
+       xResult = IotTaskPool_Schedule( NULL, xJobRecycled, ulNoFlags );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* The priority of the task pool task(s) is higher than the priority\r
+        * of this task, so the job's callback function should have already\r
+        * executed, sending a notification to this task, and incrementing this\r
+        * task's notification value. */\r
+       xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                        0UL, /* Don't clear any bits on exit. */\r
+                                        &ulNotificationValue, /* Obtain the notification value. */\r
+                                        xNoDelay ); /* No block time, return immediately. */\r
+       configASSERT( ulNotificationValue == 2 );\r
+\r
+       /* The job's callback has executed so the job is now completed. */\r
+       IotTaskPool_GetStatus( NULL, xJobRecycled, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
+\r
+       /* Clean up the recyclable job.  In the full implementation of the task\r
+        * pool the first parameter is used to pass a handle to the task pool the job\r
+        * is associated with.  In the lean implementation of the task pool used by\r
+        * this demo there is only one task pool (the system task pool created in the\r
+        * task pool library itself) so the first parameter is NULL. */\r
+       xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobRecycled );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* Clear all the notification value bits ready for the next example. */\r
        xTaskNotifyWait( portMAX_DELAY, /* Clear all bits on entry - portMAX_DELAY is used as it is a portable way of having all bits set. */\r
                                         0UL, /* Don't clear any bits on exit. */\r
                                         NULL, /* Don't need the notification value this time. */\r
-                                        0UL ); /* No block time, return immediately. */\r
-       configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
-\r
-       /* Clean up all the recyclable job.  In the full implementation of the task\r
-       pool the first parameter is used to pass a handle to the task pool the job\r
-       is associated with.  In the lean implementation of the task pool used by\r
-       this demo there is only one task pool (the system task pool created in the\r
-       task pool library itself) so the first parameter is NULL. */\r
-       for( x = 0; x < tpJOBS_TO_CREATE; x++ )\r
-       {\r
-               xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobs[ x ] );\r
-               configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
-       }\r
+                                        xNoDelay ); /* No block time, return immediately. */\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
 \r
        /* Once the job has been deleted the memory used to hold the job is\r
-       returned, so the available heap should be exactly as when entering this\r
-       function. */\r
+        * returned, so the available heap should be exactly as when entering this\r
+        * function. */\r
        configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob );\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -502,98 +519,178 @@ IotTaskPoolJobStatus_t xJobStatus;
 static void prvExample_ReuseRecyclableJobFromHighPriorityTask( void )\r
 {\r
 IotTaskPoolError_t xResult;\r
-uint32_t x, ulNotificationValue;\r
+uint32_t ulNotificationValue;\r
 const uint32_t ulNoFlags = 0UL;\r
-IotTaskPoolJob_t xJobs[ tpJOBS_TO_CREATE ];\r
-IotTaskPoolJobStorage_t xJobStorage[ tpJOBS_TO_CREATE ];\r
-size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
 TickType_t xShortDelay = pdMS_TO_TICKS( 150 );\r
+IotTaskPoolJob_t xJob, xJobRecycled;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(), xFreeHeapAfterCreatingJob = 0;\r
 IotTaskPoolJobStatus_t xJobStatus;\r
 \r
        /* Don't expect any notifications to be pending yet. */\r
-       configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
 \r
        /* prvExample_ReuseRecyclableJobFromLowPriorityTask() executes in a task\r
-       that has a lower [task] priority than the task pool's worker tasks.\r
-       Therefore a talk pool worker preempts the task that calls\r
-       prvExample_ReuseRecyclableJobFromHighPriorityTask() as soon as the job is\r
-       scheduled.  prvExample_ReuseRecyclableJobFromHighPriorityTask() reverses the\r
-       priorities - prvExample_ReuseRecyclableJobFromHighPriorityTask() raises its\r
-       priority to above the task pool's worker tasks, so the worker tasks do not\r
-       execute until the calling task enters the blocked state.  First raise the\r
-       priority - passing NULL means raise the priority of the calling task. */\r
+        * that has a lower [task] priority than the task pool's worker tasks.\r
+        * Therefore a task pool worker preempts the task that calls\r
+        * prvExample_ReuseRecyclableJobFromHighPriorityTask() as soon as the job is\r
+        * scheduled.  prvExample_ReuseRecyclableJobFromHighPriorityTask() reverses the\r
+        * priorities - prvExample_ReuseRecyclableJobFromHighPriorityTask() raises its\r
+        * priority to above the task pool's worker tasks, so the worker tasks do not\r
+        * execute until the calling task enters the blocked state.  First raise the\r
+        * priority - passing NULL means raise the priority of the calling task. */\r
        vTaskPrioritySet( NULL, tpTASK_POOL_WORKER_PRIORITY + 1 );\r
 \r
-       /* Create tpJOBS_TO_CREATE jobs using the handle of this task as the job's\r
-       context and the function that sends a notification to the task handle as\r
-       the jobs callback function. */\r
-       for( x = 0; x < tpJOBS_TO_CREATE; x++ )\r
-       {\r
-               xResult = IotTaskPool_CreateJob(  prvSimpleTaskNotifyCallback, /* Callback function. */\r
-                                                                                 ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */\r
-                                                                                 &( xJobStorage[ x ] ),\r
-                                                                                 &( xJobs[ x ] ) );\r
-               configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
-\r
-               /* This is not a persistent (recyclable) job and its storage is on the\r
-               stack of this function, so the amount of heap space available should not\r
-               have chanced since entering this function. */\r
-               configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() );\r
-       }\r
+       /* Create a recycleable job using the handle of this task as the job's\r
+        * context and the function that sends a notification to the task handle as\r
+        * the job's callback function.  In the full task pool implementation the\r
+        * first parameter is used to pass the handle of the task pool this\r
+        * recyclable job is to be associated with.  In the lean implementation of\r
+        * the task pool used by this demo there is only one task pool (the system\r
+        * task pool created within the task pool library) so the first parameter is\r
+        * NULL. */\r
+       xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+                                                                                          prvSimpleTaskNotifyCallback,\r
+                                                                                          (void * ) xTaskGetCurrentTaskHandle(),\r
+                                                                                          &( xJob ) );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
-       for( x = 0; x < tpJOBS_TO_CREATE; x++ )\r
-       {\r
-               /* Schedule the next job. */\r
-               xResult = IotTaskPool_Schedule( NULL, xJobs[ x ], ulNoFlags );\r
-               configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
-\r
-               /* Although scheduled, the job's callback has not executed, so the job\r
-               reports itself as scheduled. */\r
-               IotTaskPool_GetStatus( NULL, xJobs[ x ], &xJobStatus );\r
-               configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_SCHEDULED );\r
-\r
-               /* The priority of the task pool task(s) is lower than the priority\r
-               of this task, so the job's callback function should not have executed\r
-               yes, so don't expect the notification value for this task to have\r
-               changed. */\r
-               xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
-                                                0UL, /* Don't clear any bits on exit. */\r
-                                                &ulNotificationValue, /* Obtain the notification value. */\r
-                                                0UL ); /* No block time, return immediately. */\r
-               configASSERT( ulNotificationValue == 0 );\r
-       }\r
+       /* The job is created as a recyclable job and in this case the memory to\r
+        * store the job information is allocated within the create function as at\r
+        * this time there are no recyclable jobs in the task pool jobs cache. So\r
+        * expect there to be less heap space than when entering the function. */\r
+       xFreeHeapAfterCreatingJob = xPortGetFreeHeapSize();\r
+       configASSERT( xFreeHeapAfterCreatingJob < xFreeHeapBeforeCreatingJob );\r
 \r
-       /* At this point there are tpJOBS_TO_CREATE scheduled, but none have executed\r
-       their callbacks because the priority of this task is higher than the\r
-       priority of the task pool worker threads.  When this task blocks to wait for\r
-       a notification a worker thread will be able to executes - but as soon as its\r
-       callback function sends a notification to this task this task will\r
-       preempt it (because it has a higher priority) so this task only expects to\r
-       receive one notification at a time. */\r
-       for( x = 0; x < tpJOBS_TO_CREATE; x++ )\r
-       {\r
-               xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
-                                                0UL, /* Don't clear any bits on exit. */\r
-                                                &ulNotificationValue, /* Obtain the notification value. */\r
-                                                xShortDelay ); /* Short delay to allow a task pool worker to execute. */\r
-               configASSERT( ulNotificationValue == ( x + 1 ) );\r
-       }\r
+       /* The job has been created but not scheduled so is now ready. */\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
+\r
+       /* In the full task pool implementation the first parameter is used to\r
+        * pass the handle of the task pool to schedule.  The lean task pool\r
+        * implementation used in this demo only supports a single task pool, which\r
+        * is created internally within the library, so the first parameter is NULL. */\r
+       xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* The priority of the task pool task(s) is lower than the priority\r
+        * of this task, so the job's callback function should not have executed\r
+        * yet, so don't expect the notification value for this task to have\r
+        * changed. */\r
+       xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                        0UL, /* Don't clear any bits on exit. */\r
+                                        &ulNotificationValue, /* Obtain the notification value. */\r
+                                        xNoDelay ); /* No block time, return immediately. */\r
+       configASSERT( ulNotificationValue == 0 );\r
+\r
+       /* When this task blocks to wait for a notification, a worker thread will be\r
+        * able to execute - but as soon as its callback function sends a\r
+        * notification to this task, this task will preempt it (because it has a\r
+        * higher priority). So this task expects to receive one notification. */\r
+       xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                        0UL, /* Don't clear any bits on exit. */\r
+                                        &ulNotificationValue, /* Obtain the notification value. */\r
+                                        xShortDelay ); /* Short delay to allow a task pool worker to execute. */\r
+       configASSERT( ulNotificationValue == 1 );\r
+\r
+       /* Since the scheduled job has now executed, so waiting for another\r
+        * notification should timeout without the notification value changing. */\r
+       xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                        0UL, /* Don't clear any bits on exit. */\r
+                                        &ulNotificationValue, /* Obtain the notification value. */\r
+                                        xShortDelay ); /* Short delay to allow a task pool worker to execute. */\r
+       configASSERT( ulNotificationValue == 1 );\r
+\r
+       /* The job's callback has executed so the job is now completed. */\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
 \r
-       /* All the scheduled jobs have now executed, so waiting for another\r
-       notification should timeout without the notification value changing. */\r
+       /* Return the job to the task pool's job cache. */\r
+       IotTaskPool_RecycleJob( NULL, xJob );\r
+\r
+       /* Create a recycleable job again using the handle of this task as the job's\r
+        * context and the function that sends a notification to the task handle as\r
+        * the job's callback function.  In the full task pool implementation the\r
+        * first parameter is used to pass the handle of the task pool this\r
+        * recyclable job is to be associated with.  In the lean implementation of\r
+        * the task pool used by this demo there is only one task pool (the system\r
+        * task pool created within the task pool library) so the first parameter is\r
+        * NULL. */\r
+       xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+                                                                                          prvSimpleTaskNotifyCallback,\r
+                                                                                          (void * ) xTaskGetCurrentTaskHandle(),\r
+                                                                                          &( xJobRecycled ) );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* Since this time the task pool's job cache had a recycleable job, it must\r
+        * have been re-used. Thefore expect the free heap space to be same as after\r
+        * the creation of first job */\r
+       configASSERT( xPortGetFreeHeapSize() == xFreeHeapAfterCreatingJob );\r
+\r
+       /* Expect the task pool to re-use the job in its cache as opposed to\r
+        * allocating a new one. */\r
+       configASSERT( xJobRecycled == xJob );\r
+\r
+       /* In the full task pool implementation the first parameter is used to\r
+        * pass the handle of the task pool to schedule.  The lean task pool\r
+        * implementation used in this demo only supports a single task pool, which\r
+        * is created internally within the library, so the first parameter is NULL. */\r
+       xResult = IotTaskPool_Schedule( NULL, xJobRecycled, ulNoFlags );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* The priority of the task pool task(s) is lower than the priority\r
+        * of this task, so the job's callback function should not have executed\r
+        * yet, so don't expect the notification value for this task to have\r
+        * changed. */\r
+       xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                        0UL, /* Don't clear any bits on exit. */\r
+                                        &ulNotificationValue, /* Obtain the notification value. */\r
+                                        xNoDelay ); /* No block time, return immediately. */\r
+       configASSERT( ulNotificationValue == 1 );\r
+\r
+       /* When this task blocks to wait for a notification, a worker thread will be\r
+        * able to execute - but as soon as its callback function sends a\r
+        * notification to this task, this task will preempt it (because it has a\r
+        * higher priority). So this task expects to receive one notification. */\r
        xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
                                         0UL, /* Don't clear any bits on exit. */\r
                                         &ulNotificationValue, /* Obtain the notification value. */\r
                                         xShortDelay ); /* Short delay to allow a task pool worker to execute. */\r
-       configASSERT( ulNotificationValue == x );\r
+       configASSERT( ulNotificationValue == 2 );\r
 \r
-       /* Reset the priority of this task and clear the notifications ready for the\r
-       next example. */\r
+       /* Since the scheduled job has now executed, so waiting for another\r
+        * notification should timeout without the notification value changing. */\r
+       xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                        0UL, /* Don't clear any bits on exit. */\r
+                                        &ulNotificationValue, /* Obtain the notification value. */\r
+                                        xShortDelay ); /* Short delay to allow a task pool worker to execute. */\r
+       configASSERT( ulNotificationValue == 2 );\r
+\r
+       /* The job's callback has executed so the job is now completed. */\r
+       IotTaskPool_GetStatus( NULL, xJobRecycled, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
+\r
+       /* Clean up the recyclable job.  In the full implementation of the task\r
+        * pool the first parameter is used to pass a handle to the task pool the job\r
+        * is associated with.  In the lean implementation of the task pool used by\r
+        * this demo there is only one task pool (the system task pool created in the\r
+        * task pool library itself) so the first parameter is NULL. */\r
+       xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobRecycled );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* Reset this task's priority. */\r
        vTaskPrioritySet( NULL, tskIDLE_PRIORITY );\r
+\r
+       /* Clear all the notification value bits ready for the next example. */\r
        xTaskNotifyWait( portMAX_DELAY, /* Clear all bits on entry - portMAX_DELAY is used as it is a portable way of having all bits set. */\r
                                         0UL, /* Don't clear any bits on exit. */\r
                                         NULL, /* Don't need the notification value this time. */\r
-                                        0UL ); /* No block time, return immediately. */\r
+                                        xNoDelay ); /* No block time, return immediately. */\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
+\r
+       /* Once the job has been deleted the memory used to hold the job is\r
+        * returned, so the available heap should be exactly as when entering this\r
+        * function. */\r
+       configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob );\r
 }\r
 /*-----------------------------------------------------------*/\r
-\r