On 11/01/2011 10:10 AM, Alon Levy wrote:
This patch reuses Dispatcher in RedDispatcher. It adds two helpers
to red_worker to keep RedWorker opaque to the outside. The dispatcher is
abused in three places that use the underlying socket directly:
once sending a READY after red_init completes
once for each channel creation, replying with the RedChannel instance
for cursor and display.
exploit this opportunity to rename red_dispatcher? ->worker_dispatcher?
display_dispatcher?
Code is being added, not removed.
Readability?
wrote a script to review the patch :)
---
server/red_dispatcher.c | 585 +++++++++++++++++++++++++++------------
server/red_dispatcher.h | 182 ++++++++++++
server/red_worker.c | 716 +++++++++++++++++++++++++----------------------
server/red_worker.h | 2 +
4 files changed, 979 insertions(+), 506 deletions(-)
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 7a0033f..4680b50 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -37,6 +37,7 @@
#include "reds_gl_canvas.h"
#endif // USE_OPENGL
#include "reds.h"
+#include "dispatcher.h"
#include "red_dispatcher.h"
#include "red_parse_qxl.h"
@@ -53,7 +54,7 @@ struct AsyncCommand {
struct RedDispatcher {
QXLWorker base;
QXLInstance *qxl;
- int channel;
+ Dispatcher dispatcher;
pthread_t worker_thread;
uint32_t pending;
int primary_active;
@@ -83,24 +84,196 @@ extern spice_wan_compression_t zlib_glz_state;
static RedDispatcher *dispatchers = NULL;
+static void register_callbacks(RedDispatcher *dispatcher)
+{
+ dispatcher_register_handler(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DISPLAY_CONNECT,
+ handle_dev_display_connect,
+ sizeof(RedWorkerMessageDisplayConnect),
+ 0);
+ dispatcher_register_handler(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
+ handle_dev_display_disconnect,
+ sizeof(RedWorkerMessageDisplayDisconnect),
+ 1);
+ dispatcher_register_handler(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
+ handle_dev_display_migrate,
+ sizeof(RedWorkerMessageDisplayMigrate),
+ 0);
<snip>
.
.
.
+ dispatcher_register_handler(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_RESET_MEMSLOTS,
+ handle_dev_reset_memslots,
+ sizeof(RedWorkerMessageResetMemslots),
+ 0);
+}
+
What do you think about moving the registering the cbs to red_worker?
Then you will not need to add all the cbs prototype to red_dispatcher.h
(but you will need to expose Dispatcher to red_worker)
static void red_dispatcher_set_display_peer(RedChannel *channel, RedClient
*client,
RedsStream *stream, int migration,
int num_common_caps, uint32_t
*common_caps, int num_caps,
uint32_t *caps)
{
+ RedWorkerMessageDisplayConnect payload;
RedDispatcher *dispatcher;
red_printf("");
dispatcher = (RedDispatcher *)channel->data;
- RedWorkerMessage message = RED_WORKER_MESSAGE_DISPLAY_CONNECT;
- write_message(dispatcher->channel,&message);
- send_data(dispatcher->channel,&client, sizeof(RedClient *));
- send_data(dispatcher->channel,&stream, sizeof(RedsStream *));
- send_data(dispatcher->channel,&migration, sizeof(int));
+ payload.client = client;
+ payload.stream = stream;
+ payload.migration = migration;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DISPLAY_CONNECT,
+&payload);
}
<snip>
diff --git a/server/red_worker.c b/server/red_worker.c
index 00efc05..6e5a238 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -866,8 +866,8 @@ typedef struct RedWorker {
CursorChannel *cursor_channel;
QXLInstance *qxl;
RedDispatcher *dispatcher;
- int id;
int channel;
+ int id;
int running;
uint32_t *pending;
int epoll;
@@ -10102,21 +10102,19 @@ static void surface_dirty_region_to_rects(RedSurface
*surface,
free(dirty_rects);
}
-static inline void handle_dev_update_async(RedWorker *worker)
+void handle_dev_update_async(void *opaque, void *payload)
{
- QXLRect qxl_rect;
+ RedWorker *worker = opaque;
+ RedWorkerMessageUpdateAsync *msg = payload;
SpiceRect rect;
- uint32_t surface_id;
- uint32_t clear_dirty_region;
QXLRect *qxl_dirty_rects;
uint32_t num_dirty_rects;
RedSurface *surface;
+ uint32_t surface_id = msg->surface_id;
+ QXLRect qxl_area = msg->qxl_area;
+ uint32_t clear_dirty_region = msg->clear_dirty_region;
- receive_data(worker->channel,&surface_id, sizeof(uint32_t));
- receive_data(worker->channel,&qxl_rect, sizeof(QXLRect));
- receive_data(worker->channel,&clear_dirty_region, sizeof(uint32_t));
-
- red_get_rect_ptr(&rect,&qxl_rect);
+ red_get_rect_ptr(&rect,&qxl_area);
flush_display_commands(worker);
ASSERT(worker->running);
@@ -10124,12 +10122,12 @@ static inline void handle_dev_update_async(RedWorker
*worker)
validate_surface(worker, surface_id);
red_update_area(worker,&rect, surface_id);
if (!worker->qxl->st->qif->update_area_complete) {
- return;
+ goto complete;
}
surface =&worker->surfaces[surface_id];
num_dirty_rects = pixman_region32_n_rects(&surface->draw_dirty_region);
if (num_dirty_rects == 0) {
- return;
+ goto complete;
}
qxl_dirty_rects = spice_new0(QXLRect, num_dirty_rects);
surface_dirty_region_to_rects(surface, qxl_dirty_rects, num_dirty_rects,
@@ -10137,26 +10135,25 @@ static inline void handle_dev_update_async(RedWorker
*worker)
worker->qxl->st->qif->update_area_complete(worker->qxl, surface_id,
qxl_dirty_rects, num_dirty_rects);
free(qxl_dirty_rects);
+
+complete:
+ red_dispatcher_async_complete(worker->dispatcher, msg->cmd);
You can register only one callback to all the async messages, and then
handle each one differently, but call red_dispatcher_async_complete for
all of them.
Thanks,
Yonit.
_______________________________________________
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel