Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

threads: add new mp_thread abstraction #12709

Merged
merged 10 commits into from
Nov 5, 2023
Merged

Conversation

kasper93
Copy link
Contributor

To resolve issue with hijacking pthread headers/symbols and overall simplify the thread API and win32 implementation in particular. No more hacks, no more internal state, no more strange time conversions.

@github-actions
Copy link

github-actions bot commented Oct 22, 2023

Download the artifacts for this pull request:

Windows

@kasper93 kasper93 force-pushed the threads branch 3 times, most recently from c2bbfa6 to 425b4c0 Compare October 22, 2023 05:53
@sfan5
Copy link
Member

sfan5 commented Oct 22, 2023

I wanted to mention it before you started your work but: is it worth it when we could just switch to pl_thread in the future?

@kasper93
Copy link
Contributor Author

kasper93 commented Oct 22, 2023

I wanted to mention it before you started your work but: is it worth it when we could just switch to pl_thread in the future?

I was thinking about it. This would be very good idea, and I initially wanted to do that. Problem is the pl_thread is internal utility header of libplacebo. (also is less capable, than mp_thread currently, but can be extended) Unless it is exported in public API, we cannot feasibly use it. And I don't see why would libplacebo export this in API. In general this is quit lightweight wrapper tailored for our needs.

@Dudemanguy Dudemanguy mentioned this pull request Oct 22, 2023
@kasper93 kasper93 force-pushed the threads branch 4 times, most recently from cd7ca89 to e79eb35 Compare October 28, 2023 19:40
@kasper93
Copy link
Contributor Author

Rebase only, no additional changes.

@kasper93 kasper93 force-pushed the threads branch 3 times, most recently from 9871082 to 24ad34c Compare October 28, 2023 19:54
because its sole purpose is to interrupt a thread waiting via pthread_cond_wait()
are not variables that signal a condition. mp_cond does not have any
state per-se. Maybe mp_cond would better be named mp_interrupt,
because its sole purpose is to interrupt a thread waiting via mp_cond_wait()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have our own interface, we aren't bound to copy pthread's naming. So this "maybe" can be turned into reality.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not an interrupt. It is a way to signal that a new condition exists and that threads waiting for that condition can continue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frankly speaking I have not read this tech-overview.txt. mp_thread is a thin pthread wrapper, which with all intention and purpose should work in similar way. Obviously it is limited to a subset of pthread and with higher level abstraction, like offloading the clock conversion from the caller.

I can take a look into updating this docs, but I was surprised in the first place that we have something like that in mpv, it is not really related specifically to mpv and mostly standard threading stuff that we are no place to explain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have our own interface, we aren't bound to copy pthread's naming. So this "maybe" can be turned into reality.

I frankly don't agree with this mp_interrupt commentary. Also cond or conditional variable naming is standardized, not only by pthread, but anything else really. Including C++ std::condition_variable and so on. This make easier to understand what mp_cond represents. And it definitely is NOT interrupt.

@@ -555,13 +555,13 @@ Condition variables
-------------------

They're used whenever a thread needs to wait for something, without nonsense
like sleep calls or busy waiting. mpv uses the standard pthread API for this.
like sleep calls or busy waiting. mpv uses the mp_thread API for this.
There's a lot of literature on it. Read it.
Copy link
Contributor

@N-R-K N-R-K Nov 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isn't lots of literature on mp_thread API :)

Which brings up another point, we probably need some documentation on this new interface, i.e what type of guarantees it makes and doesn't make etc. We can go two routes:

  1. Start fresh. Make the absolute minimum amount of guarantees that mpv code expects/needs and cut the churn.
  2. Make it "based on pthreads" and document deviations.

The latter is probably easier to start off with, but pthreads have lots of subtle details that can be easy to overlook and/or get wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it is more or less pthreads document it based on that.
After this extra layer is here just because windows is missing it and somewhat difficult to implement in a good way directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latter is probably easier to start off with, but pthreads have lots of subtle details that can be easy to overlook and/or get wrong.

The functionality that mpv uses is pretty basic, we just have mutex/condvar and thread, that's all.

After this extra layer is here just because windows is missing it and somewhat difficult to implement in a good way directly.

@DanOscarsson: Sorry, I don't understand what you mean. You mean that this extra layer is here only for windows, because it is hard to implement otherwise or you mean the new interface is hard to implement on windows directly. Both old and new version was implemented for win32.

And no, this is not a wrapper for Windows. The main point is to abstract implementation details of pthread and clock used. Use mp_time as an internal clock and convert only when needed. Of course there are some adjustment to make Windows wrapper lightweight without the need of tracking thread pids. The main difference that with pthread you can get current thread handle, but not pid and on Windows is the other way around, you can get current thread pid and not handle.

Copy link
Contributor Author

@kasper93 kasper93 Nov 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isn't lots of literature on mp_thread API :)

Updated this line. I've also skimmed through the rest of the threading overview and it flows nicely. Our API is basic ans uses pretty standard primitives and nor the API, nor the users of it cares about small intricacies. I still don't feel like mpv's technical overview is the place to teach threading and in the same time while we define custom mp_thread now, all primitives of it are pretty standardized and knowledge transferable. I don't think we have to do full description of it and developers would be better of it they learn pthreads or std::thread or even win32 threads first... and then usage of this mp_thread is quite standard.

Copy link
Member

@Dudemanguy Dudemanguy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like not hijacking global symbols so overall pretty good. Just minor things. I also noticed that a few of the <pthread.h> removals were in some commits after the use new mp_thread abstraction, so maybe some of the comments I initially made were taken care of later. I would be nicer if all of those were in the use new mp_thread abstraction commit though.

osdep/threads-posix.h Outdated Show resolved Hide resolved
audio/out/ao_pulse.c Show resolved Hide resolved
demux/demux_lavf.c Show resolved Hide resolved
player/command.c Show resolved Hide resolved
video/vaapi.h Show resolved Hide resolved
osdep/threads-posix.h Outdated Show resolved Hide resolved
@Dudemanguy
Copy link
Member

Also this would unbreak windows 7 support right? At least in terms of removing the GetSystemTimePreciseAsFileTime call.

@kasper93
Copy link
Contributor Author

kasper93 commented Nov 4, 2023

I like not hijacking global symbols so overall pretty good. Just minor things. I also noticed that a few of the <pthread.h> removals were in some commits after the use new mp_thread abstraction, so maybe some of the comments I initially made were taken care of later. I would be nicer if all of those were in the use new mp_thread abstraction commit though.

Not possible. On use new mp_thread abstraction the old win32 pthread wrapper still works. And for it to make work our pthread.h has to be included before any other pthread thread. So we have to keep (or in few places even add) phread.h include the fix the compilation. After mp_thread: add win32 implementation the stray phread.h includes are removed, because at this point we can do that. This is the all mess with hijacking pthread.h ...

Also this would unbreak windows 7 support right? At least in terms of removing the GetSystemTimePreciseAsFileTime call.

Yes, probably.

@Dudemanguy
Copy link
Member

And for it to make work our pthread.h has to be included before any other pthread thread. So we have to keep (or in few places even add) phread.h include the fix the compilation.

Ah I see. Yeah, the old way it worked always bothered me too.

osdep/threads.h Outdated Show resolved Hide resolved
osdep/threads.h Outdated Show resolved Hide resolved
@kasper93 kasper93 force-pushed the threads branch 2 times, most recently from b3ed00c to bba3e99 Compare November 4, 2023 18:44
Copy link
Member

@Dudemanguy Dudemanguy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kasper93
Copy link
Contributor Author

kasper93 commented Nov 4, 2023

Removed one unused header from test/timer.c, no other changes.

@Dudemanguy
Copy link
Member

@kasper93: Ping. Looks like the sub thing I just merged caused a merged conflict.

This will allow to avoid hacky pthreads symbols/header override.

Inspired by pl_thread from libplacebo.
This change essentially removes mp_thread_self() and instead add
mp_thread_id to track threads and have ability to query current thread
id during runtime.

This will be useful for upcoming win32 implementation, where accessing
thread handle is different than on pthreads. Greatly reduces complexity.
Otherweis locked map of tid <-> handle is required which is completely
unnecessary for all mpv use-cases.

Note that this is the mp_thread_id, not to confuse with system tid. For
example on threads-posix implementation it is simply pthread_t.
And remove redundant define while at it.
@kasper93
Copy link
Contributor Author

kasper93 commented Nov 5, 2023

rebased

@Dudemanguy Dudemanguy merged commit 076be24 into mpv-player:master Nov 5, 2023
14 checks passed
@kasper93 kasper93 deleted the threads branch November 5, 2023 17:39
audio/out/ao_audiotrack.c Show resolved Hide resolved
input/ipc-win.c Show resolved Hide resolved
osdep/threads-win32.h Show resolved Hide resolved
osdep/threads-win32.h Show resolved Hide resolved
#define pthread_mutex_trylock(...) \
mp_ptwrap_mutex_trylock(__FILE__, __LINE__, __VA_ARGS__)
#define mp_mutex_init_type(mutex, mtype) \
assert(!mp_mutex_init_type_internal(mutex, mtype))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

threads-win32.h already defines this, mistake?

also if this is never supposed to fail why not drop the _internal split and make the return value void?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is fixed. It was quite a big mess up ;p a718677

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so is mp_mutex_init_type supposed to return void?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants