[1/6] qmgr: Add infrastructure for background file transferring. [take 5]
Dan Hipschman
dsh at linux.ucla.edu
Thu Mar 13 17:54:01 CDT 2008
In this one, ServiceMain waits for the thread to terminate (which it does
if it sees stop_event set) before stopping the service.
---
dlls/qmgr/job.c | 1 +
dlls/qmgr/qmgr.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++
dlls/qmgr/qmgr.h | 5 +++-
dlls/qmgr/service.c | 21 ++++++++++++++++++-
4 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/dlls/qmgr/job.c b/dlls/qmgr/job.c
index 6bc63f4..2fbf1bc 100644
--- a/dlls/qmgr/job.c
+++ b/dlls/qmgr/job.c
@@ -139,6 +139,7 @@ static HRESULT WINAPI BITS_IBackgroundCopyJob_Resume(
&& This->state != BG_JOB_STATE_TRANSFERRING)
{
This->state = BG_JOB_STATE_QUEUED;
+ SetEvent(globalMgr.jobEvent);
}
LeaveCriticalSection(&globalMgr.cs);
diff --git a/dlls/qmgr/qmgr.c b/dlls/qmgr/qmgr.c
index b0a6013..9a52ad3 100644
--- a/dlls/qmgr/qmgr.c
+++ b/dlls/qmgr/qmgr.c
@@ -130,6 +130,7 @@ static const IBackgroundCopyManagerVtbl BITS_IBackgroundCopyManager_Vtbl =
BackgroundCopyManagerImpl globalMgr = {
&BITS_IBackgroundCopyManager_Vtbl,
{ NULL, -1, 0, 0, 0, 0 },
+ NULL,
LIST_INIT(globalMgr.jobs)
};
@@ -140,3 +141,57 @@ HRESULT BackgroundCopyManagerConstructor(IUnknown *pUnkOuter, LPVOID *ppObj)
*ppObj = (IBackgroundCopyManager *) &globalMgr;
return S_OK;
}
+
+DWORD WINAPI fileTransfer(void *param)
+{
+ BackgroundCopyManagerImpl *qmgr = &globalMgr;
+ HANDLE events[2] = {qmgr->jobEvent, stop_event};
+
+ for (;;)
+ {
+ BackgroundCopyJobImpl *job, *jobCur;
+ BOOL haveJob = FALSE;
+
+ WaitForMultipleObjects(2, events, FALSE, INFINITE);
+ /* Check if it's the stop_event */
+ if (WaitForSingleObject(stop_event, 0) == WAIT_OBJECT_0)
+ return 0;
+
+ /* Note that other threads may add files to the job list, but only
+ this thread ever deletes them so we don't need to worry about jobs
+ magically disappearing from the list. */
+ EnterCriticalSection(&qmgr->cs);
+
+ LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
+ {
+ if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED)
+ {
+ list_remove(&job->entryFromQmgr);
+ IBackgroundCopyJob_Release((IBackgroundCopyJob *) job);
+ }
+ else if (job->state == BG_JOB_STATE_QUEUED)
+ {
+ haveJob = TRUE;
+ break;
+ }
+ else if (job->state == BG_JOB_STATE_CONNECTING
+ || job->state == BG_JOB_STATE_TRANSFERRING)
+ {
+ ERR("Invalid state for job %p: %d\n", job, job->state);
+ }
+ }
+
+ if (!haveJob)
+ ResetEvent(qmgr->jobEvent);
+
+ LeaveCriticalSection(&qmgr->cs);
+
+ if (haveJob)
+ {
+ FIXME("Actually process job %p; setting error state\n", job);
+ EnterCriticalSection(&qmgr->cs);
+ job->state = BG_JOB_STATE_ERROR;
+ LeaveCriticalSection(&qmgr->cs);
+ }
+ }
+}
diff --git a/dlls/qmgr/qmgr.h b/dlls/qmgr/qmgr.h
index a584694..fce84d9 100644
--- a/dlls/qmgr/qmgr.h
+++ b/dlls/qmgr/qmgr.h
@@ -81,8 +81,9 @@ typedef struct
typedef struct
{
const IBackgroundCopyManagerVtbl *lpVtbl;
- /* Protects job list and job states */
+ /* Protects job list, job states, and jobEvent */
CRITICAL_SECTION cs;
+ HANDLE jobEvent;
struct list jobs;
} BackgroundCopyManagerImpl;
@@ -91,6 +92,7 @@ typedef struct
const IClassFactoryVtbl *lpVtbl;
} ClassFactoryImpl;
+extern HANDLE stop_event;
extern ClassFactoryImpl BITS_ClassFactory;
extern BackgroundCopyManagerImpl globalMgr;
@@ -104,6 +106,7 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
LPVOID *ppObj);
HRESULT EnumBackgroundCopyFilesConstructor(LPVOID *ppObj,
IBackgroundCopyJob* copyJob);
+DWORD WINAPI fileTransfer(void *param);
/* Little helper functions */
static inline char *
diff --git a/dlls/qmgr/service.c b/dlls/qmgr/service.c
index 5e31b8f..e20fc94 100644
--- a/dlls/qmgr/service.c
+++ b/dlls/qmgr/service.c
@@ -28,10 +28,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
+HANDLE stop_event;
+
static WCHAR qmgr_nameW[] = {'B','I','T','S',0};
static SERVICE_STATUS_HANDLE status_handle;
static SERVICE_STATUS status;
-static HANDLE stop_event = NULL;
static VOID
UpdateStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
@@ -108,6 +109,8 @@ StartCount(void)
VOID WINAPI
ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
{
+ HANDLE fileTxThread;
+ DWORD threadId;
TRACE("\n");
stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
@@ -129,9 +132,25 @@ ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
return;
}
+ globalMgr.jobEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+ if (!globalMgr.jobEvent) {
+ ERR("Couldn't create event: error %d\n", GetLastError());
+ UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
+ return;
+ }
+
+ fileTxThread = CreateThread(NULL, 0, fileTransfer, NULL, 0, &threadId);
+ if (!fileTxThread)
+ {
+ ERR("Failed starting file transfer thread\n");
+ UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
+ return;
+ }
+
UpdateStatus(SERVICE_RUNNING, NO_ERROR, 0);
WaitForSingleObject(stop_event, INFINITE);
+ WaitForSingleObject(fileTxThread, INFINITE);
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
CloseHandle(stop_event);
TRACE("service stoped\n");
More information about the wine-patches
mailing list