/* Copyright (c) 2015-17 Miranda NG project (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "stdafx.h" RequestQueue::RequestQueue(HNETLIBUSER hConnection) : hConnection(hConnection), requests(1) { isTerminated = true; hRequestQueueThread = NULL; hRequestQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL); } RequestQueue::~RequestQueue() { requests.destroy(); CloseHandle(hRequestQueueEvent); } void RequestQueue::Start() { if (!isTerminated) return; isTerminated = false; if (hRequestQueueThread == NULL) hRequestQueueThread = mir_forkthread((pThreadFunc)&RequestQueue::WorkerThread, this); } void RequestQueue::Stop() { if (isTerminated) return; isTerminated = true; SetEvent(hRequestQueueEvent); } void RequestQueue::Push(HttpRequest *request, HttpResponseCallback response, void *arg, HttpFinallyCallback last) { if (isTerminated) return; RequestQueueItem *item = new RequestQueueItem(request, response, arg, last); { mir_cslock lock(requestQueueLock); requests.insert(item); } SetEvent(hRequestQueueEvent); } void RequestQueue::Send(HttpRequest *request, HttpResponseCallback response, void *arg, HttpFinallyCallback last) { RequestQueueItem *item = new RequestQueueItem(request, response, arg, last); mir_forkthreadowner((pThreadFuncOwner)&RequestQueue::AsyncSendThread, this, item, 0); } void RequestQueue::Execute(RequestQueueItem *item) { HttpResponse *response = item->request->Send(hConnection); if (item->responseCallback != NULL) item->responseCallback(response, item->arg); if (item->finallyCallback != NULL) item->finallyCallback(item->arg); delete item; delete response; } unsigned int RequestQueue::AsyncSendThread(void *owner, void *arg) { RequestQueue *queue = (RequestQueue*)owner; RequestQueueItem *item = (RequestQueueItem*)arg; queue->Execute(item); return 0; } unsigned int RequestQueue::WorkerThread(void *arg) { RequestQueue *queue = (RequestQueue*)arg; while (!queue->isTerminated) { WaitForSingleObject(queue->hRequestQueueEvent, INFINITE); while (true) { RequestQueueItem *item = NULL; { mir_cslock lock(queue->requestQueueLock); if (queue->requests.getCount() == 0) break; item = queue->requests[0]; queue->requests.remove(0); } if (item != NULL) queue->Execute(item); } } queue->hRequestQueueThread = NULL; return 0; }