9
9
10
10
namespace nbl ::video
11
11
{
12
+ class TimelineEventHandlerBase : core::Unmovable, core::Uncopyable
13
+ {
14
+ public:
15
+ struct PollResult
16
+ {
17
+ uint32_t eventsLeft = ~0u ;
18
+ bool bailed = false ;
19
+ };
20
+
21
+ // little utility
22
+ inline const ISemaphore* getSemaphore () const { return m_sema.get (); }
23
+
24
+ // todo: rename to default_wait_point ?
25
+ template <class Clock =std::chrono::steady_clock>
26
+ static inline Clock::time_point default_wait ()
27
+ {
28
+ return Clock::now ()+std::chrono::microseconds (50 );
29
+ }
30
+
31
+ protected:
32
+ TimelineEventHandlerBase (core::smart_refctd_ptr<const ISemaphore>&& sema) : m_sema(std::move(sema)) {}
33
+
34
+ core::smart_refctd_ptr<const ISemaphore> m_sema;
35
+ };
36
+
12
37
template <typename Functor>
13
38
class MultiTimelineEventHandlerST ;
14
39
15
40
// Could be made MT and relatively lockless, if only had a good lock-few circular buffer impl
16
41
// Not sure its worth the effort as anything using this will probably need to be lockful to be MT
17
42
template <typename Functor>
18
- class TimelineEventHandlerST final : core::Unmovable, core::Uncopyable
43
+ class TimelineEventHandlerST final : TimelineEventHandlerBase
19
44
{
20
45
public:
21
46
// Theoretically could make a factory function cause passing a null semaphore is invalid, but counting on users to be relatively intelligent.
22
47
inline TimelineEventHandlerST (core::smart_refctd_ptr<const ISemaphore>&& sema, const uint64_t initialCapacity=4095 /sizeof (FunctorValuePair)+1) :
23
- m_sema(std::move(sema)), m_greatestLatch(0 )
24
- {
25
- m_greatestSignal = m_sema->getCounterValue ();
26
- }
48
+ TimelineEventHandlerBase(std::move(sema)), m_greatestLatch(0 ), m_greatestSignal(m_sema->getCounterValue ()) {}
27
49
// If you don't want to deadlock here, look into the `abort*` family of methods
28
50
~TimelineEventHandlerST ()
29
51
{
30
52
while (wait (std::chrono::steady_clock::now ()+std::chrono::seconds (5 ))) {}
31
53
}
32
- // little utility
33
- inline const ISemaphore* getSemaphore () const {return m_sema.get ();}
34
54
35
55
inline uint32_t count () const {return m_cb.size ();}
36
56
@@ -44,23 +64,12 @@ class TimelineEventHandlerST final : core::Unmovable, core::Uncopyable
44
64
}
45
65
46
66
//
47
- struct PollResult
48
- {
49
- uint32_t eventsLeft = ~0u ;
50
- bool bailed = false ;
51
- };
52
67
template <typename ... Args>
53
68
inline PollResult poll (Args&&... args)
54
69
{
55
70
return poll_impl<true >(std::forward<Args>(args)...);
56
71
}
57
72
58
- template <class Clock =std::chrono::steady_clock>
59
- static inline Clock::time_point default_wait ()
60
- {
61
- return Clock::now ()+std::chrono::microseconds (50 );
62
- }
63
-
64
73
template <class Clock , class Duration =typename Clock::duration, typename ... Args>
65
74
inline uint32_t wait (const std::chrono::time_point<Clock,Duration>& timeout_time, Args&&... args)
66
75
{
@@ -160,7 +169,6 @@ class TimelineEventHandlerST final : core::Unmovable, core::Uncopyable
160
169
};
161
170
// could be a circular buffer but whatever for now
162
171
core::deque<FunctorValuePair> m_cb;
163
- core::smart_refctd_ptr<const ISemaphore> m_sema;
164
172
uint64_t m_greatestSignal;
165
173
uint64_t m_greatestLatch;
166
174
@@ -410,7 +418,7 @@ class MultiTimelineEventHandlerST final : core::Unmovable, core::Uncopyable
410
418
inline container_t ::iterator eraseTimeline (typename container_t ::iterator timeline)
411
419
{
412
420
// if not the last in scratch
413
- if (timeline->waitInfoIx <m_scratchWaitInfos.size ())
421
+ if (timeline->waitInfoIx + 1 <m_scratchWaitInfos.size ())
414
422
{
415
423
// swap the mapping with the end scratch element
416
424
const auto & lastScratch = m_scratchWaitInfos.back ();
0 commit comments