Project
Loading...
Searching...
No Matches
GPUDisplayGUIWrapper.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
16#include "GPUDisplayGUI.h"
18
19#include <QApplication>
20
21#include <atomic>
22#include <condition_variable>
23#include <mutex>
24#include <stdexcept>
25#include <thread>
26
27using namespace o2::gpu;
28
29namespace o2::gpu::internal
30{
32 int argc = 1;
33 char appName[64] = "GPU CA Standalone Event Display GUI";
34 char* argv[2] = {appName, nullptr}; // Must outlive the QApplication
35 std::unique_ptr<QApplication> app;
36 std::unique_ptr<GPUDisplayGUI> gui; // Protected by mutex
37 std::thread thread;
38 std::mutex mutex;
39 std::condition_variable signal;
40 bool start = false, terminate = false; // Protected by mutex
41 std::atomic<bool> started = false; // Written under mutex
42};
43} // namespace o2::gpu::internal
44
45namespace
46{
47std::atomic<bool> instanceExists = false; // Qt supports only one QApplication
48} // namespace
49
51{
52 if (instanceExists.exchange(true)) {
53 throw std::runtime_error("Must not start QApplication twice");
54 }
55 mO = std::make_unique<internal::GPUDisplayGUIWrapperObjects>();
56 mO->thread = std::thread(&GPUDisplayGUIWrapper::guiThread, this);
57}
58
60{
61 stop();
62 {
63 std::lock_guard lock(mO->mutex);
64 mO->terminate = true;
65 }
66 mO->signal.notify_all();
67 mO->thread.join();
68 instanceExists = false;
69}
70
71void GPUDisplayGUIWrapper::guiThread()
72{
73 mO->app = std::make_unique<QApplication>(mO->argc, mO->argv);
74 std::unique_lock lock(mO->mutex);
75 while (true) {
76 mO->signal.wait(lock, [this] { return mO->start || mO->terminate; });
77 if (mO->terminate) {
78 break;
79 }
80 mO->start = false;
81 mO->gui = std::make_unique<GPUDisplayGUI>(mChannel);
82 mO->gui->show();
83 mO->started = true;
84 mO->signal.notify_all();
85 lock.unlock();
86 mO->app->exec(); // Returns when the GUI window is closed, by the user or by stop()
87 lock.lock();
88 mO->gui.reset();
89 mO->started = false;
90 mO->signal.notify_all();
91 }
92 lock.unlock();
93 mO->app.reset();
94}
95
97{
98 std::unique_lock lock(mO->mutex);
99 if (!mO->started) {
100 mO->start = true;
101 mO->signal.notify_all();
102 mO->signal.wait(lock, [this] { return mO->started.load(); });
103 }
104 return 0;
105}
106
108{
109 {
110 std::lock_guard lock(mChannel.mutex);
111 mChannel.stop = true;
112 }
113 mChannel.stateUpdated.notify_all(); // Wake up the GUI if it waits for a reply
114 std::unique_lock lock(mO->mutex);
115 mO->signal.wait(lock, [this] { return !mO->started; });
116 return 0;
117}
118
120{
121 std::lock_guard lock(mO->mutex);
122 if (mO->started) {
123 QMetaObject::invokeMethod(mO->gui.get(), &GPUDisplayGUI::bringToFront, Qt::QueuedConnection); // Widgets must only be accessed from the GUI thread
124 }
125 return 0;
126}
127
129{
130 return mO->started;
131}
GPUDisplayGUIWrapper(GPUDisplayGUIChannel &channel)
GLuint start
Definition glcorearb.h:469
std::condition_variable stateUpdated