Jacek Caban : urlmon:
Added task queue architecture and use it for OnProgress calls from
Continue call .
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Jun 1 06:48:42 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 99cb95394aaeb0a1100874a6d217d6f7810523f5
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=99cb95394aaeb0a1100874a6d217d6f7810523f5
Author: Jacek Caban <jacek at codeweavers.com>
Date: Wed May 31 19:45:16 2006 +0200
urlmon: Added task queue architecture and use it for OnProgress calls from Continue call.
---
dlls/urlmon/binding.c | 179 ++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 145 insertions(+), 34 deletions(-)
diff --git a/dlls/urlmon/binding.c b/dlls/urlmon/binding.c
index 22a4ea2..9a13002 100644
--- a/dlls/urlmon/binding.c
+++ b/dlls/urlmon/binding.c
@@ -34,9 +34,47 @@ #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
-typedef struct ProtocolStream ProtocolStream;
+typedef struct Binding Binding;
+
+enum task_enum {
+ TASK_ON_PROGRESS
+};
+
+typedef struct {
+ Binding *binding;
+ ULONG progress;
+ ULONG progress_max;
+ ULONG status_code;
+ LPWSTR status_text;
+} on_progress_data;
+
+typedef struct {
+ Binding *binding;
+ PROTOCOLDATA *data;
+} switch_data;
+
+typedef struct _task_t {
+ enum task_enum task;
+ Binding *binding;
+ struct _task_t *next;
+ union {
+ on_progress_data on_progress;
+ } data;
+} task_t;
typedef struct {
+ const IStreamVtbl *lpStreamVtbl;
+
+ LONG ref;
+
+ IInternetProtocol *protocol;
+
+ BYTE buf[1024*8];
+ DWORD buf_size;
+ BOOL init_buf;
+} ProtocolStream;
+
+struct Binding {
const IBindingVtbl *lpBindingVtbl;
const IInternetProtocolSinkVtbl *lpInternetProtocolSinkVtbl;
const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
@@ -54,23 +92,15 @@ typedef struct {
LPWSTR mime;
LPWSTR url;
BOOL verified_mime;
+ DWORD continue_call;
DWORD apartment_thread;
HWND notif_hwnd;
STGMEDIUM stgmed;
-} Binding;
-
-struct ProtocolStream {
- const IStreamVtbl *lpStreamVtbl;
-
- LONG ref;
-
- IInternetProtocol *protocol;
- BYTE buf[1024*8];
- DWORD buf_size;
- BOOL init_buf;
+ task_t *task_queue_head, *task_queue_tail;
+ CRITICAL_SECTION section;
};
#define BINDING(x) ((IBinding*) &(x)->lpBindingVtbl)
@@ -83,18 +113,62 @@ #define STREAM(x) ((IStream*) &(x)->lpSt
#define WM_MK_ONPROGRESS (WM_USER+100)
#define WM_MK_CONTINUE (WM_USER+101)
-typedef struct {
- Binding *binding;
- ULONG progress;
- ULONG progress_max;
- ULONG status_code;
- LPWSTR status_text;
-} on_progress_data;
+static void push_task(task_t *task)
+{
+ task->next = NULL;
-typedef struct {
- Binding *binding;
- PROTOCOLDATA *data;
-} switch_data;
+ EnterCriticalSection(&task->binding->section);
+
+ if(task->binding->task_queue_tail)
+ task->binding->task_queue_tail->next = task;
+ else
+ task->binding->task_queue_tail = task->binding->task_queue_head = task;
+
+ LeaveCriticalSection(&task->binding->section);
+}
+
+static task_t *pop_task(Binding *binding)
+{
+ task_t *ret;
+
+ EnterCriticalSection(&binding->section);
+
+ ret = binding->task_queue_head;
+ if(ret) {
+ binding->task_queue_head = ret->next;
+ if(!binding->task_queue_head)
+ binding->task_queue_tail = NULL;
+ }
+
+ LeaveCriticalSection(&binding->section);
+
+ return ret;
+}
+
+static void do_task(task_t *task)
+{
+ switch(task->task) {
+ case TASK_ON_PROGRESS: {
+ on_progress_data *data = &task->data.on_progress;
+
+ IBindStatusCallback_OnProgress(task->binding->callback, data->progress,
+ data->progress_max, data->status_code, data->status_text);
+
+ HeapFree(GetProcessHeap(), 0, data->status_text);
+ HeapFree(GetProcessHeap(), 0, data);
+ }
+ }
+}
+
+static void do_tasks(Binding *This)
+{
+ task_t *task;
+
+ while((task = pop_task(This))) {
+ do_task(task);
+ IBinding_Release(BINDING(task->binding));
+ }
+}
static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@@ -116,7 +190,11 @@ static LRESULT WINAPI notif_wnd_proc(HWN
case WM_MK_CONTINUE: {
switch_data *data = (switch_data*)lParam;
+ data->binding->continue_call++;
IInternetProtocol_Continue(data->binding->protocol, data->data);
+ data->binding->continue_call--;
+
+ do_tasks(data->binding);
IBinding_Release(BINDING(data->binding));
HeapFree(GetProcessHeap(), 0, data);
@@ -170,33 +248,61 @@ static HWND get_notif_hwnd(void)
static void on_progress(Binding *This, ULONG progress, ULONG progress_max,
ULONG status_code, LPCWSTR status_text)
{
- on_progress_data *data;
+ task_t *task;
+
+ if(GetCurrentThreadId() != This->apartment_thread) {
+ on_progress_data *data;
+
+ data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
+
+ IBinding_AddRef(BINDING(This));
+
+ data->binding = This;
+ data->progress = progress;
+ data->progress_max = progress_max;
+ data->status_code = status_code;
+
+ if(status_text) {
+ DWORD size = (strlenW(status_text)+1)*sizeof(WCHAR);
- if(GetCurrentThreadId() == This->apartment_thread) {
+ data->status_text = HeapAlloc(GetProcessHeap(), 0, size);
+ memcpy(data->status_text, status_text, size);
+ }else {
+ data->status_text = NULL;
+ }
+
+ PostMessageW(This->notif_hwnd, WM_MK_ONPROGRESS, 0, (LPARAM)data);
+
+ return;
+ }
+
+ if(!This->continue_call) {
IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
status_code, status_text);
return;
}
- data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
+ task = HeapAlloc(GetProcessHeap(), 0, sizeof(task_t));
+
+ task->task = TASK_ON_PROGRESS;
IBinding_AddRef(BINDING(This));
+ task->binding = This;
- data->binding = This;
- data->progress = progress;
- data->progress_max = progress_max;
- data->status_code = status_code;
+ task->data.on_progress.progress = progress;
+ task->data.on_progress.progress_max = progress_max;
+ task->data.on_progress.status_code = status_code;
if(status_text) {
DWORD size = (strlenW(status_text)+1)*sizeof(WCHAR);
- data->status_text = HeapAlloc(GetProcessHeap(), 0, size);
- memcpy(data->status_text, status_text, size);
+ task->data.on_progress.status_text = HeapAlloc(GetProcessHeap(), 0, size);
+ memcpy(task->data.on_progress.status_text, status_text, size);
}else {
- data->status_text = NULL;
+ task->data.on_progress.status_text = NULL;
}
- PostMessageW(This->notif_hwnd, WM_MK_ONPROGRESS, 0, (LPARAM)data);
+ push_task(task);
}
static void dump_BINDINFO(BINDINFO *bi)
@@ -606,6 +712,7 @@ static ULONG WINAPI Binding_Release(IBin
IStream_Release(STREAM(This->stream));
ReleaseBindInfo(&This->bindinfo);
+ DeleteCriticalSection(&This->section);
HeapFree(GetProcessHeap(), 0, This->mime);
HeapFree(GetProcessHeap(), 0, This->url);
@@ -1041,11 +1148,15 @@ static HRESULT Binding_Create(LPCWSTR ur
ret->apartment_thread = GetCurrentThreadId();
ret->notif_hwnd = get_notif_hwnd();
ret->verified_mime = FALSE;
+ ret->continue_call = 0;
+ ret->task_queue_head = ret->task_queue_tail = NULL;
memset(&ret->bindinfo, 0, sizeof(BINDINFO));
ret->bindinfo.cbSize = sizeof(BINDINFO);
ret->bindf = 0;
+ InitializeCriticalSection(&ret->section);
+
hres = get_callback(pbc, &ret->callback);
if(FAILED(hres)) {
WARN("Could not get IBindStatusCallback\n");
More information about the wine-cvs
mailing list