Merge pull request #26308 from jjd-uk/estuary_playerprocess
[xbmc.git] / xbmc / threads / Event.cpp
blob9ec7f3f1c0ae21373be58e1361c6994f1c3eb35e
1 /*
2 * Copyright (c) 2002 Frodo
3 * Portions Copyright (c) by the authors of ffmpeg and xvid
4 * Copyright (C) 2002-2018 Team Kodi
5 * This file is part of Kodi - https://kodi.tv
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 * See LICENSES/README.md for more information.
9 */
11 #include "Event.h"
13 #include <algorithm>
14 #include <limits>
15 #include <memory>
16 #include <mutex>
18 using namespace std::chrono_literals;
20 void CEvent::addGroup(XbmcThreads::CEventGroup* group)
22 std::unique_lock<CCriticalSection> lock(groupListMutex);
23 if (!groups)
24 groups = std::make_unique<std::vector<XbmcThreads::CEventGroup*>>();
26 groups->push_back(group);
29 void CEvent::removeGroup(XbmcThreads::CEventGroup* group)
31 std::unique_lock<CCriticalSection> lock(groupListMutex);
32 if (groups)
34 groups->erase(std::remove(groups->begin(), groups->end(), group), groups->end());
35 if (groups->empty())
37 groups.reset();
42 // locking is ALWAYS done in this order:
43 // CEvent::groupListMutex -> CEventGroup::mutex -> CEvent::mutex
44 void CEvent::Set()
46 // Originally I had this without locking. Thanks to FernetMenta who
47 // pointed out that this creates a race condition between setting
48 // checking the signal and calling wait() on the Wait call in the
49 // CEvent class. This now perfectly matches the boost example here:
50 // http://www.boost.org/doc/libs/1_41_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref
52 std::unique_lock<CCriticalSection> slock(mutex);
53 signaled = true;
56 actualCv.notifyAll();
58 std::unique_lock<CCriticalSection> l(groupListMutex);
59 if (groups)
61 for (auto* group : *groups)
62 group->Set(this);
66 namespace XbmcThreads
68 /**
69 * This will block until any one of the CEvents in the group are
70 * signaled at which point a pointer to that CEvents will be
71 * returned.
73 CEvent* CEventGroup::wait()
75 return wait(std::chrono::milliseconds::max());
78 CEventGroup::CEventGroup(std::initializer_list<CEvent*> eventsList)
79 : events{eventsList}
81 // we preping for a wait, so we need to set the group value on
82 // all of the CEvents.
83 for (auto* event : events)
85 event->addGroup(this);
89 CEventGroup::~CEventGroup()
91 for (auto* event : events)
93 event->removeGroup(this);