[2/4] qmgr: Add infrastructure for background file transferring. [take 3]

Dan Hipschman dsh at linux.ucla.edu
Tue Mar 11 18:13:26 CDT 2008


This adds the infrastructure for processing jobs.  It using an event to signal
when jobs are ready to be processed rather than polling.

---
 dlls/qmgr/job.c     |    1 +
 dlls/qmgr/qmgr.c    |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/qmgr/qmgr.h    |    4 +++-
 dlls/qmgr/service.c |   17 +++++++++++++++++
 4 files changed, 72 insertions(+), 1 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..50f807e 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,53 @@ HRESULT BackgroundCopyManagerConstructor(IUnknown *pUnkOuter, LPVOID *ppObj)
     *ppObj = (IBackgroundCopyManager *) &globalMgr;
     return S_OK;
 }
+
+DWORD WINAPI fileTransfer(void *param)
+{
+    BackgroundCopyManagerImpl *qmgr = &globalMgr;
+
+    for (;;)
+    {
+        BackgroundCopyJobImpl *job, *jobCur;
+        BOOL haveJob = FALSE;
+
+        WaitForSingleObject(qmgr->jobEvent, INFINITE);
+
+        /* 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);
+                job->lpVtbl->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..96635a7 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;
 
@@ -104,6 +105,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..553d43c 100644
--- a/dlls/qmgr/service.c
+++ b/dlls/qmgr/service.c
@@ -108,6 +108,8 @@ StartCount(void)
 VOID WINAPI
 ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
 {
+    HANDLE fileTxThread;
+    DWORD threadId;
     TRACE("\n");
 
     stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
@@ -129,6 +131,21 @@ 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);



More information about the wine-patches mailing list