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

Export getThreadId from GHC.Conc.Sync #117

Closed
bgamari opened this issue Jan 17, 2023 · 34 comments
Closed

Export getThreadId from GHC.Conc.Sync #117

bgamari opened this issue Jan 17, 2023 · 34 comments
Labels
approved Approved by CLC vote base-4.19 Implemented in base-4.19 (GHC 9.8)

Comments

@bgamari
Copy link

bgamari commented Jan 17, 2023

Currently GHC.Conc.Sync.ThreadId is nearly entirely opaque, supporting only Eq, Ord, and Show. Such a restrictive interface is quite limiting and precludes the user providing instances like Hashable without relying on GHC's internals (e.g. see https://hackage-search.serokell.io/?q=rts_getThreadId). Moreover, this is quite silly as GHC already associates a unique integer identifier with each thread.

I propose exporting the following from GHC.Conc.Sync:

fromThreadId :: ThreadId -> Word64

This will expose the thread identifier to the user.

See also: GHC #22700

@nomeata
Copy link

nomeata commented Jan 17, 2023

Is that a good name? I was assuming a function of that name to have type IO ThreadId maybe.

threasIdToInt maybe, as ugly as that is?

@treeowl
Copy link

treeowl commented Jan 17, 2023

I agree with @nomeata .

@bgamari
Copy link
Author

bgamari commented Jan 17, 2023

Sure, I have no strong opinion about the name. I have updated the proposal with this suggestion.

@arybczak
Copy link

The function should have a type ThreadId -> Int64, because rts_getThreadId returns a CULLong.

Also, for the risk of unnecessary bikeshedding, I had to import this in one in one of my projects and used the name weakThreadId because it kinda is - it's a unique thread identifier, but holding onto it (unlike holding onto ThreadId# itself) won't prevent the thread from getting garbage collected if appropriate.

@chessai
Copy link
Member

chessai commented Jan 18, 2023

The function should have a type ThreadId -> Int64, because rts_getThreadId returns a CULLong.

Shouldn't that be Word64 then?

@phadej
Copy link

phadej commented Jan 18, 2023

Yes. Which makes foreign import rts_getThreadId use the wrong type. It should use Word64 as the types defined are

typedef StgWord64 StgThreadID;
StgThreadID rts_getThreadId                  (StgPtr tso);

So it seems that all code on Hackage importing rts_getThreadId including base is using a wrong type. It's accidental that CULLong is Word64 on all platforms GHC supports :)

@Bodigrim
Copy link
Collaborator

See also: GHC #22700

@bgamari this is a wrong ticket, I think.

@bgamari
Copy link
Author

bgamari commented Jan 19, 2023

The function should have a type ThreadId -> Int64, because rts_getThreadId returns a CULLong.

Yes, a good point. I will update the proposal.

@bgamari this is a wrong ticket, I think.

Fixed.

@bgamari
Copy link
Author

bgamari commented Jan 19, 2023

On @phadej's request, I have further updated the proposal such that threadIdToInt returns a Word64, reflecting the fact that the RTS's internal representation is unsigned.

However, this now introduces the awkward fact that threadIdToInt doesn't return an Int. I suppose we can explain this away by claiming that "Int" is in fact short for "Integer" and doesn't refer to the Int type. However, it does seem a bit odd. Other names that come to mind include:

  • getThreadNumber
  • threadIdToWord
  • getThreadIdentifier
  • threadId
  • threadIdId

@arybczak
Copy link

arybczak commented Jan 27, 2023

To be fair, all of these are a bit confusing. It's somewhat unfortunate since at this point you already have the ThreadId that supposedly represents the identifier of a thread. Maybe rtsThreadId (or rtsThreadIdentifier)? Then the name at least points to the origin of the number.

@mpickering
Copy link

Please can we have a resolution on this @haskell/core-language-committee ?

@Bodigrim
Copy link
Collaborator

@mpickering #117 (comment) looks to me like an invitation for discussion, not the final proposal for a vote.

@bgamari
Copy link
Author

bgamari commented Jan 30, 2023

@Bodigrim, to my mind the proposal is done and I think the proposed naming is acceptable. I presented the other alternatives to spur discussion but given that there aren't any strong opinions on the matter I think it would be fine to put this to a vote.

@Bodigrim
Copy link
Collaborator

CLC is currently on pause anyway until new members are elected, which will hopefully happen somewhere next week.

@phadej
Copy link

phadej commented Jan 31, 2023

Sorry for bringing more unwelcome news, but I was reading base-4.18.0.0 changelog, and there are few entries mentioning GHC.Conc.Sync:

  • GHC.Conc.Sync.listThreads was added, allowing the user to list the threads (both running and blocked) of the program.
  • GHC.Conc.Sync.labelThreadByteArray# was added, allowing the user to specify a thread label by way of a ByteArray# containing a UTF-8-encoded string. The old GHC.Conc.Sync.labelThread is now implemented in terms of this function.
  • GHC.Conc.Sync.threadLabel was added, allowing the user to query the label of a given ThreadId.

Which are not unlike this issue.


OTOH, these are good news also, as it seems to be the only entries on the base-4.18.0.0 changelog without CLC Proposal, all others have them, except

@Bodigrim
Copy link
Collaborator

Sorry for bringing more unwelcome news, but I was reading base-4.18.0.0 changelog, and there are few entries mentioning GHC.Conc.Sync

Thanks for digging it out, it is not unwelcome at all. We should have done a better job with regards to communication and monitoring last year. Reverting the changes and ramming through a proposal in a week or so left before 9.6 RC will be a farce, not a public scrutiny. Given that GHC.Conc.Sync is a relatively obscure corner I am inclined to think that it is in the public interest to let them be as is, even while I do not enjoy it. Same for GHC.Weak.Finalize.

GHC.Stats is a worse example: not only extending a record is a breaking change, but it is also misattributed to base-4.17: https://ghc.gitlab.haskell.org/ghc/doc/libraries/base-4.18.0.0/GHC-Stats.html#t:GCDetails. This needs to be fixed before base-4.18 released.


Back to the topic, threadIdToInt :: ThreadId -> Word64 looks wrong to me. threadIdToWord64 is certainly better.

@Bodigrim
Copy link
Collaborator

The proposal is to export rts_getThreadId from GHC.Conc.Sync:

foreign import ccall unsafe "rts_getThreadId" getThreadId :: ThreadId# -> CULLong

Strictly speaking, CULLong type here is a mistake, because according to C sources it should be Word64. These types are the same on all platforms GHC supports, but we should take a chance to rectify this as well.

Now, the hardest question of all: naming. It might be suboptimal for a public function of type ThreadId# -> Word64 to be called getThreadId as it is at the moment. After all, it takes ThreadId#, not returns. Here are options so far:

  • threadIdToInt,
  • threadIdToWord64,
  • getThreadId,
  • getThreadNumber,
  • threadIdToWord,
  • getThreadIdentifier,
  • threadId,
  • threadIdId.

Dear CLC members, let's help the proposer to choose a name. This is not a vote, just non-binding opinions. Obviously, if you are against exporting this function under any name, please say so as well.

@chshersh @mixphix @angerman @tomjaguarpaw @parsonsmatt @hasufell.

@hasufell
Copy link
Member

fromThreadId

This way we don't need to rename in case the API breaks with a different type (e.g. another newtype over Word64 or god knows what).

@angerman
Copy link

I like @hasufell's suggestion. I find it's the clearest. ToInt feels certainly wrong. Especially as it does not align with the signature.

@mixphix
Copy link
Collaborator

mixphix commented Feb 16, 2023

I agree on fromThreadId. Prefixing with get feels monadic, and the threadIdToX becomes either redundant or wrong if X changes for some reason.

@Bodigrim
Copy link
Collaborator

Bodigrim commented Feb 17, 2023

@bgamari are you happy with fromThreadId :: ThreadId -> Word64? If you update the proposal, we'll be able to vote.

@Bodigrim Bodigrim added the awaits-MR No GHC MR (https://gitlab.haskell.org/ghc/ghc/-/merge_requests) has been raised yet label Feb 18, 2023
@Bodigrim
Copy link
Collaborator

@bgamari could you please update the proposal?

@bgamari
Copy link
Author

bgamari commented Mar 24, 2023

I have updated the proposal to reflect the fromThreadId name.

@bgamari
Copy link
Author

bgamari commented Mar 24, 2023

One remaining question is whether fromThreadId should also be exported from Control.Concurrent as well since GHC.Conc.Sync is currently a grab-bag of various GHC-specific implementation details.

@Bodigrim
Copy link
Collaborator

To a certain extent fromThreadId :: ThreadId -> Word is a GHC-specific implementation detail, another compiler with another RTS could be doing it differently. If need arises, it can be re-exported from Control.Concurrent later. But I'm personally fine either way.

Unless someone feels strongly that re-exporting fromThreadId from Control.Concurrent is a tangible improvement right now, I'll trigger a vote on the proposal as is soon.

@bgamari
Copy link
Author

bgamari commented Mar 25, 2023

An immediate vote is fine with me.

@Bodigrim
Copy link
Collaborator

Dear CLC members, any non-binding opinions on this?

@chshersh
Copy link
Member

I'm happy with the name of the function, its type and it being exported from GHC.Conc.Sync. I would be fine with reexporting from Control.Concurrent as well. But I personally don't have problems with importing GHC.Conc.Sync for this function, and I don't think it will be used that often by beginners to make imports more beginner-friendly. Besides, the GHC.* import does suggest that this is how GHC represents ThreadId, and its implementation is tied to the GHC internals.

However, the documentation for ThreadId could mention this helpful function regardless of reexport.

@Bodigrim
Copy link
Collaborator

Dear CLC members, let's vote on the proposal to add GHC.Conc.Sync.fromThreadId :: ThreadId -> Word64 as detailed in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/10176/diffs. The motivation is to provide a "blessed" way to convert ThreadId to an integer instead of FFI'ng into RTS headers as people do now with rts_getThreadId (https://hackage-search.serokell.io/?q=rts_getThreadId).

@chshersh @tomjaguarpaw @hasufell @angerman @parsonsmatt @mixphix


+1 from me.

@hasufell
Copy link
Member

+1

3 similar comments
@angerman
Copy link

+1

@chshersh
Copy link
Member

+1

@parsonsmatt
Copy link

+1

@Bodigrim
Copy link
Collaborator

Thanks all, 5 votes out of 7 are enough to approve.

@Bodigrim Bodigrim added approved Approved by CLC vote and removed awaits-MR No GHC MR (https://gitlab.haskell.org/ghc/ghc/-/merge_requests) has been raised yet labels Apr 14, 2023
@Bodigrim Bodigrim added the base-4.19 Implemented in base-4.19 (GHC 9.8) label Jun 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Approved by CLC vote base-4.19 Implemented in base-4.19 (GHC 9.8)
Projects
None yet
Development

No branches or pull requests