Upstream version 11.39.265.0
[platform/framework/web/crosswalk.git] / src / ozone / wayland / display_poll_thread.cc
1 // Copyright 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ozone/wayland/display_poll_thread.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <poll.h>
10 #include <sys/socket.h>
11 #include <sys/types.h>
12 #include <wayland-client.h>
13
14 #include "base/bind.h"
15 #include "ozone/wayland/display.h"
16
17 namespace ozonewayland {
18 const int MAX_EVENTS = 16;
19
20 WaylandDisplayPollThread::WaylandDisplayPollThread(wl_display* display)
21     : base::Thread("WaylandDisplayPollThread"),
22       display_(display),
23       polling_(true, false),
24       stop_polling_(true, false) {
25   DCHECK(display_);
26 }
27
28 WaylandDisplayPollThread::~WaylandDisplayPollThread() {
29   StopProcessingEvents();
30 }
31
32 void WaylandDisplayPollThread::StartProcessingEvents() {
33   DCHECK(!polling_.IsSignaled());
34   base::Thread::Options options;
35   options.message_loop_type = base::MessageLoop::TYPE_IO;
36   StartWithOptions(options);
37   SetPriority(base::kThreadPriority_Background);
38   message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
39       &WaylandDisplayPollThread::DisplayRun, this));
40 }
41
42 void WaylandDisplayPollThread::StopProcessingEvents() {
43   if (polling_.IsSignaled())
44     stop_polling_.Signal();
45
46   Stop();
47 }
48
49 void WaylandDisplayPollThread::CleanUp() {
50   SetThreadWasQuitProperly(true);
51 }
52
53 void  WaylandDisplayPollThread::DisplayRun(WaylandDisplayPollThread* data) {
54   struct pollfd ep;
55   int i, ret, count = 0;
56   uint32_t event = 0;
57   unsigned display_fd = wl_display_get_fd(data->display_);
58   ep.fd = display_fd;
59   ep.events = POLLIN | POLLERR | POLLHUP;
60
61   // Set the signal state. This is used to query from other threads (i.e.
62   // StopProcessingEvents on Main thread), if this thread is still polling.
63   data->polling_.Signal();
64
65   // Adopted from:
66   // http://cgit.freedesktop.org/wayland/weston/tree/clients/window.c#n5531.
67   while (1) {
68     wl_display_dispatch_pending(data->display_);
69     ret = wl_display_flush(data->display_);
70     if (ret < 0 && errno != EAGAIN) {
71       break;
72     }
73     // StopProcessingEvents has been called or we have been asked to stop
74     // polling. Break from the loop.
75     if (data->stop_polling_.IsSignaled())
76       break;
77
78     count = poll(&ep, 1, -1);
79     // Break if epoll wait returned value less than 0 and we aren't interrupted
80     // by a signal.
81     if (count < 0 && errno != EINTR) {
82       LOG(ERROR) << "poll returned an error." << errno;
83       break;
84     }
85
86     if (count == 1) {
87       event = ep.revents;
88       // We can have cases where POLLIN and POLLHUP are both set for
89       // example. Don't break if both flags are set.
90       if ((event & POLLERR || event & POLLHUP) &&
91              !(event & POLLIN)) {
92         break;
93       }
94
95       if (event & POLLIN) {
96         ret = wl_display_dispatch(data->display_);
97         if (ret == -1) {
98           LOG(ERROR) << "wl_display_dispatch failed with an error." << errno;
99           break;
100         }
101       }
102     }
103   }
104
105   data->polling_.Reset();
106   data->stop_polling_.Reset();
107 }
108
109 }  // namespace ozonewayland