Bug 225650

Summary: [WTF][GStreamer] Add RAII lockers for 3rd party locks
Product: WebKit Reporter: Alicia Boya García <aboya>
Component: Web Template FrameworkAssignee: Alicia Boya García <aboya>
Status: RESOLVED FIXED    
Severity: Normal CC: benjamin, bugs-noreply, calvaris, cdumez, cgarcia, cmarcelo, eric.carlson, ews-watchlist, glenn, gustavo, jer.noble, menard, philipj, pnormand, sergio, vjaquez, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch
none
Patch
none
Patch none

Description Alicia Boya García 2021-05-11 05:08:13 PDT
This patch introduces RAII locker classes that wrap GST_OBJECT_LOCK
and GST_PAD_STREAM_LOCK to match the style, safety and convenience of
locks from WTF.

This patch introduces no behavior changes.
Comment 1 Alicia Boya García 2021-05-11 05:15:31 PDT
Created attachment 428265 [details]
Patch
Comment 2 Xabier Rodríguez Calvar 2021-05-11 06:57:16 PDT
Comment on attachment 428265 [details]
Patch

Art.
Comment 3 Xabier Rodríguez Calvar 2021-05-11 07:10:27 PDT
Comment on attachment 428265 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=428265&action=review

> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:323
> +    explicit ExternalLocker(T* lockable) : m_lockable(lockable) { lock(); }

I wonder if we should ASSERT(lockable)...

> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:332
> +    T* lockable() { return m_lockable; }
> +
> +    explicit operator bool() const { return !!m_lockable; }

Why do you need these?

> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:387
> +inline GstObjectLocker holdGstObjectLock(void* gstObject) WARN_UNUSED_RETURN;
> +inline GstObjectLocker holdGstObjectLock(void* gstObject)
> +{
> +    return GstObjectLocker(gstObject);
> +}

Can't we collapse declaration and implementation?

Independently of asserting above, it could be interesting ASSERT(GST_IS_OBJECT(gstObject))

> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:393
> +inline GstPadStreamLocker holdGstPadStreamLock(GstPad*) WARN_UNUSED_RETURN;
> +inline GstPadStreamLocker holdGstPadStreamLock(GstPad* pad)
> +{
> +    return GstPadStreamLocker(pad);
> +}

Ditto.

Ditto.
Comment 4 Alicia Boya García 2021-05-11 16:30:10 PDT
Comment on attachment 428265 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=428265&action=review

>> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:323
>> +    explicit ExternalLocker(T* lockable) : m_lockable(lockable) { lock(); }
> 
> I wonder if we should ASSERT(lockable)...

We definitely can.

>> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:332
>> +    explicit operator bool() const { return !!m_lockable; }
> 
> Why do you need these?

It's here just for completeness to match WTF::Locker, even though we don't need all the fancy features at the moment (such as moving locks). This tells you if this locker still holds a lock: it doesn't if it has been moved.

>> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:387
>> +}
> 
> Can't we collapse declaration and implementation?
> 
> Independently of asserting above, it could be interesting ASSERT(GST_IS_OBJECT(gstObject))

We can't collapse declaration and implementation because WARN_UNUSED_RETURN can only be used in declarations, not in function definitions.
Comment 5 Xabier Rodríguez Calvar 2021-05-12 01:12:49 PDT
Comment on attachment 428265 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=428265&action=review

>>> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:332
>>> +    explicit operator bool() const { return !!m_lockable; }
>> 
>> Why do you need these?
> 
> It's here just for completeness to match WTF::Locker, even though we don't need all the fancy features at the moment (such as moving locks). This tells you if this locker still holds a lock: it doesn't if it has been moved.

You can keep them.

> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:384
> +// We can't pass macros as template parameters, so we need to wrap them in inline functions.
> +inline void gstObjectLock(void* object) { GST_OBJECT_LOCK(object); }
> +inline void gstObjectUnlock(void* object) { GST_OBJECT_UNLOCK(object); }
> +inline void gstPadStreamLock(GstPad* pad) { GST_PAD_STREAM_LOCK(pad); }
> +inline void gstPadStreamUnlock(GstPad* pad) { GST_PAD_STREAM_UNLOCK(pad); }
> +
> +using GstObjectLocker = ExternalLocker<void, gstObjectLock, gstObjectUnlock>;
> +using GstPadStreamLocker = ExternalLocker<GstPad, gstPadStreamLock, gstPadStreamUnlock>;
> +
> +inline GstObjectLocker holdGstObjectLock(void* gstObject) WARN_UNUSED_RETURN;
> +inline GstObjectLocker holdGstObjectLock(void* gstObject)

I would also be tempted of moving ExternalLocker to WTF and just keeping these functions here. WDYT? (It would need a new review, easy I hope) Besides, I think you can just use holdLock as a name and let function overload do its job. WDYT?
Comment 6 Alicia Boya García 2021-05-17 02:20:27 PDT
Created attachment 428817 [details]
Patch
Comment 7 Xabier Rodríguez Calvar 2021-05-24 03:55:55 PDT
Comment on attachment 428817 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=428817&action=review

> Source/WTF/wtf/Locker.h:188
> +    explicit ExternalLocker(T* lockable) : m_lockable(lockable) { lock(); }

You missed this ASSERT.

> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:331
> +    return GstObjectLocker(gstObject);

Ditto.

> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:337
> +    return GstPadStreamLocker(pad);

Ditto.
Comment 8 Chris Dumez 2021-05-24 06:59:33 PDT
Can you clarify the difference between this locker and the WTF::Locker we already have? As far as I know WTF supports all types of locks, not just WTF::Lock.
Comment 9 Chris Dumez 2021-05-24 07:06:16 PDT
(In reply to Chris Dumez from comment #8)
> Can you clarify the difference between this locker and the WTF::Locker we
> already have? As far as I know WTF supports all types of locks, not just
> WTF::Lock.

I see, you need custom lock()/unlock() functions.
Comment 10 Chris Dumez 2021-05-24 07:08:34 PDT
Comment on attachment 428817 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=428817&action=review

> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:329
> +inline GstObjectLocker holdGstObjectLock(void* gstObject)

What do those hold functions bring? Why not call the constructor directly at call sites like we now do for the regular Locker:
GstObjectLocker locker { object };
Comment 11 Alicia Boya García 2021-05-24 07:14:27 PDT
Comment on attachment 428817 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=428817&action=review

>> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:329
>> +inline GstObjectLocker holdGstObjectLock(void* gstObject)
> 
> What do those hold functions bring? Why not call the constructor directly at call sites like we now do for the regular Locker:
> GstObjectLocker locker { object };

They were there for consistency with holdLock(), which was used all across WebKit, until it stopped being used last Friday because the clang thread safety checker couldn't support it. https://bugs.webkit.org/show_bug.cgi?id=226119

Now I have to rework this patch a bit to adapt it to the new checker.
Comment 12 Chris Dumez 2021-05-24 07:28:15 PDT
(In reply to Alicia Boya García from comment #11)
> Comment on attachment 428817 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=428817&action=review
> 
> >> Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h:329
> >> +inline GstObjectLocker holdGstObjectLock(void* gstObject)
> > 
> > What do those hold functions bring? Why not call the constructor directly at call sites like we now do for the regular Locker:
> > GstObjectLocker locker { object };
> 
> They were there for consistency with holdLock(), which was used all across
> WebKit, until it stopped being used last Friday because the clang thread
> safety checker couldn't support it.
> https://bugs.webkit.org/show_bug.cgi?id=226119
> 
> Now I have to rework this patch a bit to adapt it to the new checker.

I don’t believe clang thread safety analysis will work with GstObject. However, I think it would still be nice to be as consistent as possible with the rest of WebKit. So I think the patch is fine as is but I would just remove the hold functions. I would also have moved the new ExternalLocker to its own header probably.
Comment 13 Xabier Rodríguez Calvar 2021-05-25 03:46:00 PDT
(In reply to Chris Dumez from comment #12)
> I don’t believe clang thread safety analysis will work with GstObject.
> However, I think it would still be nice to be as consistent as possible with
> the rest of WebKit. So I think the patch is fine as is but I would just
> remove the hold functions. I would also have moved the new ExternalLocker to
> its own header probably.

LGTM
Comment 14 Alicia Boya García 2021-06-08 09:36:51 PDT
Created attachment 430851 [details]
Patch
Comment 15 EWS 2021-06-09 03:58:45 PDT
Committed r278655 (238637@main): <https://commits.webkit.org/238637@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 430851 [details].
Comment 16 Radar WebKit Bug Importer 2021-06-09 03:59:16 PDT
<rdar://problem/79068061>
Comment 17 Alicia Boya García 2021-06-09 04:39:39 PDT
> I don’t believe clang thread safety analysis will work with GstObject.

You're right, as even though it would be possible to add lock/unlock annotations, all library GStreamer code would not contain any require_lock annotations.