ClRcT clJobQueueInit(ClJobQueueT* hdl, ClUint32T maxJobs, ClUint32T maxTasks)
{
    ClRcT rc;
    hdl->flags = 0;
    hdl->queue = 0;
    hdl->pool  = 0;

    rc = clOsalMutexInit(&hdl->mutex);
    if (rc != CL_OK) goto error;

    rc = clQueueCreate(maxJobs, deleteCallback, deleteCallback, &hdl->queue);
    if (rc != CL_OK) goto error;

    rc = clTaskPoolCreate(&hdl->pool, maxTasks, clJobQueuePreIdle, hdl);
    if (rc != CL_OK) goto error;

    hdl->flags |= CreatedQueue | CreatedPool | Running;
    return CL_OK;  

    error:
    clOsalMutexDestroy(&hdl->mutex);
    if (hdl->pool) clTaskPoolDelete(hdl->pool);
    if (hdl->queue) clQueueDelete(&hdl->queue);

    hdl->queue = 0;
    hdl->pool  = 0;
    return rc;
}
ClRcT clJobQueueDelete(ClJobQueueT* hdl)
{
    if(hdl->flags & CreatedQueue) 
    {
        /*
         * Prevent parallel job queue pushes during a queue delete.
         */
        JQ_PFX(hdl);
        hdl->flags &= ~Running;
        JQ_SFX(hdl);
        clJobQueueStop(hdl);
        if (hdl->flags & CreatedPool) clTaskPoolDelete(hdl->pool);
        clQueueDelete(&hdl->queue);
        clOsalMutexDestroy(&hdl->mutex);
    }
    if (hdl->flags & CreatedJobQueue) clHeapFree(hdl);
    return CL_OK;
}
ClRcT
clTimerFinalize (void)
{
    ClRcT retCode = 0;
    CL_FUNC_ENTER();
    /* kill the timer-task */
    retCode = clOsalTaskDelete (gActiveTimerQueue.timerTaskId);

    retCode = tsActiveTimersQueueDestroy ();

    retCode = tsFreeTimersPoolDestroy ();

    /* create re-enqueue Queue */
    retCode = clQueueDelete(&(gActiveTimerQueue.reEnqueueQueue));

    CL_DEBUG_PRINT (CL_DEBUG_INFO,("\nTimer Cleanup : DONE"));
    CL_FUNC_EXIT();
    return (CL_OK);
}
/* Handle destructor function. */
static void clDispatchHandleDestructor(void* cbArgs)
{
    ClRcT   rc = CL_OK;
    ClDispatchDbEntryT* thisDbEntry = NULL;
    ClUint32T   queueSize = 0;
    ClDispatchCbQueueDataT*   queueData = NULL;

    if (cbArgs == NULL)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Handle destructor is called with NULL pointer"));
        return;
    }

    thisDbEntry = (ClDispatchDbEntryT*)cbArgs;

    /* Lock the queue mutex */
    rc = clOsalMutexLock(thisDbEntry->dispatchMutex);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to lock dispatch Mutex in Handle destructor callback"));
        return;
    }

    /*
     * Before deleting the queue you need to flush the queue.
     * Even though clQueueDelete will flush the node, we need
     * handle it explicitly so that we can invoke
     * ClDispatchQueueDestroyCallbackT registered during Register
     * which will deallocate the memory for the callback arguments.
     */
    rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize);
    if (rc != CL_OK)
    {
        goto proceed_other_functions;
    }

    while (queueSize != 0)
    {
        rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData);
        if (rc != CL_OK)
        {
            goto proceed_other_functions;
        }
        CL_ASSERT(queueData != NULL);

        /* Invoke the queue destroy callback function */
        thisDbEntry->queueDestroyCallback(queueData->callbackType,
                                          queueData->callbackArgs);

        rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize);
        if (rc != CL_OK)
        {
            goto proceed_other_functions;
        }
    }

proceed_other_functions:
    /* 
     * Delete the queue. This will also flush the queue. So all the
     * pending callbacks will be flushed.
     */
    rc = clQueueDelete(&thisDbEntry->cbQueue);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to delete the queue. Rc = 0x%x",rc));
    }
        
    /* Delete the pipe */
    errno = 0;
    if ((close(thisDbEntry->readFd)) < 0)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to close write fd of the pipe:%s",strerror(errno)));
    }

    errno = 0;
    if ((close(thisDbEntry->writeFd)) < 0)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to close read fd of the pipe:%s",strerror(errno)));
    }


    /* Delete the mutex */
    rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Failed to unlock the dispatch mutex"));
    }
    rc = clOsalMutexDelete(thisDbEntry->dispatchMutex);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Failed to delete the dispatch mutex"));
    }


    return;
}
/**
 *  Creates a new Extended State machine Instance.
 *
 *  This API creates a new Extended State macine Instance of given
 *  state machine type.  The extended state machine shall include
 *  all the regular state machine instance functionalities, plus
 *  additional event queue, history, and lock capabilities.
 *                                                                        
 *  @param sm       State machine type 
 *  @param instance [out] newly created extended state machine instance
 *
 *  @returns 
 *    CL_OK on CL_OK <br/>
 *    CL_SM_RC(CL_ERR_NO_MEMORY) on memory allocation FAILURE <br/>
 *    CL_SM_RC(CL_ERR_NULL_POINTER) on invalid/null sm / instance <br/>
 *
 *  @see #clEsmInstanceDelete
 */
ClRcT
clEsmInstanceCreate(ClSmTemplatePtrT sm, 
                  ClExSmInstancePtrT* instance
                  )
{
  ClRcT ret = CL_OK;

  CL_FUNC_ENTER();
  CL_ASSERT(instance);  
  CL_ASSERT(sm);  

  clLogTrace(ESM_LOG_AREA,ESM_LOG_CTX_CREATE,"Create Extended State Machine Instance");

  if(sm && instance) 
    {
      /* allocate the instance space */
      *instance = (ClExSmInstancePtrT) mALLOC(sizeof(ClExSmInstanceT));
      if(*instance!=0) 
        {
          memset(*instance, 0, sizeof(ClExSmInstanceT));
          /* call sm create here */
          ret = clSmInstanceCreate(sm, &(*instance)->fsm);
          if(ret == CL_OK)
            {
              ret = clOsalMutexCreate(&(*instance)->lock);
              if (CL_OK != ret)
              {
                  clSmInstanceDelete((*instance)->fsm);
                  mFREE(*instance);
                  ret = SM_ERR_NO_SEMA;
              }
              else
              {
              /* create queue and init */
              ret = SMQ_CREATE((*instance)->q);
              if(ret == CL_OK)
                {
                  /* init log buffer */
                  ESM_LOG_INIT((*instance)->log, ESM_LOG_ENTRIES);
                }
              if(!(*instance)->log.buffer || ret != CL_OK)
                {
                  /* delete the instance */
                  ret = clSmInstanceDelete((*instance)->fsm);
                  /* delete the mutex */
                  clOsalMutexDelete((*instance)->lock);
                  /* check if q init succeeded */
                  if(ret == CL_OK)
                    {
                      /* delete the queue */
                      clQueueDelete(&((*instance)->q));
                    }
                  /* free the instance */
                  mFREE(*instance);
                  ret = CL_SM_RC(CL_ERR_NO_MEMORY);
                }
              }
            }
          
        } else 
          {
            ret = CL_SM_RC(CL_ERR_NO_MEMORY);
          }
    } else 
      {
        ret = CL_SM_RC(CL_ERR_NULL_POINTER);
      }
  
  CL_FUNC_EXIT();
  return ret;
}
/** 
 *  Delete Extended State machine Instance.
 *  
 *  API to delete a previously created State macine Instance. Also
 *  frees up the events that are in the Q.
 *                                                                        
 *  @param smThis Extended State machine Instance to be deleted
 *
 *  @returns 
 *    CL_OK on CL_OK <br/>
 *    CL_SM_RC(CL_ERR_NULL_POINTER) on invalid/null instance handle <br/>
 *
 *  @see #clEsmInstanceCreate
 *
 */
ClRcT 
clEsmInstanceDelete(ClExSmInstancePtrT smThis
                 )
{
  ClRcT ret = CL_OK;

  CL_FUNC_ENTER();
  CL_ASSERT(smThis);  

  clLogTrace(ESM_LOG_AREA,ESM_LOG_CTX_DELETE,"Delete Extended State Machine Instance");

  if(smThis) 
    {
      ClUint32T sz = 0;

      if(ESM_LOCK(smThis)!=CL_OK)
        {
          ret = SM_ERR_LOCKED;
          CL_FUNC_EXIT();
          return ret;
        }

      /* free the fsm first */
      ret = clSmInstanceDelete(smThis->fsm);

      SMQ_SIZE(smThis->q, sz);
      /* Check if the queue is empty, if not, dequeue and delete them */
      if(sz > 0) 
        {
          ClSmQueueItemPtrT item;
          ClRcT rc;

          rc = SMQ_DEQUEUE(smThis->q, item);
          while(rc==CL_OK && item)
            {
              mFREE(item);
              rc = SMQ_DEQUEUE(smThis->q, item);
            }
          clLogInfo(ESM_LOG_AREA,ESM_LOG_CTX_DELETE,"***Delete: Events are present in Q! Dropped to floor!!! ***");
        }

      /* delete the queue */
      clQueueDelete(&smThis->q);

      /* free the history buffer */
      mFREE(smThis->log.buffer);

      /* unlock it before, so we can delete the mutex */
      ESM_UNLOCK(smThis);

      /* delete the mutex */
      clOsalMutexDelete(smThis->lock);

      /* free the object */
      mFREE(smThis);
    } else 
      {
        ret = CL_SM_RC(CL_ERR_NULL_POINTER);
      }

  CL_FUNC_EXIT();
  return ret;
}