/** * Deallocates the work queue */ STATIC void WKQ_Free(WorkQueue * q) { ASSERT(QUEUE_IsEmpty(&q->submit)); ASSERT(QUEUE_IsEmpty(&q->items)); ASSERT(q->flags & WKQ_DEAD); EVENT_Destroy(&q->stopEvent); EVENT_Destroy(&q->event); MUTEX_Destroy(&q->mutex); MEM_Free(q); }
/** * Returns the last queue entry or NULL if queue is empty */ QEntry * QUEUE_Last(Queue * q) { if (!QUEUE_IsEmpty(q)) { return q->head.prev; } return NULL; }
/** * Returns the first queue entry or NULL if queue is empty */ QEntry * QUEUE_First(Queue * q) { if (!QUEUE_IsEmpty(q)) { return q->head.next; } return NULL; }
alt_u32 QUEUE_Pop(QUEUE_STRUCT *pQueue){ alt_u32 data32; if (QUEUE_IsEmpty(pQueue)) return 0; data32 = pQueue->data[pQueue->rear]; pQueue->rear = (pQueue->rear+1)%pQueue->num; return data32; }
/** * Waits until all work items associated with this work queue are done ane * deallocates the work queue. */ void WKQ_Delete(WorkQueue * q) { if (q) { WKQ_Stop(q, True); if (q->flags & WKQ_KILLME) { ASSERT(QUEUE_Size(&q->items) == 1); } else { ASSERT(QUEUE_IsEmpty(&q->items)); WKQ_Free(q); } } }
/** * Creates the read-only iterator which doesn't support remove operation */ Iterator * QUEUE_ConstIterator(const Queue * q) { if (QUEUE_IsEmpty(q)) { return ITR_Empty(); } else { QueueIterator * qi = MEM_New(QueueIterator); if (qi) { ITR_Init(&qi->itr, &queueConstIterator); qi->entry = NULL; qi->next = q->head.next; return &qi->itr; } else { return NULL; } } }
/** * Creates the iterator */ Iterator * QUEUE_Iterator(Queue * q) { if (QUEUE_IsEmpty(q)) { return ITR_Empty(); } else { QueueIterator * qi = MEM_New(QueueIterator); if (qi) { ITR_Init(&qi->itr, &queueIterator); qi->entry = NULL; qi->next = QUEUE_First(q); return &qi->itr; } else { return NULL; } } }
void ICACHE_FLASH_ATTR MQTT_Task(os_event_t *e) { MQTT_Client* client = (MQTT_Client*)e->par; uint8_t dataBuffer[MQTT_BUF_SIZE]; uint16_t dataLen; if(e->par == 0) return; switch(client->connState){ case TCP_RECONNECT_REQ: break; case TCP_RECONNECT: MQTT_Connect(client); INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); client->connState = TCP_CONNECTING; break; case MQTT_DATA: if(QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { break; } if(QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0){ client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); client->sendTimeout = MQTT_SEND_TIMOUT; INFO("MQTT: Sending, type: %d, id: %04X\r\n",client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); if(client->security){ espconn_secure_sent(client->pCon, dataBuffer, dataLen); } else{ espconn_sent(client->pCon, dataBuffer, dataLen); } client->mqtt_state.outbound_message = NULL; break; } break; case TCP_CONNECTING_ERROR: MQTT_Disconnect(client); MQTT_exit(client); break; } }
void FUNCTION_ATTRIBUTE MQTT_Task(MQTT_Client *client) { INFO("MQTT TASK: state: %d\n", client->connState); uint8_t dataBuffer[MQTT_BUF_SIZE]; uint16_t dataLen; struct data_buf buffer; if(client == NULL) return; switch(client->connState){ case TCP_RECONNECT_REQ: break; case TCP_RECONNECT: MQTT_Connect(client); INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); client->connState = TCP_CONNECTING; break; case MQTT_DATA: INFO("MQTT TASK DATA\n"); if(QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { break; } if(QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0){ INFO("%s, dataLen:%d\n", __func__, dataLen); client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); client->sendTimeout = MQTT_SEND_TIMOUT; buffer.length = dataLen; buffer.data = dataBuffer; INFO("MQTT: Sending, type: %d, id: %04X\r\n",client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); net_tcp_send(client->pCon, buffer, client->sendTimeout); client->mqtt_state.outbound_message = NULL; break; } break; case TCP_CONNECTING_ERROR: MQTT_Disconnect(client); MQTT_exit(client); break; } }
void WKQ_Shutdown() { if ((--WKQ.initcount) == 0) { while (WKQ.waitpool) { Waiter * next = WKQ.waitpool->next; EVENT_Destroy(&WKQ.waitpool->event); MEM_Free(WKQ.waitpool); WKQ.waitpool = next; WKQ.nwait--; } ASSERT(WKQ.nwait == 0); while (!QUEUE_IsEmpty(&WKQ.itempool)) { QEntry * e = QUEUE_RemoveHead(&WKQ.itempool); WorkItem * w = QCAST(e,WorkItem,itemsQ); MEM_Free(w); } MUTEX_Destroy(&WKQ.mutex); THREAD_Shutdown(); } }
bool MTC_GetStatus(MTC_INFO *p, alt_u8 *Event, alt_u8 *TouchNum, int *X1, int *Y1, int *X2, int *Y2) { bool bFind; MTC_EVENT *pEvent; if (!p) return FALSE; bFind = QUEUE_IsEmpty(p->pQueue)?FALSE:TRUE; if (bFind){ pEvent = (MTC_EVENT *)QUEUE_Pop(p->pQueue); *Event = pEvent->Event; *TouchNum = pEvent->TouchNum; *X1 = pEvent->x1; *Y1 = pEvent->y1; *X2 = pEvent->x2; *Y2 = pEvent->y2; free(pEvent); } return bFind; }
/** * Returns work item from the pool, allocates a new one if needed. */ STATIC WorkItem * WKQ_GetWorkItem(WorkQueueModule * mod, WorkQueue * q, WorkProc cb, WorkProc2 cb2, void * p1, void * p2) { WorkItem * w = NULL; ASSERT(mod->initcount > 0); /* can't use QUEUE_IsEmpty without synchronization */ if (!mod->itempool.size) { MUTEX_Lock(&mod->mutex); if (!QUEUE_IsEmpty(&mod->itempool)) { w = QCAST(QUEUE_RemoveHead(&mod->itempool),WorkItem,itemsQ); w->flags = 0; } MUTEX_Unlock(&mod->mutex); } if (!w) { w = MEM_New(WorkItem); if (w) { memset(w, 0, sizeof(*w)); } } if (w) { if (MUTEX_Lock(&q->mutex)) { w->proc = cb; w->proc2 = cb2; w->param = p1; w->param2 = p2; QUEUE_InsertTail(&q->items,&w->itemsQ); MUTEX_Unlock(&q->mutex); return w; } MEM_Free(w); } return NULL; }
void ICACHE_FLASH_ATTR MQTT_Task(os_event_t *e) { MQTT_Client* client = (MQTT_Client*)e->par; uint8_t dataBuffer[MQTT_BUF_SIZE]; uint16_t dataLen; if (e->par == 0) return; switch (client->connState) { case TCP_RECONNECT_REQ: break; case TCP_RECONNECT: mqtt_tcpclient_delete(client); MQTT_Connect(client); INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); client->connState = TCP_CONNECTING; break; case MQTT_DELETING: case TCP_DISCONNECTING: case TCP_RECONNECT_DISCONNECTING: if (client->security) { #ifdef MQTT_SSL_ENABLE espconn_secure_disconnect(client->pCon); #else INFO("TCP: Do not support SSL\r\n"); #endif } else { espconn_disconnect(client->pCon); } break; case TCP_DISCONNECTED: INFO("MQTT: Disconnected\r\n"); mqtt_tcpclient_delete(client); break; case MQTT_DELETED: INFO("MQTT: Deleted client\r\n"); mqtt_client_delete(client); break; case MQTT_KEEPALIVE_SEND: mqtt_send_keepalive(client); break; case MQTT_DATA: if (QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { break; } if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0) { client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); client->sendTimeout = MQTT_SEND_TIMOUT; INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); if (client->security) { #ifdef MQTT_SSL_ENABLE espconn_secure_send(client->pCon, dataBuffer, dataLen); #else INFO("TCP: Do not support SSL\r\n"); #endif } else { espconn_send(client->pCon, dataBuffer, dataLen); } client->mqtt_state.outbound_message = NULL; break; } break; } }
/** * The worker thread */ STATIC void WKQ_Thread(void * par) { WorkQueue * q = (WorkQueue *)par; TRACE("WKQ: starting\n"); /* start the loop */ MUTEX_Lock(&q->mutex); q->lastActivity = TIME_Now(); while ((q->flags & WKQ_ACTIVE) || !QUEUE_IsEmpty(&q->submit)) { QEntry * e; while ((e = QUEUE_RemoveHead(&q->submit)) != NULL) { WorkItem * w = QCAST(e,WorkItem,submitQ); ASSERT(!(w->flags & (WKI_DONE|WKI_CANCELED))); /* * NULL callback may be used by dummy work items whose purpose * is to wait until all pending work items have been processed */ if (w->proc) { /* update flags */ w->flags |= WKI_CALL; /* invoke the handler */ MUTEX_Unlock(&q->mutex); w->proc(w, w->param); MUTEX_Lock(&q->mutex); q->lastActivity = TIME_Now(); if (w->flags & WKI_DETACHED) { /* put the work item to the pool or deallocate it */ ASSERT(!w->waiters); QUEUE_RemoveEntry(&w->itemsQ); WKQ_ReleaseWorkItem(&WKQ, w); } else { /* * update flags. Note that we released the mutex when * were invoking the callback. Therefore, this work * item could be re-submitted to the queue. Or it could * be re-submitted and then canceled. In such cases we * don't need to set the WKI_DONE flag. */ w->flags &= ~WKI_CALL; if (!(w->flags & WKI_CANCELED) && !w->submitQ.queue) { w->flags |= WKI_DONE; } /* signal the events associated with the work item */ WKI_Signal(w); } } else { /* it's a dummy work item. Just release the waiters */ WKI_Signal(w); } } /* wait for a signal */ if (q->flags & WKQ_ACTIVE) { EVENT_Reset(&q->event); if (q->idleProc) { /* we have an idle timeout */ IdleProc idle = q->idleProc; void * param = q->idleParam; Time now = TIME_Now(); Time deadline = q->lastActivity + q->idleTimeout; if (deadline > now) { MUTEX_Unlock(&q->mutex); switch (EVENT_TimeWait(&q->event,(long)(deadline-now))) { case WAIT_STATE_OK: /* don't invoke idle callback */ MUTEX_Lock(&q->mutex); break; case WAIT_STATE_TIMEOUT: /* invoke idle callback */ MUTEX_Lock(&q->mutex); now = TIME_Now(); deadline = q->lastActivity + q->idleTimeout; if (deadline <= now) { MUTEX_Unlock(&q->mutex); q->lastActivity = now; idle(q, param); MUTEX_Lock(&q->mutex); } break; default: case WAIT_STATE_ERROR: /* terminate the thread on error */ MUTEX_Lock(&q->mutex); q->flags &= ~WKQ_ACTIVE; break; } } else { q->lastActivity = now; MUTEX_Unlock(&q->mutex); idle(q, param); MUTEX_Lock(&q->mutex); } } else { /* wait forever */ MUTEX_Unlock(&q->mutex); EVENT_Wait(&q->event); MUTEX_Lock(&q->mutex); } } } /* cleanup */ MUTEX_Unlock(&q->mutex); TRACE("WKQ: done\n"); if (q->flags & WKQ_KILLME) { TRACE1("WKQ: killing WorkQueue %p\n",q); WKQ_Free(q); } }