Module: wine Branch: refs/heads/master Commit: 99cb95394aaeb0a1100874a6d217d6f7810523f5 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=99cb95394aaeb0a1100874a6...
Author: Jacek Caban jacek@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");