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
1513BrowserManager::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
127119int 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
436474static BrowserManager *instance;
0 commit comments