Skip to content

Commit 2e5e679

Browse files
committed
Revert "Use CEF multi-threaded handler and use C++11"
This reverts commit 5e9ad21. Multi-threaded mode isn't supported on OSX according to this CEF post: https://bitbucket.org/chromiumembedded/cef/issues/745/multi_threaded_message_loop-yes-on-mac-os A different fix will be made for the startup hang issue.
1 parent 5e9ad21 commit 2e5e679

File tree

2 files changed

+131
-97
lines changed

2 files changed

+131
-97
lines changed

obs-browser/browser-manager-base.cpp

Lines changed: 117 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#include "browser-render-handler.hpp"
1010
#include "browser-load-handler.hpp"
1111
#include "browser-obs-bridge-base.hpp"
12-
#include <chrono>
13-
#include <thread>
1412

1513
BrowserManager::BrowserManager()
1614
: pimpl(new BrowserManager::Impl())
@@ -106,31 +104,25 @@ void BrowserManager::DispatchJSEvent(const char *eventName, const char *jsonStri
106104
pimpl->DispatchJSEvent(eventName, jsonString);
107105
}
108106

109-
std::string getBootstrap()
107+
BrowserManager::Impl::Impl()
110108
{
111-
std::string modulePath(BrowserManager::Instance()->GetModulePath());
112-
std::string parentPath(modulePath.substr(0,
113-
modulePath.find_last_of('/') + 1));
114-
#ifdef _WIN32
115-
return parentPath + "/cef-bootstrap.exe";
116-
#else
117-
return parentPath + "/cef-bootstrap";
118-
#endif
109+
os_event_init(&dispatchEvent, OS_EVENT_TYPE_AUTO);
110+
pthread_mutex_init(&dispatchLock, nullptr);
119111
}
120112

121-
//////////////////////////////////////////////////////////////////////////
122-
// BrowserManager::Impl
123-
BrowserManager::Impl::Impl() {}
124-
125-
BrowserManager::Impl::~Impl() {}
113+
BrowserManager::Impl::~Impl()
114+
{
115+
os_event_destroy(dispatchEvent);
116+
pthread_mutex_destroy(&dispatchLock);
117+
}
126118

127119
int BrowserManager::Impl::CreateBrowser(
128120
const BrowserSettings &browserSettings,
129121
const std::shared_ptr<BrowserListener> &browserListener)
130122
{
131123
int browserIdentifier = 0;
132-
std::mutex createMutex;
133-
std::condition_variable createEvent;
124+
os_event_t *createdEvent;
125+
os_event_init(&createdEvent, OS_EVENT_TYPE_AUTO);
134126

135127
BrowserOBSBridge *browserOBSBridge = new BrowserOBSBridgeBase();
136128

@@ -165,11 +157,11 @@ int BrowserManager::Impl::CreateBrowser(
165157
browserIdentifier = browser->GetIdentifier();
166158
browserMap[browserIdentifier] = browser;
167159
}
168-
createEvent.notify_all();
160+
os_event_signal(createdEvent);
169161
}));
170162

171-
std::unique_lock<std::mutex> createLock(createMutex);
172-
createEvent.wait(createLock);
163+
os_event_wait(createdEvent);
164+
os_event_destroy(createdEvent);
173165
return browserIdentifier;
174166
}
175167

@@ -178,14 +170,15 @@ BrowserManager::Impl::DestroyBrowser(int browserIdentifier)
178170
{
179171
if (browserMap.count(browserIdentifier) > 0) {
180172
CefRefPtr<CefBrowser> browser = browserMap[browserIdentifier];
181-
std::mutex closeMutex;
182-
std::condition_variable closeEvent;
183-
CefPostTask(TID_UI, BrowserTask::newTask([&, browser]
173+
os_event_t *closeEvent;
174+
os_event_init(&closeEvent, OS_EVENT_TYPE_AUTO);
175+
CefPostTask(TID_UI, BrowserTask::newTask([&, browser]
184176
{
185177
browser->GetHost()->CloseBrowser(true);
186-
closeEvent.notify_all();
178+
os_event_signal(closeEvent);
187179
}));
188-
closeEvent.wait(std::unique_lock<std::mutex>(closeMutex));
180+
os_event_wait(closeEvent);
181+
os_event_destroy(closeEvent);
189182
browserMap.erase(browserIdentifier);
190183
}
191184
}
@@ -205,13 +198,14 @@ void BrowserManager::Impl::ExecuteOnBrowser(int browserIdentifier,
205198
f(browser);
206199
}));
207200
} else {
208-
std::mutex finishedMutex;
209-
std::condition_variable finishedEvent;
201+
os_event_t *finishedEvent;
202+
os_event_init(&finishedEvent, OS_EVENT_TYPE_AUTO);
210203
CefPostTask(TID_UI, BrowserTask::newTask([&] {
211204
f(browser);
212-
finishedEvent.notify_all();
205+
os_event_signal(finishedEvent);
213206
}));
214-
finishedEvent.wait(std::unique_lock<std::mutex>(finishedMutex));
207+
os_event_wait(finishedEvent);
208+
os_event_destroy(finishedEvent);
215209
}
216210
}
217211
}
@@ -227,13 +221,14 @@ void BrowserManager::Impl::ExecuteOnAllBrowsers(
227221
f(browser);
228222
}));
229223
} else {
230-
std::mutex finishedMutex;
231-
std::condition_variable finishedEvent;
224+
os_event_t *finishedEvent;
225+
os_event_init(&finishedEvent, OS_EVENT_TYPE_AUTO);
232226
CefPostTask(TID_UI, BrowserTask::newTask([&] {
233227
f(browser);
234-
finishedEvent.notify_all();
228+
os_event_signal(finishedEvent);
235229
}));
236-
finishedEvent.wait(std::unique_lock<std::mutex>(finishedMutex));
230+
os_event_wait(finishedEvent);
231+
os_event_destroy(finishedEvent);
237232
}
238233
}
239234
}
@@ -368,69 +363,112 @@ void BrowserManager::Impl::DispatchJSEvent(const char *eventName, const char *js
368363
});
369364
}
370365

371-
void BrowserManager::Impl::Startup()
366+
void
367+
BrowserManager::Impl::Startup()
372368
{
373-
// Initialize CEF
374-
CefMainArgs mainArgs;
375-
CefSettings settings;
376-
settings.log_severity = LOGSEVERITY_VERBOSE;
377-
settings.windowless_rendering_enabled = true;
378-
settings.no_sandbox = false;
379-
settings.multi_threaded_message_loop = true;
380-
CefString(&settings.cache_path).FromASCII(obs_module_config_path(""));
381-
CefString(&settings.browser_subprocess_path) = getBootstrap();
382-
CefRefPtr<BrowserApp> app(new BrowserApp());
383-
CefExecuteProcess(mainArgs, app, nullptr);
384-
CefInitialize(mainArgs, settings, app, nullptr);
385-
CefRegisterSchemeHandlerFactory("http", "absolute", new BrowserSchemeHandlerFactory());
386-
387-
// Initialize event queue.
388-
{
389-
std::lock_guard<std::mutex> lock(events.mutex);
390-
events.bQuit = false;
391-
events.thread = std::thread(QueueThreadMain, this);
369+
pthread_mutex_lock(&dispatchLock);
370+
int ret = pthread_create(&managerThread, nullptr,
371+
browserManagerEntry, this);
372+
373+
if (ret != 0) {
374+
blog(LOG_ERROR,
375+
"BrowserManager: failed to create browser "
376+
"manager thread.");
377+
threadAlive = false;
392378
}
393-
394-
379+
else {
380+
threadAlive = true;
381+
}
382+
pthread_mutex_unlock(&dispatchLock);
383+
395384
return;
396385
}
397386

398-
void BrowserManager::Impl::Shutdown()
387+
void BrowserManager::Impl::Shutdown()
399388
{
400-
// Quit Event Thread
401-
events.bQuit = true;
402-
events.condvar.notify_all();
403-
events.thread.join();
389+
os_event_t *shutdown_event;
390+
os_event_init(&shutdown_event, OS_EVENT_TYPE_AUTO);
391+
392+
// post the task
393+
CefPostTask(TID_UI, BrowserTask::newTask([] {
394+
CefQuitMessageLoop();
395+
}));
404396

405-
// Shut down CEF
406-
CefShutdown();
397+
// this event will then get processed and shut down the dispatcher loop
398+
PushEvent([this, shutdown_event] {
399+
threadAlive = false;
400+
os_event_signal(shutdown_event);
401+
});
402+
403+
os_event_wait(shutdown_event);
404+
os_event_destroy(shutdown_event);
407405
return;
408406
}
409407

410-
void BrowserManager::Impl::PushEvent(std::function<void()> event)
408+
void *BrowserManager::Impl::browserManagerEntry(void* threadArgument)
411409
{
412-
std::lock_guard<std::mutex> lock(events.mutex);
413-
events.queue.push(event);
414-
events.condvar.notify_one();
410+
BrowserManager::Impl *browserManager =
411+
static_cast<BrowserManager::Impl *>(threadArgument);
412+
browserManager->BrowserManagerEntry();
413+
return nullptr;
415414
}
416415

417-
void BrowserManager::Impl::QueueThreadMain(void* data)
416+
void BrowserManager::Impl::PushEvent(std::function<void()> event)
418417
{
419-
auto obj = static_cast<BrowserManager::Impl*>(data);
420-
obj->QueueThreadLocalMain();
418+
pthread_mutex_lock(&dispatchLock);
419+
queue.push_back(event);
420+
pthread_mutex_unlock(&dispatchLock);
421+
os_event_signal(dispatchEvent);
421422
}
422423

423-
void BrowserManager::Impl::QueueThreadLocalMain()
424+
std::string getBootstrap()
424425
{
425-
std::unique_lock<std::mutex> ulock(events.mutex);
426-
do {
427-
events.condvar.wait(ulock);
428-
while (events.queue.size() > 0) {
429-
auto v = events.queue.front();
430-
v();
431-
events.queue.pop();
426+
std::string modulePath(BrowserManager::Instance()->GetModulePath());
427+
std::string parentPath(modulePath.substr(0,
428+
modulePath.find_last_of('/') + 1));
429+
#ifdef _WIN32
430+
return parentPath + "/cef-bootstrap.exe";
431+
#else
432+
return parentPath + "/cef-bootstrap";
433+
#endif
434+
}
435+
436+
void BrowserManager::Impl::BrowserManagerEntry()
437+
{
438+
std::string bootstrapPath = getBootstrap();
439+
bool thread_exit = false;
440+
PushEvent([] {
441+
CefMainArgs mainArgs;
442+
CefSettings settings;
443+
settings.log_severity = LOGSEVERITY_VERBOSE;
444+
settings.windowless_rendering_enabled = true;
445+
settings.no_sandbox = true;
446+
CefString(&settings.cache_path).FromASCII(obs_module_config_path(""));
447+
CefString(&settings.browser_subprocess_path) = getBootstrap();
448+
CefRefPtr<BrowserApp> app(new BrowserApp());
449+
CefExecuteProcess(mainArgs, app, nullptr);
450+
CefInitialize(mainArgs, settings, app, nullptr);
451+
CefRegisterSchemeHandlerFactory("http", "absolute", new BrowserSchemeHandlerFactory());
452+
CefRunMessageLoop();
453+
CefShutdown();
454+
});
455+
456+
while (true) {
457+
458+
if (os_event_timedwait(dispatchEvent, 10) != ETIMEDOUT) {
459+
pthread_mutex_lock(&dispatchLock);
460+
while (!queue.empty()) {
461+
auto event = queue[0];
462+
event();
463+
queue.erase(queue.begin());
464+
}
465+
thread_exit = !threadAlive;
466+
pthread_mutex_unlock(&dispatchLock);
467+
if (thread_exit) {
468+
return;
469+
}
432470
}
433-
} while (events.bQuit == false);
471+
}
434472
}
435473

436474
static BrowserManager *instance;

obs-browser/browser-manager-base.hpp

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99
#include <functional>
1010
#include <util/threading.h>
1111

12-
#include <thread>
13-
#include <mutex>
14-
#include <condition_variable>
15-
#include <queue>
16-
1712
#include "browser-manager.hpp"
1813

1914
class BrowserManager::Impl
@@ -23,6 +18,14 @@ class BrowserManager::Impl
2318
Impl();
2419
~Impl();
2520

21+
private:
22+
23+
static void *browserManagerEntry(void* threadArguments);
24+
void BrowserManagerEntry();
25+
26+
27+
public:
28+
2629
void Startup();
2730
void Shutdown();
2831

@@ -68,19 +71,12 @@ class BrowserManager::Impl
6871
bool async = false);
6972

7073
private:
74+
bool threadAlive;
75+
os_event_t *dispatchEvent;
76+
pthread_t managerThread;
77+
pthread_mutex_t dispatchLock;
78+
7179
std::map<int, std::shared_ptr<BrowserListener>> listenerMap;
7280
std::map<int, CefRefPtr<CefBrowser> > browserMap;
73-
74-
// Holds Queue related Information
75-
struct {
76-
std::thread thread;
77-
std::mutex mutex;
78-
std::condition_variable condvar;
79-
std::queue<std::function<void()>> queue;
80-
81-
bool bQuit = false;
82-
} events;
83-
static void QueueThreadMain(void*);
84-
void QueueThreadLocalMain();
85-
81+
std::vector<std::function<void()>> queue;
8682
};

0 commit comments

Comments
 (0)